運維命令系統之 strace

2021-09-29 15:24:32 字數 4411 閱讀 3731

strace是什麼?

按照strace官網的描述, strace是乙個可用於診斷、除錯和教學的linux使用者空間***。我們用它來監控使用者空間程序和核心的互動,比如系統呼叫、訊號傳遞、程序狀態變更等。

linux核心目前有300多個系統呼叫,詳細的列表可以通過syscalls手冊頁檢視。這些系統呼叫主要分為幾類:

檔案和裝置訪問類 比如open/close/read/write/chmod等

程序管理類 fork/clone/execve/exit/getpid等

訊號類 signal/sigaction/kill 等

記憶體管理 brk/mmap/mlock等

程序間通訊ipc shmget/semget * 訊號量,共享記憶體,訊息佇列等

網路通訊 socket/connect/sendto/sendmsg 等

其他1、安裝

yum install strace

2、使用

1、strace -tt nginx

檢視nginx啟動過程中與系統核心的互動

在你要執行的命令前加strace命令即可

2、a ssh登入登入b,在b上執行

strace -f -p 20481 -ttt -o 1.log

20481是遠端ssh登入b所產生的程序號

記錄ssh之後的所有互動資訊並寫入到當前目錄的 1.log檔案中,相當於》

strace -p pid

3、strace -tt -t -v -f -e trace=file -o /data/log/strace.log -s 1024 -p 23489

-tt 在每行輸出的前面,顯示毫秒級別的時間

-t 顯示每次系統呼叫所花費的時間

-v 對於某些相關呼叫,把完整的環境變數,檔案stat結構等打出來。

-f 跟蹤目標程序,以及目標程序建立的所有子程序

-e 控制要跟蹤的事件和跟蹤行為,比如指定要跟蹤的系統呼叫名稱

-o 把strace的輸出單獨寫到指定的檔案

-s 當系統呼叫的某個引數是字串時,最多輸出指定長度的內容,預設是32個位元組

-p 指定要跟蹤的程序pid, 要同時跟蹤多個pid, 重複多次-p選項即可。

例項:跟蹤nginx, 看其啟動時都訪問了哪些檔案

strace -tt -t -f -e trace=file -o /data/log/strace.log -s 1024 nginx

strace問題定位案例

1、定位程序異常退出

問題:機器上有個叫做run.sh的常駐指令碼,執行一分鐘後會死掉。需要查出死因。

定位:程序還在執行時,通過ps命令獲取其pid, 假設我們得到的pid是24298

strace -o strace.log -tt -p 24298

檢視strace.log, 我們在最後2行看到如下內容:

