你可能還不知道,現在有一個新工具sysdig,可以用它來排查故障。它被鼓吹是 strace 和 tcpdump 的合體,我認為這是一種炒作。我倒覺得可以把 sysdig 同 SystemTap 和 tcpdump一起比較,因為它的命令語法類似tcpdump,而功能像 SystemTap 一樣強大。
我在本文中會介紹關於 sysdig 的一些基礎知識和很棒的例子,你可以在 sysdig wiki 上找到更為詳細的資訊。然而,即便是 sysdig 的官方文件,也只涉及 sysdig 功能的皮毛而已。
安裝
本文中我們將在 Ubuntu 上使用 apt-get 安裝sysdig。如果你執行的是基於 rpm 的發行版,你可以在wiki上找到通過 yum 安裝的細節。
準備 apt 倉庫
通過 apt 安裝sysdig,我們需要準備好 apt 倉庫,由 sysdig 後面的 Draios 公司來維護。可以執行下面的 curl 命令來完成:
1 2 |
# curl -s https://s3.amazonaws.com/download.draios.com/DRAIOS-GPG-KEY.public | apt-key add - # curl -s -o /etc/apt/sources.list.d/draios.list http://download.draios.com/stable/deb/draios.list |
第一行命令下載 Draios gpg 金鑰並把它加入 apt 金鑰庫。第二行從 Draios 下載 apt 原始檔,並把它放到 /etc/apt/sources.list.d/ 路徑下。
更新 apt 的索引
一旦安裝好原始檔列表和 gpg 金鑰,需要執行 apt-get update 來重新同步 apt 包的索引。
1 |
# apt-get update |
核心標頭檔案包
sysdig 工具需要用到核心標頭檔案包,開始安裝前,需要確認核心標頭檔案包已安裝上。
檢查核心標頭檔案是否安裝
在這個例子中,我使用的系統已經安裝了核心標頭檔案包,你可以使用 dpkg 命令檢視你的系統上是否有安裝。
1 2 3 4 5 |
# dpkg --list | grep header ii linux-generic 3.11.0.12.13 amd64 Complete Generic Linux kernel and headers ii linux-headers-3.11.0-12 3.11.0-12.19 all Header files related to Linux kernel version 3.11.0 ii linux-headers-3.11.0-12-generic 3.11.0-12.19 amd64 Linux kernel headers for version 3.11.0 on 64 bit x86 SMP ii linux-headers-generic 3.11.0.12.13 amd64 Generic Linux kernel headers |
有一點要特別注意,核心標頭檔案包必須和你係統上的核心版本相匹配。從上面的輸出,你可以看到 linux-generic 包的版本號是3.11.0.12,標頭檔案包也是3.11.0.12。如果你有多個核心,你可以通過 uname 命令來確認你正在執行哪個版本。
1 2 |
# uname -r 3.11.0-12-generic |
安裝核心標頭檔案包
你可以用 apt-get 安裝與核心匹配的標頭檔案包。記住,你必須確認核心的版本資訊,可以通過 uname -r 來獲得。
1 |
# apt-get install linux-headers-<kernel version> |
例如
1 |
# apt-get install linux-headers-3.11.0-12-generic |
安裝 sysdig
既然 apt repo 安裝完成,那麼所需的依賴條件都已滿足。下面可以安裝 sysdig 命令了。
1 |
# apt-get install sysdig |
使用 sysdig
基本操作
sysdig 語法和 tcpdump類似,特別是儲存和讀取記錄檔案的時候。與tcpdump 一樣,sysdig 所有的輸出都可以存成一個檔案方便後面閱讀。如果你正在執行一個程式或者遇到一個問題,希望之後再來通過資訊深入挖掘,這個功能就很有幫助。
寫入記錄檔案
語法:
1 |
# sysdig -w <output file> |
例子:
1 |
# sysdig -w tracefile.dump |
像tcpdump一樣,sysdig 命令也可以用 CTRL+C 來停止。
讀取記錄檔案
你一旦寫了一個記錄檔案,就需要用 sysdig 讀取這個檔案,這可以通過 -r 標記來完成。
語法:
1 |
# sysdig -r output file |
例子:
1 2 3 4 5 6 7 8 9 10 11 |
# sysdig -r tracefile.dump 1 23:44:57.964150879 0 <NA> (7) > switch next=6200(sysdig) 2 23:44:57.966700100 0 rsyslogd (358) < read res=414 data=<6>[ 3785.473354] sysdig_probe: starting capture.<6>[ 3785.473523] sysdig_probe: 3 23:44:57.966707800 0 rsyslogd (358) > gettimeofday 4 23:44:57.966708216 0 rsyslogd (358) < gettimeofday 5 23:44:57.966717424 0 rsyslogd (358) > futex addr=13892708 op=133(FUTEX_PRIVATE_FLAG|FUTEX_WAKE_OP) val=1 6 23:44:57.966721656 0 rsyslogd (358) < futex res=1 7 23:44:57.966724081 0 rsyslogd (358) > gettimeofday 8 23:44:57.966724305 0 rsyslogd (358) < gettimeofday 9 23:44:57.966726254 0 rsyslogd (358) > gettimeofday 10 23:44:57.966726456 0 rsyslogd (358) < gettimeofday |
按 ASCII 格式輸出
sysdig 預設按照二進位制儲存檔案,但你可以通過使用-A 標記得到 ASCII 格式的輸出。
語法:
1 |
# sysdig -A |
例子:
1 2 3 |
# sysdig -A > /var/tmp/out.txt # cat /var/tmp/out.txt 1 22:26:15.076829633 0 <NA> (7) > switch next=11920(sysdig) |
上面的例子把輸出重定位到一個文字檔案。如果你想儲存檔案並在一個沒有安裝 sysdig 的系統上檢查資料,就可以這樣做。
sysdig 過濾器
和 tcpdump 很像,sysdig 命令也有過濾器,可以用來過濾輸出,得到特定的資訊 。你可以通過-l 標記列出所有可用的過濾器。
例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# sysdig -l ---------------------- Field Class: fd fd.num the unique number identifying the file descriptor. fd.type type of FD. Can be 'file', 'ipv4', 'ipv6', 'unix', 'pipe', 'e vent', 'signalfd', 'eventpoll', 'inotify' or 'signalfd'. fd.typechar type of FD as a single character. Can be 'f' for file, 4 for IPv4 socket, 6 for IPv6 socket, 'u' for unix socket, p for pi pe, 'e' for eventfd, 's' for signalfd, 'l' for eventpoll, 'i' for inotify, 'o' for uknown. fd.name FD full name. If the fd is a file, this field contains the fu ll path. If the FD is a socket, this field contain the connec tion tuple. <truncated output> |
過濾器例子
抓取特定的程式
你可以使用“proc.name” 過濾器去抓取特定程式的所有 sysdig 事件。下面的例子中,我過濾了所有名字中包含 sshd 的程式。
例子:
1 2 3 4 5 6 7 |
# sysdig -r tracefile.dump proc.name=sshd 530 23:45:02.804469114 0 sshd (917) < select res=1 531 23:45:02.804476093 0 sshd (917) > rt_sigprocmask 532 23:45:02.804478942 0 sshd (917) < rt_sigprocmask 533 23:45:02.804479542 0 sshd (917) > rt_sigprocmask 534 23:45:02.804479767 0 sshd (917) < rt_sigprocmask 535 23:45:02.804487255 0 sshd (917) > read fd=3(<4t>10.0.0.12:55993->162.0.0.80:22) size=16384 |
抓取開啟一個特定檔案的所有程式
fd.name這個過濾器用在過濾一個特定檔名的事件。這樣可以看到有哪些程式來讀取或者寫入特定的檔案或 socket。
例子:
1 2 |
# sysdig fd.name=/dev/log 14 11:13:30.982445884 0 rsyslogd (357) < read res=414 data=<6>[ 582.136312] sysdig_probe: starting capture.<6>[ 582.136472] sysdig_probe: |
抓取開啟一個特定檔案系統的所有程式
你也可以在過濾器中使用比較運算子,例如包含、=、!=、<=、>=、< 和 >。
例子:
1 2 3 4 5 6 7 8 9 10 11 |
# sysdig fd.name contains /etc 8675 11:16:18.424407754 0 apache2 (1287) < open fd=13(<f>/etc/apache2/.htpasswd) name=/etc/apache2/.htpasswd flags=1(O_RDONLY) mode=0 8678 11:16:18.424422599 0 apache2 (1287) > fstat fd=13(<f>/etc/apache2/.htpasswd) 8679 11:16:18.424423601 0 apache2 (1287) < fstat res=0 8680 11:16:18.424427497 0 apache2 (1287) > read fd=13(<f>/etc/apache2/.htpasswd) size=4096 8683 11:16:18.424606422 0 apache2 (1287) < read res=44 data=admin:$apr1$OXXed8Rc$rbXNhN/VqLCP.ojKu1aUN1. 8684 11:16:18.424623679 0 apache2 (1287) > close fd=13(<f>/etc/apache2/.htpasswd) 8685 11:16:18.424625424 0 apache2 (1287) < close res=0 9702 11:16:21.285934861 0 apache2 (1287) < open fd=13(<f>/etc/apache2/.htpasswd) name=/etc/apache2/.htpasswd flags=1(O_RDONLY) mode=0 9703 11:16:21.285936317 0 apache2 (1287) > fstat fd=13(<f>/etc/apache2/.htpasswd) 9704 11:16:21.285937024 0 apache2 (1287) < fstat res=0 |
從上面這些例子,你可以看出過濾器可以用來讀取檔案或者活動的事件流 。
鑿子
前面我把 sysdig 類比 SystemTap 的原因就在於 鑿子(Chisels)。類似 SystemTap 這類工具都有它自己的指令碼語言,可以用來擴充 SystemTap 的功能。在 sysdig 中,它們叫做鑿子,可以用 LUA 這種常見程式語言來編寫。我個人認為選擇使用 LUA 是一個好點子,這可以讓新手很容易擴充 sysdig。
列出可用的鑿子
可以通過 -cl 標記,列出所有可以使用的鑿子。
例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# sysdig -cl Category: CPU Usage ------------------- topprocs_cpu Top processes by CPU usage Category: I/O ------------- echo_fds Print the data read and written by processes. fdbytes_by I/O bytes, aggregated by an arbitrary filter field fdcount_by FD count, aggregated by an arbitrary filter field iobytes Sum of I/O bytes on any type of FD iobytes_file Sum of file I/O bytes stderr Print stderr of processes stdin Print stdin of processes stdout Print stdout of processes <truncated output> |
雖然 sysdig 還很新,但這個列表相當長,而且 sysdig 在 GitHub 上,你可以很容易擴充和貢獻自己的鑿子。
顯示鑿子的資訊
列表命令可以讓你大致瞭解每個鑿子,你還可以通過 -i 標記加鑿子名來獲取更詳細的資訊。
例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# sysdig -i bottlenecks Category: Performance --------------------- bottlenecks Slowest system calls Use the -i flag to get detailed information about a specific chisel Lists the 10 system calls that took the longest to return dur ing the capture interval. Args: (None) |
執行鑿子
你可以通過 -c 標記和指定鑿子名,讓 sysdig 來執行這個鑿子。
例子:
1 2 3 4 |
# sysdig -c topprocs_net Bytes Process ------------------------------ 296B sshd |
帶過濾器執行鑿子
你在執行鑿子時候,仍然可以使用對特定的事件使用過濾器。
抓取一個特定程式的所有網路流量
下面這個例子顯示對 apache2 程式使用 echo_fds 鑿子。
1 2 3 4 5 6 7 8 9 10 11 12 |
# sysdig -A -c echo_fds proc.name=apache2 ------ Read 444B from 127.0.0.1:57793->162.243.109.80:80 GET /wp-admin/install.php HTTP/1.1 Host: 162.243.109.80 Connection: keep-alive Cache-Control: max-age=0 Authorization: Basic YWRtaW46ZUNCM3lyZmRRcg== Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.152 Safari/537.36 Accept-Encoding: gzip,deflate,sdch Accept-Language: en-US,en;q=0.8 |
抓取一個特定 IP 的網路流量交換
我們使用 echo_fds 鑿子和fd.cip 過濾器 ,顯示單獨一個 IP 所有的網路流量。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# sysdig -A -c echo_fds fd.cip=127.0.0.1 ------ Write 1.92KB to 127.0.0.1:58896->162.243.109.80:80 HTTP/1.1 200 OK Date: Thu, 17 Apr 2014 03:11:33 GMT Server: Apache X-Powered-By: PHP/5.5.3-1ubuntu2.3 Vary: Accept-Encoding Content-Encoding: gzip Content-Length: 1698 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: text/html; charset=utf-8 |
打賞支援我翻譯更多好文章,謝謝!
打賞譯者
打賞支援我翻譯更多好文章,謝謝!
任選一種支付方式