ようへいの日々精進XP

よかろうもん

WEB+DB PRESS Vol.116 を読んだ (1) 〜 特集 1: トラブルシューティング (第 2 章バックエンド) && trdsql をちょっと触ってみた〜

tl;dr

WEB+DB PRESS Vol.116 の記事を読んでみたメモです.

gihyo.jp

読みながら気になる単語や内容をマインドマップにまとめていきたいと思います. 今回は「特集 1: トラブルシューティング」の「第 2 章バックエンド」を読みました.

マインドマップ

f:id:inokara:20200426132142p:plain

メモ

憶測するな計測せよ

curlsmtp

SMTP との会話

HTTP プロトコル以外にも対応してるということなので, curlSMTP と会話してみたいと思います.

手元で SMTP サーバーを起動

こちらの記事を参考にさせて頂きました.

Docker を利用します.

$ docker run -d -p 25:25 \
  --name mailserver \
  -e maildomain=example.com \
  -e smtp_user=username:password \
  catatnight/postfix
$ docker ps
CONTAINER ID        IMAGE                COMMAND                  CREATED             STATUS              PORTS                NAMES
367c3f04439a        catatnight/postfix   "/bin/sh -c '/opt/in…"   16 minutes ago      Up 16 minutes       0.0.0.0:25->25/tcp   mailserver

一旦, telnet で会話してみます.

$ telnet localhost 25
Trying ::1...
Connected to localhost.
Escape character is '^]'.
220 example.com ESMTP Postfix (Ubuntu)
HELO example.com
250 example.com
MAIL FROM: from@example.com
250 2.1.0 Ok
RCPT TO: to@example.com
454 4.7.1 <to@example.com>: Relay access denied
QUIT
221 2.0.0 Bye
Connection closed by foreign host.

curl でメールを送信してみる

こちらの記事を参考にさせて頂きました.

以下のようなテキストファイルを用意します. このテキストファイルを test.txt というファイル名で保存します.

To: to@example.com
From: from@example.com
Subject: this is a test

hello world!

以下のように curl コマンドでメールを送信します.

$ curl -sv smtp://localhost:25 --mail-from 'from@example.com' --mail-rcpt 'to@example.com' -u username -T test.txt

以下のように出力されました.

Enter host password for user 'username':
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 25 (#0)
< 220 example.com ESMTP Postfix (Ubuntu)
> EHLO test.txt
< 250-example.com
< 250-PIPELINING
< 250-SIZE 10240000
< 250-VRFY
< 250-ETRN
< 250-STARTTLS
< 250-AUTH PLAIN LOGIN CRAM-MD5 DIGEST-MD5 NTLM
< 250-AUTH=PLAIN LOGIN CRAM-MD5 DIGEST-MD5 NTLM
< 250-ENHANCEDSTATUSCODES
< 250-8BITMIME
< 250 DSN
> AUTH DIGEST-MD5
< 334 bm9uY2U9IjJJZnVhc1JVbnRTdjVpcmFuRXpYY0k1NklPeWFiMXF2YmdrKzdSL2JhMkE9IixyZWFsbT0iZXhhbXBsZS5jb20iLHFvcD0iYXV0aCIsY2hhcnNldD11dGYtOCxhbGdvcml0aG09bWQ1LXNlc3M=
> dXNlcm5hbWU9InVzZXJuYW1lIixyZWFsbT0iZXhhbXBsZS5jb20iLG5vbmNlPSIySWZ1YXNSVW50U3Y1aXJhbkV6WGNJNTZJT3lhYjFxdmJnays3Ui9iYTJBPSIsY25vbmNlPSJlODcwZWFlMDNhOWQ5MGYwZjQyNTQ4OWJlMmNjOGI4YiIsbmM9IjAwMDAwMDAxIixkaWdlc3QtdXJpPSJzbXRwL2V4YW1wbGUuY29tIixyZXNwb25zZT1lZWFhNTliY2ZiNjJkMmUwZWI2MWYzM2JiOGU2MTA1Mixxb3A9YXV0aA==
< 334 cnNwYXV0aD1kMWYxNmI4ODUzZGJkMjRlZTdjZmY0YTE4MjhiZjM3MQ==
>
< 235 2.7.0 Authentication successful
> MAIL FROM:<from@example.com> SIZE=80
< 250 2.1.0 Ok
> RCPT TO:<to@example.com>
< 250 2.1.5 Ok
> DATA
< 354 End data with <CR><LF>.<CR><LF>
} [80 bytes data]
* We are completely uploaded and fine
< 250 2.0.0 Ok: queued as 1448D342D47
* Connection #0 to host localhost left intact