22:47:42.803937 wait4(-1,

22:47:43.228422 +++ killed by sigkill +++

這裡可以看出,程序是被其他程序用kill訊號殺死的。

實際上,通過分析,我們發現機器上別的服務有個監控指令碼,它監控乙個也叫做run.sh的程序,當發現run.sh程序數大於2時,就會把它殺死重啟。結果導致我們這個run.sh指令碼被誤殺。

程序被殺退出時,strace會輸出killed by sigx(sigx代表傳送給程序的訊號)等,那麼,程序自己退出時會輸出什麼呢?

這裡有個叫做test_exit的程式,其**如下:

#include

#include

int main(int argc, char **ar**)

我們strace看下它退出時strace上能看到什麼痕跡。

strace -tt -e trace=process -f ./test_exit

說明: -e trace=process 表示只跟蹤和程序管理相關的系統呼叫。

輸出:23:07:24.672849 execve("./test_exit", ["./test_exit"], [/* 35 vars */]) = 0

23:07:24.674665 arch_prctl(arch_set_fs, 0x7f1c0eca7740) = 0

23:07:24.675108 exit_group(1) = ?

23:07:24.675259 +++ exited with 1 +++

可以看出,程序自己退出時(呼叫exit函式,或者從main函式返回), 最終呼叫的是exit_group系統呼叫, 並且strace會輸出exited with x(x為退出碼)。

可能有人會疑惑,**裡面明明呼叫的是exit, 怎麼顯示為exit_group?

這是因為這裡的exit函式不是系統呼叫,而是glibc庫提供的乙個函式,exit函式的呼叫最終會轉化為exit_group系統呼叫,它會退出當前程序的所有執行緒。實際上,有乙個叫做_exit()的系統呼叫(注意exit前面的下劃線), 執行緒退出時最終會呼叫它。

這裡特別說下strace的-e trace選項。

要跟蹤某個具體的系統呼叫,-e trace=***即可。但有時候我們要跟蹤一類系統呼叫,比如所有和檔名有關的呼叫、所有和記憶體分配有關的呼叫。

如果人工輸入每乙個具體的系統呼叫名稱,可能容易遺漏。於是strace提供了幾類常用的系統呼叫組合名字。

-e trace=file     跟蹤和檔案訪問相關的呼叫(引數中有檔名)

-e trace=process 和程序管理相關的呼叫,比如fork/exec/exit_group

-e trace=network 和網路通訊相關的呼叫,比如socket/sendto/connect

-e trace=signal 訊號傳送和處理相關,比如kill/sigaction

-e trace=desc 和檔案描述符相關,比如write/read/select/epoll等

-e trace=ipc 程序見同學相關,比如shmget等

絕大多數情況,我們使用上面的組合名字就夠了。實在需要跟蹤具體的系統呼叫時,可能需要注意c庫實現的差異。

比如我們知道建立程序使用的是fork系統呼叫,但在glibc裡面,fork的呼叫實際上對映到了更底層的clone系統呼叫。使用strace時,得指定-e trace=clone, 指定-e trace=fork什麼也匹配不上。

3、 效能分析

假如有個需求,統計linux 4.5.4 版本核心中的**行數(包含彙編和c**)。這裡提供兩個shell指令碼實現:

poor_script.sh:

!/bin/bash

total_line=0

while read filename; do

line=$(wc -l $filename | awk 『』)

(( total_line += line ))

done < <( find linux-4.5.4 -type f ( -iname 『.c』 -o -iname 『.h』 -o -iname 『*.s』 ) )

echo 「total line: $total_line」

good_script.sh:

!/bin/bash

find linux-4.5.4 -type f ( -iname 『.c』 -o -iname 『.h』 -o -iname 『*.s』 ) -print0

| wc -l —files0-from - | tail -n 1

兩段**實現的目的是一樣的。 我們通過strace的-c選項來分別統計兩種版本的系統呼叫情況和其所花的時間(使用-f同時統計子程序的情況)

從兩個輸出可以看出,good_script.sh 只需要2秒就可以得到結果:19613114行。它大部分的呼叫(calls)開銷是檔案操作(read/open/write/close)等,統計**行數本來就是幹這些事情。

而poor_script.sh完成同樣的任務則花了539秒。它大部分的呼叫開銷都在程序和記憶體管理上(wait4/mmap/getpid…)。

實際上,從兩個圖中clone系統呼叫的次數,我們可以看出good_script.sh只需要啟動3個程序,而poor_script.sh完成整個任務居然啟動了126335個程序!

而程序建立和銷毀的代價是相當高的,效能不差才怪。

總結當發現程序或服務異常時,我們可以通過strace來跟蹤其系統呼叫,「看看它在幹啥」,進而找到異常的原因。熟悉常用系統呼叫,能夠更好地理解和使用strace。

當然,萬能的strace也不是真正的萬能。當目標程序卡死在使用者態時,strace就沒有輸出了。

這個時候我們需要其他的跟蹤手段,比如gdb/perf/systemtap等。

備註:1、perf原因kernel支援

2、ftrace kernel支援可程式設計

3、systemtap 功能強大,redhat系統支援,對使用者態,核心態邏輯都能探查,使用範圍更廣

運維子系統之運維節點

運維子系統是通用平台重要的基礎構件,運維節點則是運維子系統最重要,最基礎的構成部分。運維節點被部署在每台伺服器上,維護該台伺服器上所有的運維任務。運維節點功能上篇已經描述,本篇簡介運維節點實現上相關要點。1.守護功能 守護功能作為乙個7x24小時執行系統而言是必不可少的,再穩定服務也有發生異常的時候...

Linux系統運維之運維監控 pdf格式

linux系統運維之運維監控 本文是系統運維工程師的實用手冊 主要講解基於 linux 平台運維工作中需要掌握的監控知識 本文全部基於實際應用 部署步驟詳細 可以直接複製用於生產環境的安裝配置 幫助剛剛接觸 linux運維的朋友們,迅速搭建企業級的監控平台。本文共分為五個部分 第一部分簡單的介紹了監...

運維之基礎命令大全

二 linux常用命令 如何分割槽?交換分割槽大小?一般來說,在linux系統中都有最少兩個掛載點,分別是 根目錄 及 swap 交換分割槽 其中,是必須的 建議掛載的幾大目錄 根目錄,唯一必須掛載的目錄。一般為2g swap 交換分割槽,虛擬記憶體,分擔物理記憶體的壓力。一般為物理記憶體的2倍 h...