Nên sử dụng strace như thế nào?


273

Một đồng nghiệp đã từng nói với tôi rằng lựa chọn cuối cùng khi mọi thứ không thể gỡ lỗi trên Linux là sử dụng strace .

Tôi đã cố gắng tìm hiểu khoa học đằng sau công cụ kỳ lạ này, nhưng tôi không phải là một quản trị viên hệ thống và tôi không thực sự đạt được kết quả.

Vì thế,

  • Nó chính xác là gì và nó làm gì?
  • Làm thế nào và trong những trường hợp nên được sử dụng?
  • Làm thế nào đầu ra nên được hiểu và xử lý?

Tóm lại, nói một cách đơn giản , công cụ này hoạt động như thế nào?


2
strace -p <pid> sẽ cho bạn biết những gì đang diễn ra với chương trình của bạn ..... nhanh chóng và dễ dàng hơn GDB
ernesto

1
Cá nhân tôi thấy man stracethực sự dễ đọc và hữu ích. (PS chưa biết về bước đi trước ngày hôm qua và không phải là chuyên gia về Linux)
Alexander Malakhov

1
"strace là một trình theo dõi cuộc gọi hệ thống" - nó chỉ cho bạn thấy các hàm kernel nào đang được gọi (với các đối số của chúng) là kết quả của chương trình của bạn.
Pithikos

Câu trả lời:


184

Strace Tổng quan
strace có thể được coi là một trình gỡ lỗi trọng lượng nhẹ. Nó cho phép lập trình viên / người dùng nhanh chóng tìm ra cách chương trình tương tác với HĐH. Nó thực hiện điều này bằng cách giám sát các cuộc gọi hệ thống và tín hiệu.

Sử dụng
Tốt khi bạn không có mã nguồn hoặc không muốn bị làm phiền khi thực sự đi qua nó.
Ngoài ra, hữu ích cho mã của riêng bạn nếu bạn không muốn mở GDB, nhưng chỉ quan tâm đến việc hiểu tương tác bên ngoài.

Một lời giới thiệu nhỏ
tôi đã chạy vào phần giới thiệu này để sử dụng chỉ trong một ngày khác: strace hello world


Vì vậy, nếu bạn sử dụng một cái gì đó bên dưới lớp mà màn hình strace?
Pacerier

Trong đó kiểm tra trường hợp @Pacerier ltrace stackoverflow.com/a/52012215/5884955
prosti

Thật tuyệt vời khi gỡ lỗi các chương trình cấp thấp chỉ tồn tại / chủ yếu để thực hiện các cuộc gọi hệ thống thú vị hoặc thử nghiệm các tùy chọn mới cho các tòa nhà để xem hệ điều hành của bạn làm gì. Về cơ bản, nó giúp tiết kiệm rắc rối khi viết mã đăng nhập / kiểm tra lỗi cho các thử nghiệm một lần. (Hoặc nếu bạn đang viết bằng asm hoặc một cái gì đó rất có thể bạn đã vô tình chuyển nhầm số hoặc thậm chí gọi số.) Strace nhanh hơn nhiều so với GDB vì nó tìm mã sai cho bạn, ví dụ: -EFAULTchỉ đọc, chỉ đọc bộ đệm) hoặc -ENOENT(rất tiếc, chạy từ thư mục sai nơi đường dẫn tương đối không hoạt động).)
Peter Cordes

62

Nói một cách đơn giản, strace dấu vết tất cả các cuộc gọi hệ thống được phát hành bởi một chương trình cùng với mã trả lại của chúng. Hãy suy nghĩ những thứ như các hoạt động tập tin / ổ cắm và nhiều thứ tối nghĩa hơn.

Sẽ hữu ích nhất nếu bạn có một số kiến ​​thức làm việc về C vì ở đây các cuộc gọi hệ thống sẽ chính xác hơn cho các cuộc gọi thư viện C tiêu chuẩn.

Giả sử chương trình của bạn là / usr / local / bin / ho. Đơn giản chỉ cần sử dụng:

strace /usr/local/bin/cough <any required argument for cough here>

