core dumpについて

php-fpmのログで下記のようなSIGSEGVのエラーがでており、原因を調査する場合にcore dumpという方法があるようなので試してみました。

1
WARNING: [pool www] child 17248 exited on signal 11 (SIGSEGV)

検証環境

CentOS8

core dumpとは

システムが異常終了した場合に、その時点のメモリの内容を記録したcoreファイルを吐き出すことを指すようです。

coreファイルの出力先を確認

1
2
$ cat /proc/sys/kernel/core_pattern
core

coreとなっている場合、
プロセスの作業ディレクトリに作成されます。
プロセスの作業ディレクトリは、
ls -l /proc/{プロセスID}/cwd のリンク先になります。
プロセスが終了すると /proc/{プロセスID} のディレクトリは無くなるので、
確認する場合はプロセスが生きている間に確認する必要があります。
プロセスを生きている間に確認することが難しい場合は、
/proc/sys/kernel/core_patternに適当なディレクトリを作成することでcoreの出力先を指定できます。
osを再起動すると元の設定にもどります。

1
echo '/tmp/core-%e-%p' > /proc/sys/kernel/core_pattern

%eは、プログラム名。%pはプロセスIDとして置き換わります。

CentOS8の場合

1
2
$ cat /proc/sys/kernel/core_pattern
|/usr/lib/systemd/systemd-coredump %P %u %g %s %t %c %h %e

となっており、パイブでわたされた、/usr/lib/systemd/systemd-coredumpが
/var/lib/systemd/coredumpのディレクトリ直下にコアダンプが出力されるようになっていました。
また、coredumpctlでcoreの情報を見たりできます。

最近作成されたcoreの一覧を表示。

1
2
3
$ coredumpctl list
TIME PID UID GID SIG COREFILE EXE
Sun 2020-12-06 22:29:22 JST 3252 1000 1000 11 present /usr/bin/bash

coredumpctl info に pidを指定して情報を見る。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ coredumpctl info 3252
PID: 3252 (segv.sh)
UID: 1000 (unamu)
GID: 1000 (unamu)
Signal: 11 (SEGV)
Timestamp: Sun 2020-12-06 22:29:21 JST (6min ago)
Command Line: /bin/bash ./segv.sh
Executable: /usr/bin/bash
Control Group: /user.slice/user-1000.slice/user@1000.service/gnome-terminal-server.service
Unit: user@1000.service
User Unit: gnome-terminal-server.service
Slice: user-1000.slice
Owner UID: 1000 (unamu)
Boot ID: 35a2b597dc5a4a6ebe37fd3a7e97bd73
Machine ID: c4f822f021d5433ab143f054bca5b672
Hostname: localhost.localdomain
Storage: /var/lib/systemd/coredump/core.segv\x2esh.1000.35a2b597dc5a4a6ebe37fd3a7e97bd73.3252.1607261361000000.lz4
Message: Process 3252 (segv.sh) of user 1000 dumped core.

Stack trace of thread 3252:
#0 0x00007fe849946d79 _int_malloc (libc.so.6)
#1 0x00007fe84994850e malloc (libc.so.6)
#2 0x00005625a34934c2 xmalloc (bash)

coreファイルのファイルサイズの変更

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ cat /proc/self/limits
Limit Soft Limit Hard Limit Units
Max cpu time unlimited unlimited seconds
Max file size unlimited unlimited bytes
Max data size unlimited unlimited bytes
Max stack size 8388608 unlimited bytes
Max core file size unlimited unlimited bytes
Max resident set unlimited unlimited bytes
Max processes 3140 3140 processes
Max open files 1024 262144 files
Max locked memory 65536 65536 bytes
Max address space unlimited unlimited bytes
Max file locks unlimited unlimited locks
Max pending signals 3140 3140 signals
Max msgqueue size 819200 819200 bytes
Max nice priority 0 0
Max realtime priority 0 0
Max realtime timeout unlimited unlimited us

の Max core file size の項目がCoreファイルサイズの設定になります。
softlimitが0だとcoreファイルが作成されません。

unlimitedに設定すると上限なしで作成してくれます。

1
$ ulimit -c unlimited

OSを再起動すると元の設定値に戻ります。

SIGSEGVエラーを出して、coreファイルが作成されている確認する

下記のシェルスクリプトを実行して、SIGSEGVエラーを出す。

segv.sh

