第4章 便利な SystemTap スクリプト
/usr/share/systemtap/testsuite/systemtap.examples/ ディレクトリーから利用可能となります。
4.1. ネットワーク
4.1.1. ネットワークのプロファイリング
例4.1 nettop.stp
#! /usr/bin/env stap
global ifxmit, ifrecv
global ifmerged
probe netdev.transmit
{
ifxmit[pid(), dev_name, execname(), uid()] <<< length
}
probe netdev.receive
{
ifrecv[pid(), dev_name, execname(), uid()] <<< length
}
function print_activity()
{
printf("%5s %5s %-7s %7s %7s %7s %7s %-15s\n",
"PID", "UID", "DEV", "XMIT_PK", "RECV_PK",
"XMIT_KB", "RECV_KB", "COMMAND")
foreach ([pid, dev, exec, uid] in ifrecv) {
ifmerged[pid, dev, exec, uid] += @count(ifrecv[pid,dev,exec,uid]);
}
foreach ([pid, dev, exec, uid] in ifxmit) {
ifmerged[pid, dev, exec, uid] += @count(ifxmit[pid,dev,exec,uid]);
}
foreach ([pid, dev, exec, uid] in ifmerged-) {
n_xmit = @count(ifxmit[pid, dev, exec, uid])
n_recv = @count(ifrecv[pid, dev, exec, uid])
printf("%5d %5d %-7s %7d %7d %7d %7d %-15s\n",
pid, uid, dev, n_xmit, n_recv,
n_xmit ? @sum(ifxmit[pid, dev, exec, uid])/1024 : 0,
n_recv ? @sum(ifrecv[pid, dev, exec, uid])/1024 : 0,
exec)
}
print("\n")
delete ifxmit
delete ifrecv
delete ifmerged
}
probe timer.ms(5000), end, error
{
print_activity()
}
print_activity() 関数が以下の式を使用することに注意してください。
n_xmit ? @sum(ifxmit[pid, dev, exec, uid])/1024 : 0 n_recv ? @sum(ifrecv[pid, dev, exec, uid])/1024 : 0
if or else 条件です。2 番目のステートメントは、以下の擬似コードをより簡潔にしたものです。
if n_recv != 0 then @sum(ifrecv[pid, dev, exec, uid])/1024 else 0
PID— 記載されているプロセスの ID。UID— ユーザー ID。ユーザー ID が0の場合は、root ユーザーを指します。DEV— プロセスがデータの送受信に使用したイーサネットデバイス (例:eth0、eth1)。XMIT_PK— プロセスが送信したパケット数。RECV_PK— プロセスが受信したパケット数。XMIT_KB— プロセスが送信したデータ量 (キロバイト単位)。RECV_KB— プロセスが受信したデータ量 (キロバイト単位)。
probe timer.ms(5000) を編集すると、この間隔が変更できます。例4.2「例4.1「nettop.stp」 のサンプル出力」 には、例4.1「nettop.stp」 からの 20 秒間に渡る出力を引用してあります。
例4.2 例4.1「nettop.stp」 のサンプル出力
[...]
PID UID DEV XMIT_PK RECV_PK XMIT_KB RECV_KB COMMAND
0 0 eth0 0 5 0 0 swapper
11178 0 eth0 2 0 0 0 synergyc
PID UID DEV XMIT_PK RECV_PK XMIT_KB RECV_KB COMMAND
2886 4 eth0 79 0 5 0 cups-polld
11362 0 eth0 0 61 0 5 firefox
0 0 eth0 3 32 0 3 swapper
2886 4 lo 4 4 0 0 cups-polld
11178 0 eth0 3 0 0 0 synergyc
PID UID DEV XMIT_PK RECV_PK XMIT_KB RECV_KB COMMAND
0 0 eth0 0 6 0 0 swapper
2886 4 lo 2 2 0 0 cups-polld
11178 0 eth0 3 0 0 0 synergyc
3611 0 eth0 0 1 0 0 Xorg
PID UID DEV XMIT_PK RECV_PK XMIT_KB RECV_KB COMMAND
0 0 eth0 3 42 0 2 swapper
11178 0 eth0 43 1 3 0 synergyc
11362 0 eth0 0 7 0 0 firefox
3897 0 eth0 0 1 0 0 multiload-apple
[...]4.1.2. ネットワークソケットコードで呼び出された関数の追跡
net/socket.c ファイルから呼び出された関数を追跡する方法を説明します。このタスクでは、各プロセスがカーネルレベルでネットワークと対話する様子が詳細に分かります。
例4.3 socket-trace.stp
#!/usr/bin/stap
probe kernel.function("*@net/socket.c").call {
printf ("%s -> %s\n", thread_indent(1), probefunc())
}
probe kernel.function("*@net/socket.c").return {
printf ("%s <- %s\n", thread_indent(-1), probefunc())
}
thread_indent() が機能する様子の説明に使用した SystemTap 関数 の 例3.6「thread_indent.stp」 と同じ ものです。
例4.4 例4.3「socket-trace.stp」 のサンプル出力
[...] 0 Xorg(3611): -> sock_poll 3 Xorg(3611): <- sock_poll 0 Xorg(3611): -> sock_poll 3 Xorg(3611): <- sock_poll 0 gnome-terminal(11106): -> sock_poll 5 gnome-terminal(11106): <- sock_poll 0 scim-bridge(3883): -> sock_poll 3 scim-bridge(3883): <- sock_poll 0 scim-bridge(3883): -> sys_socketcall 4 scim-bridge(3883): -> sys_recv 8 scim-bridge(3883): -> sys_recvfrom 12 scim-bridge(3883):-> sock_from_file 16 scim-bridge(3883):<- sock_from_file 20 scim-bridge(3883):-> sock_recvmsg 24 scim-bridge(3883):<- sock_recvmsg 28 scim-bridge(3883): <- sys_recvfrom 31 scim-bridge(3883): <- sys_recv 35 scim-bridge(3883): <- sys_socketcall [...]
thread_indent() が提供するこのスクリプトの出力に関する詳細情報は、SystemTap 関数 例3.6「thread_indent.stp」 を参照してください。
4.1.3. 着信 TCP 接続の監視
例4.5 tcp_connections.stp
#! /usr/bin/env stap
probe begin {
printf("%6s %16s %6s %6s %16s\n",
"UID", "CMD", "PID", "PORT", "IP_SOURCE")
}
probe kernel.function("tcp_accept").return?,
kernel.function("inet_csk_accept").return? {
sock = $return
if (sock != 0)
printf("%6d %16s %6d %6d %16s\n", uid(), execname(), pid(),
inet_get_local_port(sock), inet_get_ip_source(sock))
}
- 現行の
UID CMD- 接続を受け付けるコマンド- そのコマンドの
PID - 接続が使用するポート
- TCP 接続の発信元となる IP アドレス
例4.6 例4.5「tcp_connections.stp」 のサンプル出力
UID CMD PID PORT IP_SOURCE 0 sshd 3165 22 10.64.0.227 0 sshd 3165 22 10.64.0.227
4.1.4. カーネルでのネットワークパケットドロップの監視
kernel.trace("kfree_skb") を含むものもあり、これは簡単にパケットが破棄された場所を追跡します。例4.7「dropwatch.stp」 では、kernel.trace("kfree_skb") を使用して、パケットの破棄を追跡します。このスクリプトは、パケットが破棄された場所を 5 秒ごとに要約します。
例4.7 dropwatch.stp
#!/usr/bin/stap
############################################################
# Dropwatch.stp
# Author: Neil Horman <nhorman@redhat.com>
# An example script to mimic the behavior of the dropwatch utility
# http://fedorahosted.org/dropwatch
############################################################
# Array to hold the list of drop points we find
global locations
# Note when we turn the monitor on and off
probe begin { printf("Monitoring for dropped packets\n") }
probe end { printf("Stopping dropped packet monitor\n") }
# increment a drop counter for every location we drop at
probe kernel.trace("kfree_skb") { locations[$location] <<< 1 }
# Every 5 seconds report our drop locations
probe timer.sec(5)
{
printf("\n")
foreach (l in locations-) {
printf("%d packets dropped at location %p\n",
@count(locations[l]), l)
}
delete locations
}
kernel.trace("kfree_skb") は、カーネル内でネットワークパケットがドロップした場所を追跡します。kernel.trace("kfree_skb") には、解放されているバッファーへのポインター ($skb) と解放されているバッファーのカーネルコード内での場所 ($location) という 2 つの引数があります。
例4.8 例4.7「dropwatch.stp」 のサンプル出力
Monitoring for dropped packets 51 packets dropped at location 0xffffffff8024cd0f 2 packets dropped at location 0xffffffff8044b472 51 packets dropped at location 0xffffffff8024cd0f 1 packets dropped at location 0xffffffff8044b472 97 packets dropped at location 0xffffffff8024cd0f 1 packets dropped at location 0xffffffff8044b472 Stopping dropped packet monitor
/boot/System.map-$(uname -r) ファイルを確認します。このファイルには、各関数の開始アドレスが記載されており、例4.8「例4.7「dropwatch.stp」 のサンプル出力」 の出力のアドレスを特定の関数名にマップできます。以下の /boot/System.map-$(uname -r) ファイルの抜粋を使用して、アドレス 0xffffffff8024cd0f を関数 unix_stream_recvmsg に、アドレス 0xffffffff8044b472 を関数 arp_rcv にマッピングします。
[...] ffffffff8024c5cd T unlock_new_inode ffffffff8024c5da t unix_stream_sendmsg ffffffff8024c920 t unix_stream_recvmsg ffffffff8024cea1 t udp_v4_lookup_longway [...] ffffffff8044addc t arp_process ffffffff8044b360 t arp_rcv ffffffff8044b487 t parp_redo ffffffff8044b48c t arp_solicit [...]

Where did the comment section go?
Red Hat's documentation publication system recently went through an upgrade to enable speedier, more mobile-friendly content. We decided to re-evaluate our commenting platform to ensure that it meets your expectations and serves as an optimal feedback mechanism. During this redesign, we invite your input on providing feedback on Red Hat documentation via the discussion platform.