みんな大好きdstatコマンド!
恐らくサーバ運用をされている方なら一度は叩いたことあるのではないでしょうか。
どんなコマンドでもそうですが、自分が今どんな情報を出力して見ているをきちんと理解するのかは非常に重要ですよね
ということで、身近なdstatのコードを眺めてLinux(CentOS)の世界を少しだけ眺めてみたいと思います!
今回tcpオプションから見ていくのは、たまたまお仕事で見ることがあったためです(笑)
dstatコマンドってなに?
vmstatのリッチな感じ
詳細はこちらに素晴らしいまとめが!ありがたや!
dstatの便利なオプションまとめ
ちなみに私は何かが起きたらとりあえずこのオプションでコマンド叩いて眺めています
$ dstat -V
Dstat 0.7.0
(略)
$ dstat -tlcmgdn --socket --tcp --io
----system---- ---load-avg--- ----total-cpu-usage---- ------memory-usage----- ---paging-- -dsk/total- -net/total- ------sockets------ ----tcp-sockets---- --io/total-
date/time | 1m 5m 15m |usr sys idl wai hiq siq| used buff cach free| in out | read writ| recv send|tot tcp udp raw frg|lis act syn tim clo| read writ
25-03 10:04:20| 0 0 0| 1 2 98 0 0 0| 452M 425M 665M 328M| 0 0 | 0 76k| 560B 794B|224 7 12 0 0| 10 2 0 0 0| 0 7.00
25-03 10:04:21| 0 0 0| 0 1 99 0 0 0| 447M 425M 665M 332M| 0 0 | 0 296k| 390B 2078B|224 7 12 0 0| 10 2 0 0 0| 0 44.0
25-03 10:04:22| 0 0 0| 0 1 99 0 0 0| 448M 425M 665M 332M| 0 0 | 0 0 | 60B 664B|224 7 12 0 0| 10 2 0 0 0| 0 0
25-03 10:04:23| 0 0 0| 0 2 98 0 0 0| 454M 425M 665M 326M| 0 0 | 0 0 | 206B 820B|224 7 12 0 0| 10 2 0 0 0| 0 0
25-03 10:04:24| 0 0 0| 0 1 99 0 0 0| 448M 425M 665M 332M| 0 0 | 0 0 | 390B 810B|224 7 12 0 0| 10 2 0 0 0| 0 0
dstat --tcpオプションについて
manから引用
--tcp enable tcp stats (listen, established, syn, time_wait, close)
ふんふん、tcpの状態遷移を表示してくれるのか
出力例
$ dstat --tcp
----tcp-sockets----
lis act syn tim clo
10 2 0 1 0
10 2 0 1 0
あれ?
TCPの状態遷移ってもっといっぱいなかったっけ?
TCPの状態遷移について
詳細はこちらに素晴らしいまとめが!ありがたや!
TCPの状態遷移@Qiita
listen, established, syn, time_wait, close以外は何にカウントしてる?
コードを眺めてみよう!
$ git clone https://github.com/dagwieers/dstat.git
1603 class dstat_tcp(dstat):
1604 def __init__(self):
1605 self.name = 'tcp sockets'
1606 self.nick = ('lis', 'act', 'syn', 'tim', 'clo')
1607 self.vars = ('listen', 'established', 'syn', 'wait', 'close')
1608 self.type = 'd'
1609 self.width = 4
1610 self.scale = 100
1611 self.open('/proc/net/tcp', '/proc/net/tcp6')
1612
1613 def extract(self):
1614 for name in self.vars: self.val[name] = 0
1615 for l in self.splitlines():
1616 if len(l) < 12: continue
1617 ### 01: established, 02: syn_sent, 03: syn_recv, 04: fin_wait1,
1618 ### 05: fin_wait2, 06: time_wait, 07: close, 08: close_wait,
1619 ### 09: last_ack, 0A: listen, 0B: closing
1620 if l[3] in ('0A',): self.val['listen'] += 1
1621 elif l[3] in ('01',): self.val['established'] += 1
1622 elif l[3] in ('02', '03', '09',): self.val['syn'] += 1
1623 elif l[3] in ('06',): self.val['wait'] += 1
1624 elif l[3] in ('04', '05', '07', '08', '0B',): self.val['close'] += 1
ふんふん、どうやら/proc/net/配下のファイルを読んで
closeに複数のステータス状態をマージしてインクリメントしているっぽい!
・・・ところで/proc/net/{tcp,tcp6}ってなんだっけ
/proc/net/tcpってなんだっけ?
どんな情報が入っているのか
$ head -n 3 /proc/net/tcp
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
0: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 12288 1 ffff88007d7eb580 99 0 0 10 -1
これだけじゃよくわからん。。。
ドキュメントを。。。
Linux Kernel.org@proc_net_tcp
ふんふん、まとめるとこんな感じ?
sl | local_address | rem_address | st | tx_queue | rx_queue | tr | tm->when | retrnsmt | uid | timeout | inode | socket reference count | location of socket in memory | retransmit timeout | Predicted tick of soft clock | (ack.quick<<1) | ack.pingpong | sending congestion window |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
項番 | local IP:Port | remote IP:Port | TCP状態 | 送信キュー | 受信キュー | 再送タイマー | タイマーがタイムアウトするまでの時間(jiffies単位) | retrnsmt | uid | timeout | inode | socket reference count | location of socket in memory | retransmit timeout | Predicted tick of soft clock | (ack.quick<<1) | ack.pingpong | |
0 | 00000000:0016 | 00000000:0000 | 0A | 00000000 | 00000000 | 00 | 00000000 | 00000000 | 0 | 0 | 12288 | 1 | ffff88007d7eb580 | 99 | 0 | 0 | 10 | -1 |
jiffiesについてはこの辺りに素晴らしい情報が!
カーネルにおけるタイマー事情 ~第2回 カーネル内の時刻/時間関連サブシステム~
もうちょっと細かい説明は分かり次第追記していきます。。。
inode以降の部分はまだまだお勉強が必要そうです。。。
tcpオプションは/proc/net/tcpのstをカウントしていた!
stカラムの詳細は?
dstatのコードにコメントがあったけど、それじゃちょっとつまらない。。。
💡・・・そうだ、Kernelも見てみよう!(白目
しかし、悲しいかな、私にはCで詳細を読み解く力はありません。。。
ので、コードを落としてcsearchでそれっぽいところだけでも探してみました。
34 #define TCP_ACTION_FIN (1 << 7)
35
36 enum {
37 TCPF_ESTABLISHED = (1 << 1),
38 TCPF_SYN_SENT = (1 << 2),
39 TCPF_SYN_RECV = (1 << 3),
40 TCPF_FIN_WAIT1 = (1 << 4),
41 TCPF_FIN_WAIT2 = (1 << 5),
42 TCPF_TIME_WAIT = (1 << 6),
43 TCPF_CLOSE = (1 << 7),
44 TCPF_CLOSE_WAIT = (1 << 8),
45 TCPF_LAST_ACK = (1 << 9),
46 TCPF_LISTEN = (1 << 10),
47 TCPF_CLOSING = (1 << 11)
48 };
dstatのコメント比較してみると、構造体的にもそれっぽい!
1617 ### 01: established, 02: syn_sent, 03: syn_recv, 04: fin_wait1,
1618 ### 05: fin_wait2, 06: time_wait, 07: close, 08: close_wait,
1619 ### 09: last_ack, 0A: listen, 0B: closing
というわけで、私のC戦闘力が著しく低いことが見事に露呈した悲しい感じですが、
身近なdstatを使ってちょこっとだけLinuxの世界を覗いてみました。
また近いうちに別のオプションについても出来るだけ書いてみようとおもいます