OSXでもstraceしたい?よろしい、ならばdtrussだ
strace便利ですよね。最近もnginxがどのファイル開いてるのか調べるのに使いました。ただ、OSXだとそれに準ずるコマンドってないのかなーと勝手に諦めていたのですが、ありましたね。
dtruss
straceと同じように sudo dtruss -p プロセスID
でシステムコールを確認できる。
例えば、nginxで確認してみよう。
$ ps -ef | grep nginx 501 31223 1 0 6:22PM ?? 0:00.00 nginx: master process nginx 501 31224 31223 0 6:22PM ?? 0:00.00 nginx: worker process 501 31935 31725 0 8:07PM ttys005 0:00.00 grep nginx
ワーカーを見れば良いので、 31224
にアタッチしてみよう。
$ sudo dtruss -p 31224
おもむろにWebページにアクセスしてみる。
SYSCALL(args) = return kevent(0x8, 0x7F91DD005C00, 0x1) = 1 0 recvfrom(0x3, 0x7F91DD005400, 0x400) = 469 0 stat64("/usr/local/Cellar/nginx/1.6.2/html/index.html\0", 0x7FFF5DEEF148, 0x400) = 0 0 open("/usr/local/Cellar/nginx/1.6.2/html/index.html\0", 0x4, 0x0) = 10 0 fstat64(0xA, 0x7FFF5DEEEF08, 0x0) = 0 0 writev(0x3, 0x7FFF5DEEE9D0, 0x1) = 179 0 write(0x4, "127.0.0.1 - - [31/Dec/2014:20:08:35 +0900] \"GET / HTTP/1.1\" 304 0 \"-\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36\"\n\0", 0xC1) = 193 0 close(0xA) = 0 0 access("/etc/localtime\0", 0x4, 0x0) = 0 0 open_nocancel("/etc/localtime\0", 0x0, 0x0) = 9 0 fstat64(0x9, 0x7FFF5DEEBFC0, 0x0) = 0 0 read_nocancel(0x9, "TZif\0", 0x2A64) = 126 0 close_nocancel(0x9) = 0 0 accept(0x6, 0x7FFF5DEEF430, 0x7FFF5DEEF42C) = 9 0
標準エラーを標準出力にリダイレクトすればgrepもできるので、ここらへんもstraceと同じですね。
$ sudo dtruss -p 31224 2>&1 | grep open open_nocancel("/etc/localtime\0", 0x0, 0x0) = 10 0 open("/usr/local/Cellar/nginx/1.6.2/html/index.html\0", 0x4, 0x0) = 10 0
ちなみに、Homebrewでインストールしたnginxの何が何だか分からない問題
この検証にあたり、適当なプロセスとしてnginx動かそうと思いました。で、Homebrewでインストールしてみたのですが、どのポートで動いてるかとかぜんぜんよくわからなかったので調べてみましたのメモ(lsofの使い方いつも忘れるのだった)。
ちなみに、起動は単に nginx
と打つだけで良い。
lsofはプロセス名で検索することができるので、今回はnginxを指定して調べる。この場合、-c
オプションを使用する。さらに、-P
オプションを使用することでポート番号を生のまま(数値で)表示するオプションを追加している。
$ lsof -c nginx -P | grep LISTEN nginx 32055 sugamasao 6u IPv4 0xed732b31079edf33 0t0 TCP *:8080 (LISTEN) nginx 32056 sugamasao 6u IPv4 0xed732b31079edf33 0t0 TCP *:8080 (LISTEN)
こうすると、どうやらLISTENしているのは8080ポートらしいということがわかる。
-P
を指定しない場合、こんな感じになってService Nameとやらの値に変換するようになっている(生データをデフォルトにしてほしいなぁ)。
$ lsof -c nginx | grep LISTEN nginx 32055 sugamasao 6u IPv4 0xed732b31079edf33 0t0 TCP *:http-alt (LISTEN) nginx 32056 sugamasao 6u IPv4 0xed732b31079edf33 0t0 TCP *:http-alt (LISTEN)
っていうか、まともにlsof
の結果見るとオープンしてるファイルとかもわかるし結構良いですね、、、。
オマケ
Homebrewでインストールされたnginxが使うconfの場所がパッとわからなくてこんな感じで確認しました(こういう使い方もできるよ、ということで一つ)。
masterプロセス、あるいはプロセス名自体でdtrussでアタッチして、nginx -s reload
で設定ファイルを読み直すことで、どこのファイルを参照しているかを確認できた。
$ sudo dtruss -n nginx 2>&1 | grep conf
こうしてから別ターミナルで nginx -s reload
するとこんな感じのログが表示されていた。
32880/0x641a4: stat64("/usr/lib/system/libsystem_configuration.dylib\0", 0x7FFF54E3E9F8, 0x2) = 0 0 32055/0x6168e: open("/usr/local/etc/nginx/nginx.conf\0", 0x0, 0x0) = 4 0 32880/0x641a4: read_nocancel(0x4, "#\n# OpenSSL example configuration file.\n# This is mostly being used for generation of certificate requests.\n#\n\n# This definition stops the following lines choking if HOME isn't\n# defined.\nHOME\t\t\t= .\nRANDFILE\t\t= $ENV::HOME/.rnd\n\n# Extra OBJECT IDENTIFIER in", 0x1000) = 4096 0 32880/0x641a4: open("/usr/local/etc/nginx/nginx.conf\0", 0x0, 0x0) = 4 0
内容を確認してみると、どうやら /usr/local/etc/nginx/nginx.conf
っぽいなってのがわかった。便利〜〜