hoặc là

strace -o <out_file> /usr/local/bin/cough <any required argument for cough here>

để viết vào 'out_file'.

Tất cả đầu ra strace sẽ chuyển đến stderr (hãy cẩn thận, khối lượng tuyệt đối của nó thường yêu cầu chuyển hướng đến một tệp). Trong những trường hợp đơn giản nhất, chương trình của bạn sẽ hủy bỏ lỗi và bạn sẽ có thể thấy nơi tương tác cuối cùng của nó với HĐH trong đầu ra strace.

Thông tin thêm nên có sẵn với:

man strace

36

strace liệt kê tất cả các cuộc gọi hệ thống được thực hiện theo quy trình mà nó được áp dụng. Nếu bạn không biết hệ thống gọi là gì, bạn sẽ không thể nhận được nhiều dặm từ nó.

Tuy nhiên, nếu sự cố của bạn liên quan đến tệp hoặc đường dẫn hoặc giá trị môi trường, việc chạy strace trên chương trình có vấn đề và chuyển hướng đầu ra sang tệp và sau đó lấy tệp đó cho chuỗi đường dẫn / tệp / env của bạn có thể giúp bạn thấy chương trình của bạn đang thực sự cố gắng làm gì làm, như khác biệt với những gì bạn mong đợi nó.


7
Và đối với các chương trình không tầm thường, điều này thường giống như uống từ vòi cứu hỏa, vì vậy bạn sẽ cắt bỏ công việc của mình để vượt qua kết quả ...
dmckee --- ex-moderator đã đánh dấu

17
strace <prog_name>để theo dõi một chương trình. strace -o <out_file> <prog_name>để đưa ra một tập tin
Jestin Joy