SMTP のやりとりを確認することが出来ました.

trdsql について

ログを SQL ライクに検索出来る

ログを SQL ライクな構文で検索出来る trdsql というツールを初めて知ったので少し触ってみました. 尚, 動作検証環境は以下の通りです.

root@6dc811524b1d:/work# cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 10 (buster)"
NAME="Debian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"
VERSION_CODENAME=buster
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"

root@6dc811524b1d:/work# ruby --version
ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-linux]

root@6dc811524b1d:/work# gem list | grep apache
apache-loggen (0.0.5)

root@6dc811524b1d:/work# ./trdsql_v0.7.5_linux_amd64/trdsql --version
trdsql version v0.7.5

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.14.6
BuildVersion:   18G3020

$ ~/bin/trdsql --version
trdsql version v0.7.5

ログの用意

Apache のログを用意します. Apache のダミーログを用意するには, apache_log_gen がとても便利です.

github.com

以下のように出力しました.

$ apache-loggen --json --limit=5000 sample.log

JSON フォーマットで 5000 件のログを生成して sample.log というファイルを生成しています.

検索

trdsql でログを検索してみたいと思います. まずは, ステータスコード 200 以外のログを抽出してみます.

$ ~/bin/trdsql -ijson -oat "SELECT path,code,count(path) AS count \
  FROM sample.log WHERE code != '200' \
  GROUP BY path, code ORDER BY count DESC"

-ijsonJSON フォーマットのログを読み込むオプション, -oat は ASCII Table 形式で出力するオプションです.

以下のように出力されました.

+------------------------+------+-------+
|          path          | code | count |
+------------------------+------+-------+
| /item/games/2228       |  404 |     4 |
| /item/electronics/2168 |  404 |     3 |
| /item/games/452        |  404 |     3 |
+------------------------+------+-------+

念の為, ログを Linux コマンドを駆使して抽出してみました.

$ grep -v '"code":200' sample.log | jq -r .path | sort | uniq -c | sort -r
   4 /item/games/2228
   3 /item/games/452
   3 /item/electronics/2168

続いて, 接続元の IP アドレス毎にアクセス件数を確認してみます.

$ ~/bin/trdsql -ijson -oat "SELECT host, count(host) AS count \
  FROM sample.log GROUP BY host ORDER BY count DESC LIMIT 20"

以下のような結果となりました.

+-----------------+-------+
|      host       | count |
+-----------------+-------+
| 84.144.85.122   |    11 |
| 28.186.132.148  |    10 |
| 216.93.121.144  |    10 |
| 216.177.205.222 |    10 |
| 208.135.120.209 |    10 |
| 188.123.189.209 |    10 |
| 180.225.208.155 |    10 |
| 124.75.103.212  |    10 |
| 112.69.129.87   |    10 |
| 104.21.41.136   |    10 |
| 100.90.123.168  |    10 |
| 96.132.66.43    |     9 |
| 96.126.37.143   |     9 |
| 92.144.43.39    |     9 |
| 88.162.143.128  |     9 |
| 60.90.182.138   |     9 |
| 40.21.86.73     |     9 |
| 40.141.66.26    |     9 |
| 28.105.160.88   |     9 |
| 24.189.98.124   |     9 |
+-----------------+-------+

おおー. 素晴らしい. SQL でログを直接検索出来るのは SQL が苦手な自分でも頑張りたくなります.

以上

やっぱ, 「憶測するな計測せよ」はトラブルシューティングの鉄板. そして, trdsql に出会えたのは最高でした. これはギョームで使っていこうと思います.