1
2
3
4
5
#!/bin/bash
function func {
func
}
func
1
2
3
4
# ./segv.sh 
Segmentation fault (コアダンプ)
# ls /tmp
core-segv.sh-41856

(コアダンプ)と表示されて出力を指定した先にcoreファイルが作成されています。

coreファイルの中身を確認

gdb 実行プログラミング coreファイル でgdbでデバックできます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# gdb /bin/bash /tmp/core-segv.sh-41856

GNU gdb (GDB) Red Hat Enterprise Linux 8.2-11.el8
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from /bin/bash...Reading symbols from .gnu_debugdata for /usr/bin/bash...(no debugging symbols found)...done.
(no debugging symbols found)...done.

warning: core file may not match specified executable file.
[New LWP 41856]

warning: Loadable section ".note.gnu.property" outside of ELF segments
Core was generated by `/bin/bash ./segv.sh'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x000055b592ffb6db in expand_word_list_internal ()
Missing separate debuginfos, use: yum debuginfo-install bash-4.4.19-10.el8.x86_64
(gdb)

gdbの対話モードになったら bt or backtrackでコアダンプされる前の状態をさかのぼって原因を調査できます。

1
2
3
4
5
6
7
8
9
10
11
(gdb) bt
#0 0x000055b592ffb6db in expand_word_list_internal ()
#1 0x000055b592fd2fa7 in execute_simple_command ()
#2 0x000055b592fd51a6 in execute_command_internal ()
#3 0x000055b592fd4ab5 in execute_command_internal ()
#4 0x000055b592fd7a79 in execute_function.isra ()
#5 0x000055b592fd4124 in execute_simple_command ()
#6 0x000055b592fd51a6 in execute_command_internal ()
#7 0x000055b592fd4ab5 in execute_command_internal ()
#8 0x000055b592fd7a79 in execute_function.isra ()
#9 0x000055b592fd4124 in execute_simple_command ()

参考url

https://www2.filewo.net/wordpress/2019/12/16/centos%E3%81%A7%E3%81%AF%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88%E3%81%A7%E3%82%B3%E3%82%A2%E3%83%80%E3%83%B3%E3%83%97%E3%81%8C%E5%90%90%E3%81%8B%E3%82%8C%E3%81%AA%E3%81%84%E3%81%AE%E3%81%A7/

https://rabbitfoot141.hatenablog.com/entry/2016/11/14/153101

https://rheb.hatenablog.com/entry/systemd-coredump

https://qiita.com/suzutsuki0220/items/aa84d7e2e8f37e867f3d

https://qiita.com/rarul/items/d33b664c8414f065e65e

php-fpm

https://www.bit-hive.com/articles/20190206

AWS EKS にnginxのPodをデプロイしてブラウザからアクセスする

Docker/Kubernetes実践コンテナ開発入門の本を読んでいて5.10.1のIngressを通じたアクセスをAmazon EKSで行う場合はどのようになるのか調べました。

利用しているdocker image

gihyodocker/echo : Hollo Docker!!と表示するwebサーバー
gihyodocker/nginx-proxy : echoに対してリバースプロキシする

手順

ReplicaSet

同じ仕様のPodを複数作成する

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: echo-summer
labels:
app: echo
release: summer
spec:
replicas: 2
selector:
matchLabels:
app: echo
release: summer
template:
metadata:
labels:
app: echo
release: summer
spec:
containers:
- name: nginx
image: gihyodocker/nginx:latest
env:
- name: BACKEND_HOST
value: localhost:8080
ports:
- containerPort: 80
- name: echo
image: gihyodocker/echo:latest
ports:
- containerPort: 8080

Service

Podの集合に対して、アクセス経路を作成する。typeをNodePortにすることでグローバルなポートを開ける。OSI参照モデルのレイヤー4までしか扱えない。

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: v1
kind: Service
metadata:
name: "echo"
spec:
type: NodePort
selector:
app: echo
release: summer
ports:
- port: 80
targetPort: 80
protocol: TCP

Ingress

ServiceのKudernetesクラスタ外への公開。
VirtualHostやパスベースでのHTTP、HTTPSベースでのルーティングが可能。
Ingressが作成されると、EKSのALB Ingress ControllerがALBと必要なAWSサポートリソースを作成してくれる。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: "echo"
annotations:
kubernetes.io/ingress.class: alb # Ingress が ALB Ingress Controllerを使用することを設定
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip # Serviceでアクセス経路が作成されたPodにトラフィックをルーティングすることを設定
labels:
app: echo
spec:
rules:
- http:
paths:
- path: /*
backend:
serviceName: "echo"
servicePort: 80

AWS EKS にてno endpoints available for service kubernetes-dashboardのエラー対応

エラーの出た場面

AWSのチュートリアル: Kubernetes ダッシュボード (ウェブ UI) のデプロイをやっている時に、
「ウェブブラウザで以下のリンクを開いて、ダッシュボードエンドポイントにアクセスします。」という段階で下記urlにアクセスすると
http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/#!/login

下記のエラーが画面に表示されダッシュボードエンドポイントにアクセスできなかった。

1
2
3
4
5
6
7
8
9
{
kind: "Status",
apiVersion: "v1",
metadata: { },
status: "Failure",
message: "no endpoints available for service "kubernetes-dashboard"",
reason: "ServiceUnavailable",
code: 503
}

対応方法

下記のコマンドを打って、Namespace kubernetes-dashboard を対象とするFargateプロファイルを追加で作成する。

1
2
3
4
eksctl create fargateprofile \
--name fp-kubernetes-dashboard \
--namespace kubernetes-dashboard \
--cluster {クラスター名}

エラーの理由

https://dev.classmethod.jp/articles/fargate-for-eks-tutorial-kubernetes-dashboard/#toc-4
の「「Fargate for EKS」の場合に必要な追加手順」項目を参照

python moduleのimport fromのルートとなる起点を指定したい

実行スクリプトのディレクトリ階層に関係なくfrom importをさせたい

pythonを実行するスクリプトのディレクトリ階層によってfrom importが失敗することがあります。
実行するスクリプトのディレクトリ階層の位置に関係なくfrom importをできるようにする方法を調べました。

このようなディレクトリ構成で普段は、python main.pyからitem_service.py item.py が呼び出され実行される内容だとします。

1
2
3
4
5
├── main.py
├── models
│   └── item.py
└──services
   └── item_service.py

下記のようにitem_service.pyはmain.pyをルートとしてmodels/item.pyをfrom importしています。

1
2
3
4
5
6
7
8
9
10
item_service.py

from models.item import Item

class ItemServiceModel:
def search():
...

if __name__ == '__main__':
ItemServiceModel.search()

この場合に python item_service.py をすると
ModuleNotFoundError: No module named ‘models’
のようなエラーが出てimportに失敗します。

なぜ失敗するか

https://docs.python.org/ja/3/tutorial/modules.html
html#the-module-search-path
公式ドキュメントによると、「入力されたスクリプトのあるディレクトリ」がモジュールの探索パスになるということです。
python main.pyでは成功し、python item_service.pyでは失敗するようになることの理解はできました。

入力されたスクリプトのあるディレクトリ構成位置に関係なくfrom importさせたい

先程の公式ドキュメントの同じところに
「PYTHONPATH (ディレクトリ名のリスト。シェル変数の PATH と同じ構文)。」がモジュールの探索パス(import from の起点ルート)になると書いています。
なので、.zshrc や .bshrc に

1
export PYTHONPATH=$PYTHONPATH:{main.pyのあるディレクトリの絶対パス}

とすれば、python item_service.pyでもfrom importが成功するようになりました。

python リスト内の*について

1
2
3
4
5
6
7
8
9
10
def test(x):
return x * 2


a = [[3,2,1],[5,4,6],[5,4,6]]
a = [*map(lambda x: test(x), a)]
print(a)

# print出力
[[3, 2, 1, 3, 2, 1], [5, 4, 6, 5, 4, 6], [5, 4, 6, 5, 4, 6]]

このようなコードがあって、[*map(の部分が何をしているのか分からなかったので調べました。

結論

map()の返り値のリストを引数展開して、リストを定義している。

詳細

リストの前に*をつけると引数展開される

1
2
3
print(*[1, 2, 3])
# print出力
1 2 3

参考url

http://pixelbeat.jp/variable_length_arguments_and_argument_unpacking/

他の [ ]系 の変則的な書き方

Numpy Boolean Index

Numpy arrayのIndexにBooleanのリストを渡すと、リストのTrueの位置と一致する値だけにできる。

1
2
3
4
5
6
import numpy as np
test = np.array([1000, 2000, None])
print(test[[False, True, True]])

# print出力
[2000 None]

参考url

https://qiita.com/junjis0203/items/4136f9ae4f07c452ceb6#boolean-index%E3%81%A8%E5%80%A4%E8%A8%AD%E5%AE%9A

コマンドラインインターフェイスのオプションについて

コマンドラインでオプションの引数を指定する時に、半角スペース=を利用する違いについて気になったので調べました。

調査結果

オプションの引数が省略できる場合だと半角スペースが、オプション引数を省略した形かコマンドの引数か曖昧なので=の指定が必要。

詳細内容

コマンドラインアプリケーションごとに違いはありますので grep を基準にします。

まずファイルを作成します。

1
2
3
4
5
6
7
cat > test.txt
test
hoge
poyo
poke
111
control+d

man grep をすると、–after-context=num でnum行分を一致した行以降も表示しれくれるとなっています。

1
2
-A num, --after-context=num
Print num lines of trailing context after each match. See also the -B and -C options.
1
2
3
4
5
~/Desktop ❯❯❯ grep test test.txt --after-context=3
test
hoge
poyo
poke
1
2
3
4
5
~/Desktop ❯❯❯ grep test test.txt --after-context 3
test
hoge
poyo
poke

–after-context=num 、–after-contextnum のどちらでも受け付けてくれます。

man grep をすると、–colour=never で一致した箇所の色付けを消してくれるとなっています。[when]になっているのでオプションの引数は省略できます。

1
2
3
--colour=[when, --color=[when]]
Mark up the matching text with the expression stored in GREP_COLOR environment variable. The possible
values of when can be `never', `always' or `auto'.
1
2
~/Desktop ❯❯❯ grep test test.txt --colour=never
test
1
2
3
~/Desktop ❯❯❯ grep test test.txt --colour never
test.txt:test
grep: never: No such file or directory
1
2
~/Desktop ❯❯❯ grep test --colour test.txt
test

–colour=never は受け付けてくれますが、–colournever はneverがオプションの引数とは認識されずに検索対象のファイル名と認識されました。
確かにオプションの引数が省略できる場合だとそれが、オプションの引数かコマンドの引数か曖昧なので=の指定が必要なことは納得できますね。

参考url

http://docopt.org/ : -o --option の項目
https://qiita.com/rubytomato@github/items/2ee2fd4127eadc1f1193
https://qiita.com/aosho235/items/0f2b73d08eb645c05208

This version of ChromeDriver only supports Chrome version {vesion番号}

エラー This version of ChromeDriver only supports Chrome version 〇〇

SeleniumのWebdriverでChromeを動かしているとThis version of ChromeDriver only supports Chrome version 81とエラーメッセージが表示されました。
chromeのバージョンが自動アップデートされて、webdriverとchromeのバージョンが合わなくなったので表示されたようです。
ですので普段利用するchromeとは別に、seleniumで利用するchromeをインストールしてchromeの自動アップデートを無効にする方法を調べたのですが、個別にアップデートを抑制する方法が見つからず。

ChromiunだとChromeと同じ機能で自動アップデートされない

そんな時に、ChromiumだとChromeとほぼ同じ機能で自動アップデートされないという情報を見つけたので、
Webdriverのversionに対応する、Chromiumをダウンロードして解決しました。

Chromiumの過去バージョンのダウンロードurl

https://chromium.woolyss.com/

GoogleIME変換候補登録

GoogleIMEで「餘根津」という旧字体を含んでいたり特殊な名字を「よねず」から変換しようとしても
候補には「米津」とか「米酢」しかでてこないと思います。
それがよく利用する単語なのに変換ででてこないと面倒ですよね。
そんな時の解決方法としてGoogleIME単語登録があります。
変換候補の単語を登録すると、変換候補に出てくるようになります。

CQRSとマテリアライズドビュー

検索の一覧ページでパフォーマンスが問題になることがありますが、
マテリアライズドビューを利用することでパフォーマンス改善ができます。
mysqlではマテリアライズドビューの機能が無いので、
マテリアライズドビューのようなSQL結果を保存するテーブルを作成し、CQRSで更新をおこない利用することでパフォーマンスを改善することができます。

(例)SNSでユーザーに多くの投稿があって最新の投稿内容について検索内容が一致するユーザーを一覧で表示する場合に、
マテリアライズドビューをユーザーと最新の投稿の中間テーブルとすると
下記のような最新の投稿を特定するクエリが必要なくなることでパフォーマンス改善になる。

1
left join posts as p2 on posts.created_at < p2.created_at where p2.id is null

CQRS マテリアライズドビュー 更新フロー図
CQRSとマテリアライズドビューの更新フロー図

参考url

https://slideship.com/users/@miyake/presentations/2018/04/5JgW9hp3kHDDZi6zzDRxbm/?p=8
http://nippondanji.blogspot.com/2015/06/rdb.html
https://blog.spacemarket.com/code/room-search-speed/
https://docs.microsoft.com/ja-jp/azure/architecture/patterns/materialized-view
http://qcontokyo.com/data_2016/pdf/B-2_2_JunichiKato.pdf

https://docs.microsoft.com/ja-jp/azure/architecture/patterns/materialized-view

Laravel で参考のコードを書いてみました。

https://github.com/unamu1229/sampleapp/commit/948a6a6809ecf421629ddf18ca54bef44195e94c

処理の流れ

CommandSelectionエンティティ(コマンド用エンティティ)が CommandSelectionRepositoryリポジトリ(コマンド用リポジトリ)で永続化される

CommandSelectionRepositoryリポジトリがイベントを発生させる(新規作成時:PushCommandSelection 更新時:PutCommandSelection)
※ドメインイベントではないので、リポジトリでイベントを発生させてよいのではないかと思いました。
識別子からクエリ用のエンティティを作成する時も永続化されてからでなければ、最新の状態をとってこれないこともありますし。

リスナーでイベントを受ける(イベントPushCommandSelectionの場合、PushQuerySelection。イベントPutCommandSelectionの場合、PutQuerySelection。)

リスナーがQuerySelectionエンティティ(クエリ用のエンティティ)を作成し、QuerySelectionRepositoryリポジトリ(クエリ用リポジトリ)でマテリアライズドビュー的な永続化を行う。

amazonアフェリエイト 知り合いのリンクを通して購入すると知り合いは紹介料を貰えるのか?

推測:貰えるのではないか? → 結果:貰えません

アマゾンアフェリエイトの利用規約では、自己購入は禁止されていることは自明なのですが、知人からアフェリエイト購入した時に知人に紹介料金がつくことは禁止されていなさそうです。

Amazonアソシエイト・プログラム運営規約

https://affiliate.amazon.co.jp/help/operating/agreement

運営規約の紹介料の項目を見る限り、紹介料を支払いしない条件について知人や家族のために自己購入した場合は紹介料の発生はしないと明記されていますが、知人のリンクを通して購入することに関しては触れられていません。

乙自身、友人、親類その他の関係者のため乙が特別リンク経由で購入した商品など、乙によりまたは乙を代理して、特別リンク経由で購入された商品(例えば、個人的注文、乙自身の使用のための注文および他の個人もしくは企業のためまたはこれらを代理して、乙により発注された注文)。

補足

「乙」は、加入申込者を意味します。

結果

amazonから下記のメールが来てアフェリエイトアカウントが削除されました。
知人からアフェリエイト購入してあげることは規約違反になりました。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
いつもAmazon アソシエイト・プログラムをご利用いただき、誠にありがとうございます。

本日付で、お客様のアソシエイト・プログラムアカウントを閉鎖させていただきました。

お客様のアカウントが閉鎖となった理由:
Amazonアソシエイト・プログラムの継続的監視の一環として、当社はお客様のアカウントを再調査しました。
調査により、当社は、お客様が以下に記載の運営規約を遵守していないと判断しました。

Amazonアソシエイト・プログラム運営規約: <https://affiliate.amazon.co.jp/help/operating/agreement>

違反には以下が含まれます:

-貴殿のサイトの特別リンク経由で行われた購入は、個人的な使用、再販、商業的使用、または貴殿の友人、親戚、従業員、請負業者、ビジネス関係者によるものです。

お客様にご対応いただきたい内容:
お客様のサイト内にあるAmazonマークの使用を中止し、Amazonサイトへのすべてのリンクを速やかに削除しなければなりません。

運営規約違反と判断致しましたので、閉鎖されたアカウントの再開、および該当のアカウントについての紹介料の支払いは行われません。また、Amazonは、その裁量で予告なく、ご利用中の別アカウントまたは今後作成されるアカウントを閉鎖し、紹介料の支払いを停止する権利を留保します。

なお、限定的ではありますが、本閉鎖については不服申立が可能である場合がございます。詳細については、ここに記載の「不服申立」のヘルプを参照してください。<https://affiliate.amazon.co.jp/help/node/topic/GACDBRFKVDTXSPTH>.

Amazon.co.jp カスタマーサービス アソシエイト・プログラムスタッフ