8
bước tiến 2> & 1 | grep ^ mở \ (
đĩa mềm

10
Hoặc chỉ: strace -e open myprogHOẶC cho tất cả các cuộc gọi sys liên quan đến tệp:strace -e file myprog
Amit N Nikol

17

Strace nổi bật như một công cụ để điều tra các hệ thống sản xuất nơi bạn không đủ khả năng để chạy các chương trình này theo trình gỡ lỗi. Cụ thể, chúng tôi đã sử dụng strace trong hai tình huống sau:

  • Chương trình foo dường như rơi vào bế tắc và trở nên không phản hồi. Đây có thể là một mục tiêu cho gdb; tuy nhiên, chúng tôi không phải lúc nào cũng có mã nguồn hoặc đôi khi đang xử lý các ngôn ngữ theo kịch bản không được chuyển thẳng để chạy theo trình gỡ lỗi. Trong trường hợp này, bạn chạy strace trên một chương trình đã chạy và bạn sẽ nhận được danh sách các cuộc gọi hệ thống được thực hiện. Điều này đặc biệt hữu ích nếu bạn đang điều tra ứng dụng khách / máy chủ hoặc ứng dụng tương tác với cơ sở dữ liệu
  • Điều tra tại sao một chương trình chậm. Cụ thể, chúng tôi vừa chuyển sang một hệ thống tệp phân tán mới và thông lượng mới của hệ thống rất chậm. Bạn có thể chỉ định strace với tùy chọn '-T' sẽ cho bạn biết đã dành bao nhiêu thời gian cho mỗi cuộc gọi hệ thống. Điều này giúp xác định lý do tại sao hệ thống tập tin khiến mọi thứ chậm lại.

Để biết ví dụ về phân tích sử dụng strace, hãy xem câu trả lời của tôi cho câu hỏi này .


15

Tôi sử dụng strace tất cả thời gian để gỡ lỗi các vấn đề cho phép. Kỹ thuật này như thế này:

$ strace -e trace=open,stat,read,write gnome-calculator

Đâu gnome-calculatorlà lệnh mà bạn muốn chạy.


8

strace -tfp PID sẽ giám sát các cuộc gọi hệ thống của quy trình PID, do đó chúng ta có thể gỡ lỗi / theo dõi trạng thái quy trình / chương trình của mình.


6

Strace có thể được sử dụng như một công cụ gỡ lỗi, hoặc như một trình lược tả nguyên thủy.

Là một trình gỡ lỗi, bạn có thể thấy các cuộc gọi hệ thống đã được gọi, được thực hiện và những gì chúng trả về. Điều này rất quan trọng, vì nó cho phép bạn thấy không chỉ một chương trình thất bại, mà TẠI SAO một chương trình thất bại. Thông thường, đó chỉ là kết quả của việc mã hóa tệ hại không nắm bắt được tất cả các kết quả có thể có của một chương trình. Những lần khác, nó chỉ là đường dẫn được mã hóa cứng đến các tập tin. Không có bước đi bạn có thể đoán những gì đã sai ở đâu và như thế nào. Với strace bạn nhận được một sự cố của một tòa nhà, thường chỉ cần nhìn vào một giá trị trả về cho bạn rất nhiều.

Hồ sơ là một cách sử dụng khác. Bạn có thể sử dụng nó để thực hiện thời gian của từng tòa nhà riêng lẻ hoặc dưới dạng tổng hợp. Mặc dù điều này có thể không đủ để khắc phục vấn đề của bạn, nhưng ít nhất nó sẽ thu hẹp đáng kể danh sách các nghi phạm tiềm năng. Nếu bạn thấy rất nhiều cặp fopen / close trên một tệp, bạn có thể mở và đóng tệp một cách không cần thiết mỗi khi thực hiện một vòng lặp, thay vì mở và đóng nó bên ngoài vòng lặp.

Ltrace là anh em họ thân thiết của strace, cũng rất hữu ích. Bạn phải học cách phân biệt nơi tắc nghẽn của bạn. Nếu tổng thời gian thực hiện là 8 giây và bạn chỉ dành 0,05 giây cho các cuộc gọi hệ thống, thì việc phân tầng chương trình sẽ không giúp bạn nhiều, vấn đề nằm ở mã của bạn, thường là vấn đề logic hoặc chương trình thực sự cần để mất nhiều thời gian để chạy.

Vấn đề lớn nhất với strace / ltrace là đọc đầu ra của chúng. Nếu bạn không biết các cuộc gọi được thực hiện như thế nào, hoặc ít nhất là tên của các tòa nhà / chức năng, sẽ rất khó để giải mã ý nghĩa. Biết những gì các hàm trả về cũng có thể rất có lợi, đặc biệt là đối với các mã lỗi khác nhau. Mặc dù đó là một nỗi đau để giải mã, đôi khi họ thực sự trả lại một viên ngọc kiến ​​thức; một khi tôi thấy một tình huống tôi hết mực, nhưng không hết dung lượng, do đó tất cả các tiện ích thông thường không đưa ra bất kỳ cảnh báo nào, tôi không thể tạo một tệp mới. Đọc mã lỗi từ đầu ra của strace chỉ cho tôi đi đúng hướng.


4

Strace là một công cụ cho bạn biết ứng dụng của bạn tương tác với hệ điều hành của bạn như thế nào.

Nó thực hiện điều này bằng cách cho bạn biết hệ thống HĐH gọi ứng dụng của bạn sử dụng cái gì và với thông số nào nó gọi chúng.

Vì vậy, ví dụ bạn thấy những tập tin nào chương trình của bạn cố mở và vượt qua cuộc gọi thành công.

Bạn có thể gỡ lỗi tất cả các loại vấn đề với công cụ này. Chẳng hạn, nếu ứng dụng nói rằng nó không thể tìm thấy thư viện mà bạn biết bạn đã cài đặt, thì strace sẽ cho bạn biết ứng dụng đang tìm tệp đó ở đâu.

Và đó chỉ là một phần nổi của tảng băng chìm.


Điều này rất chính xác.
prosti

4

strace là một công cụ tốt để tìm hiểu cách chương trình của bạn thực hiện các cuộc gọi hệ thống khác nhau (yêu cầu tới kernel) và cũng báo cáo những lỗi đã xảy ra cùng với giá trị lỗi liên quan đến lỗi đó. Không phải tất cả các thất bại là lỗi. Ví dụ: một mã đang cố gắng tìm kiếm tệp có thể gặp lỗi ENOENT (Không có tệp hoặc thư mục như vậy) nhưng đó có thể là một kịch bản có thể chấp nhận được trong logic của mã.

Một trường hợp sử dụng tốt của việc sử dụng strace là gỡ lỗi các điều kiện cuộc đua trong khi tạo tệp tạm thời. Ví dụ, một chương trình có thể đang tạo các tệp bằng cách nối thêm ID tiến trình (PID) vào một số chuỗi được xác định trước có thể gặp phải các vấn đề trong các tình huống đa luồng. [Một PID + TID (id quá trình + id luồng) hoặc một cuộc gọi hệ thống tốt hơn như mkstemp sẽ khắc phục điều này].

Nó cũng tốt cho gỡ lỗi tai nạn. Bạn có thể thấy bài viết này (của tôi) về strace và gỡ lỗi sự cố hữu ích.


4

Ví dụ runnable tối thiểu

Nếu một khái niệm không rõ ràng, có một ví dụ đơn giản hơn mà bạn chưa từng thấy giải thích nó.

Trong trường hợp này, ví dụ đó là thế giới tự do lắp ráp Linux x86_64 (không có libc) hello world:

xin chào

.text
.global _start
_start:
    /* write */
    mov $1, %rax    /* syscall number */
    mov $1, %rdi    /* stdout */
    mov $msg, %rsi  /* buffer */
    mov $len, %rdx  /* buffer len */
    syscall

    /* exit */
    mov $60, %rax   /* exit status */
    mov $0, %rdi    /* syscall number */
    syscall
msg:
    .ascii "hello\n"
len = . - msg

GitHub ngược dòng .

Lắp ráp và chạy:

as -o hello.o hello.S
ld -o hello.out hello.o
./hello.out

Đầu ra dự kiến:

hello

Bây giờ hãy sử dụng strace trên ví dụ đó:

env -i ASDF=qwer strace -o strace.log -s999 -v ./hello.out arg0 arg1
cat strace.log

Chúng tôi sử dụng:

strace.log hiện chứa:

execve("./hello.out", ["./hello.out", "arg0", "arg1"], ["ASDF=qwer"]) = 0
write(1, "hello\n", 6)                  = 6
exit(0)                                 = ?
+++ exited with 0 +++

Với một ví dụ tối thiểu như vậy, mọi ký tự đầu ra đều hiển nhiên:

  • execvedòng: hiển thị cách stracethực thi hello.out, bao gồm các đối số CLI và môi trường như được ghi lại tạiman execve

  • writedòng: hiển thị cuộc gọi hệ thống ghi mà chúng tôi đã thực hiện. 6là độ dài của chuỗi "hello\n".

    = 6là giá trị trả về của lệnh gọi hệ thống, như được ghi trong tài liệu man 2 writelà số byte được ghi.

  • exitdòng: hiển thị cuộc gọi hệ thống thoát mà chúng tôi đã thực hiện. Không có giá trị trả lại, kể từ khi chương trình bỏ!

Ví dụ phức tạp hơn

Tất nhiên, ứng dụng của strace để xem hệ thống nào gọi các chương trình phức tạp đang thực sự làm để giúp gỡ lỗi / tối ưu hóa chương trình của bạn.

Đáng chú ý, hầu hết các cuộc gọi hệ thống mà bạn có khả năng gặp phải trong Linux đều có các trình bao bọc glibc, nhiều trong số chúng từ POSIX .

Trong nội bộ, các trình bao bọc glibc sử dụng lắp ráp nội tuyến ít nhiều như thế này: Làm thế nào để gọi một cuộc gọi hệ thống thông qua sysenter trong lắp ráp nội tuyến?

Ví dụ tiếp theo bạn nên học là một writethế giới xin chào POSIX :

C chính

#define _XOPEN_SOURCE 700
#include <unistd.h>

int main(void) {
    char *msg = "hello\n";
    write(1, msg, 6);
    return 0;
}

Biên dịch và chạy:

gcc -std=c99 -Wall -Wextra -pedantic -o main.out main.c
./main.out

Lần này, bạn sẽ thấy rằng một loạt các cuộc gọi hệ thống đang được glibc thực hiện trước đó mainđể thiết lập một môi trường tốt đẹp cho chính.

Điều này là do chúng tôi hiện không sử dụng chương trình tự do, mà là chương trình glibc phổ biến hơn, cho phép chức năng libc.

Sau đó, ở mọi đầu, strace.logchứa:

write(1, "hello\n", 6)                  = 6
exit_group(0)                           = ?
+++ exited with 0 +++

Vì vậy, chúng tôi kết luận rằng writechức năng POSIX sử dụng, thật bất ngờ!, writeCuộc gọi hệ thống Linux .

Chúng tôi cũng quan sát return 0dẫn đến một exit_groupcuộc gọi thay vì exit. Ha, tôi không biết về cái này! Đây là lý do tại sao stracelà rất mát mẻ. man exit_groupsau đó giải thích:

Cuộc gọi hệ thống này tương đương với lối ra (2) ngoại trừ việc nó chấm dứt không chỉ chuỗi cuộc gọi, mà tất cả các luồng trong nhóm luồng của quy trình gọi.

Và đây là một ví dụ khác mà tôi đã nghiên cứu cách gọi hệ thống nào dlopensử dụng: /unix/226524/what-system-call-is- used-to-load-lologists-in-linux / 462710 # 462710

Đã thử nghiệm trong Ubuntu 16.04, GCC 6.4.0, nhân Linux 4.4.0.


2

Dưới đây là một số ví dụ về cách tôi sử dụng strace để đào sâu vào các trang web. Hy vọng điều này là hữu ích.

Kiểm tra thời gian để byte đầu tiên như vậy:

time php index.php > timeTrace.txt

Xem bao nhiêu phần trăm hành động đang làm gì. Rất nhiều lstatfstatcó thể là một dấu hiệu cho thấy đã đến lúc xóa bộ nhớ cache:

strace -s 200 -c php index.php > traceLstat.txt

Xuất ra một trace.txtđể bạn có thể thấy chính xác những cuộc gọi đang được thực hiện.

strace -Tt -o Fulltrace.txt php index.php

Sử dụng điều này để kiểm tra về việc liệu bất cứ điều gì mất giữa .1để .9của một giây để tải:

cat Fulltrace.txt | grep "[<]0.[1-9]" > traceSlowest.txt

Xem những gì thiếu tập tin hoặc thư mục đã bị bắt trong strace. Điều này sẽ tạo ra rất nhiều thứ liên quan đến hệ thống của chúng tôi - các bit có liên quan duy nhất liên quan đến các tệp của khách hàng:

strace -vv php index.php 2>&1 | sed -n '/= -1/p' > traceFailures.txt

1

Tôi thích một số câu trả lời strace kiểm tra cách bạn tương tác với hệ điều hành của bạn.

Đây chính xác là những gì chúng ta có thể thấy. Hệ thống gọi. Nếu bạn so sánh straceltracesự khác biệt là rõ ràng hơn.

$>strace -c cd
Desktop  Documents  Downloads  examples.desktop  Music  Pictures  Public  Templates  Videos
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
  0.00    0.000000           0         7           read
  0.00    0.000000           0         1           write
  0.00    0.000000           0        11           close
  0.00    0.000000           0        10           fstat
  0.00    0.000000           0        17           mmap
  0.00    0.000000           0        12           mprotect
  0.00    0.000000           0         1           munmap
  0.00    0.000000           0         3           brk
  0.00    0.000000           0         2           rt_sigaction
  0.00    0.000000           0         1           rt_sigprocmask
  0.00    0.000000           0         2           ioctl
  0.00    0.000000           0         8         8 access
  0.00    0.000000           0         1           execve
  0.00    0.000000           0         2           getdents
  0.00    0.000000           0         2         2 statfs
  0.00    0.000000           0         1           arch_prctl
  0.00    0.000000           0         1           set_tid_address
  0.00    0.000000           0         9           openat
  0.00    0.000000           0         1           set_robust_list
  0.00    0.000000           0         1           prlimit64
------ ----------- ----------- --------- --------- ----------------
100.00    0.000000                    93        10 total

Mặt khác, có ltracedấu vết chức năng.

$>ltrace -c cd
Desktop  Documents  Downloads  examples.desktop  Music  Pictures  Public  Templates  Videos
% time     seconds  usecs/call     calls      function
------ ----------- ----------- --------- --------------------
 15.52    0.004946         329        15 memcpy
 13.34    0.004249          94        45 __ctype_get_mb_cur_max
 12.87    0.004099        2049         2 fclose
 12.12    0.003861          83        46 strlen
 10.96    0.003491         109        32 __errno_location
 10.37    0.003303         117        28 readdir
  8.41    0.002679         133        20 strcoll
  5.62    0.001791         111        16 __overflow
  3.24    0.001032         114         9 fwrite_unlocked
  1.26    0.000400         100         4 __freading
  1.17    0.000372          41         9 getenv
  0.70    0.000222         111         2 fflush
  0.67    0.000214         107         2 __fpending
  0.64    0.000203         101         2 fileno
  0.62    0.000196         196         1 closedir
  0.43    0.000138         138         1 setlocale
  0.36    0.000114         114         1 _setjmp
  0.31    0.000098          98         1 realloc
  0.25    0.000080          80         1 bindtextdomain
  0.21    0.000068          68         1 opendir
  0.19    0.000062          62         1 strrchr
  0.18    0.000056          56         1 isatty
  0.16    0.000051          51         1 ioctl
  0.15    0.000047          47         1 getopt_long
  0.14    0.000045          45         1 textdomain
  0.13    0.000042          42         1 __cxa_atexit
------ ----------- ----------- --------- --------------------
100.00    0.031859                   244 total

Mặc dù tôi đã kiểm tra hướng dẫn sử dụng nhiều lần, tôi không tìm thấy nguồn gốc của tên stracenhưng có khả năng đó là dấu vết cuộc gọi hệ thống, vì điều này là hiển nhiên.

Có ba lưu ý lớn hơn để nói về strace.

Lưu ý 1: Cả hai chức năng này straceltraceđang sử dụng lệnh gọi hệ thống ptrace. Vì vậy, ptracehệ thống gọi là cách hiệu quả làm straceviệc.

Cuộc gọi hệ thống ptrace () cung cấp một phương tiện để một quá trình ("bộ theo dõi") có thể quan sát và kiểm soát việc thực hiện quy trình khác ("tracee"), và kiểm tra và thay đổi bộ nhớ và các thanh ghi của tracee. Nó chủ yếu được sử dụng để thực hiện gỡ lỗi điểm dừng và theo dõi cuộc gọi hệ thống.

Lưu ý 2: Có các tham số khác nhau mà bạn có thể sử dụng strace, vì stracecó thể rất dài dòng. Tôi thích thử nghiệm với -cnó giống như một bản tóm tắt của mọi thứ. Dựa vào -cbạn có thể chọn một cuộc gọi hệ thống như -e trace=opennơi bạn sẽ chỉ thấy cuộc gọi đó. Điều này có thể thú vị nếu bạn đang kiểm tra những tập tin nào sẽ được mở trong lệnh bạn đang theo dõi. Và tất nhiên, bạn có thể sử dụng grepcho cùng một mục đích nhưng lưu ý bạn cần chuyển hướng như thế này 2>&1 | grep etcđể hiểu rằng các tệp cấu hình được tham chiếu khi lệnh được ban hành.

Lưu ý 3: Tôi thấy lưu ý rất quan trọng này. Bạn không bị giới hạn trong một kiến ​​trúc cụ thể. stracesẽ thổi vào tâm trí của bạn, vì nó có thể theo dõi các nhị phân của các kiến ​​trúc khác nhau. nhập mô tả hình ảnh ở đây

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.