Dòng lệnh Linux cung cấp nhiều công cụ hữu ích cho các nhà phát triển phần mềm. Một trong số đó là strace, một lệnh để theo dõi các lệnh gọi hệ thống và tín hiệu Linux. Những điều cơ bản về strace mà chúng ta sẽ thảo luận trong hướng dẫn này bằng một số ví dụ dễ hiểu.
Nhưng trước khi làm điều đó, cần đề cập rằng tất cả các ví dụ trong bài viết này đã được thử nghiệm trên máy Ubuntu 22.04 LTS và Debian 11.
Lệnh strace trong Linux cho phép bạn theo dõi các lệnh gọi hệ thống và tín hiệu. Sau đây là cú pháp của lệnh:
Và đây là cách trang hướng dẫn của công cụ giải thích về lệnh này:
Sau đây là một số ví dụ theo kiểu Hỏi & Đáp sẽ giúp bạn hiểu rõ hơn về cách lệnh strace hoạt động.
Cài đặt lệnh strace
Theo Mặc định, lệnh strace không được cài đặt trên hầu hết các hệ thống, để cài đặt lệnh này trên Debian và Ubuntu, hãy chạy lệnh này:
Và đây là đầu ra được tạo ra trên hệ thống của tôi:
Các đoạn trích sau đây từ trang hướng dẫn cung cấp lời giải thích chính xác:
Ví dụ:
Đây là đầu ra:
Vì vậy, bạn có thể thấy rằng con trỏ lệnh đã được in ra ở mỗi dòng trong đầu ra.
Ví dụ:
Sau đây là kết quả đầu ra do lệnh này tạo ra:
Vì vậy, bạn có thể thấy rằng dấu thời gian tương đối được tạo ra ở đầu mỗi dòng.
Ví dụ:
Đây là đầu ra của lệnh này trên hệ thống của tôi:
Vì vậy, bạn có thể thấy thời gian hệ thống được in ra ở đầu mỗi dòng.
Lưu ý rằng có thêm hai tùy chọn liên quan mà strace cung cấp:
Ví dụ:
Sau đây là kết quả:
Vì vậy, bạn có thể thấy thời gian dành cho các cuộc gọi hệ thống được in ở cuối mỗi dòng.
Ví dụ, lệnh sau:
tạo ra đầu ra này trên hệ thống của tôi:
Vì vậy, bạn có thể thấy bản tóm tắt cung cấp cho bạn ý tưởng về số lượng cuộc gọi được thực hiện trên mỗi syscall cũng như thông tin liên quan đến thời gian cho mỗi syscall.
Nhưng trước khi làm điều đó, cần đề cập rằng tất cả các ví dụ trong bài viết này đã được thử nghiệm trên máy Ubuntu 22.04 LTS và Debian 11.
Lệnh strace trong Linux cho phép bạn theo dõi các lệnh gọi hệ thống và tín hiệu. Sau đây là cú pháp của lệnh:
Mã:
strace [OPTIONS] command
Mã:
Trong trường hợp đơn giản nhất, strace chạy lệnh đã chỉ định cho đến khi lệnh đó thoát.
Lệnh này chặn và ghi lại các lệnh gọi hệ thống được gọi bởi một
quy trình và các tín hiệu mà một quy trình nhận được. Tên của
mỗi lệnh gọi hệ thống, các đối số và giá trị trả về của nó được in trên
lỗi chuẩn hoặc vào tệp được chỉ định bằng tùy chọn -o.
strace là một công cụ chẩn đoán, hướng dẫn và gỡ lỗi hữu ích. Các quản trị viên, chuyên gia chẩn đoán và người khắc phục sự cố hệ thống sẽ thấy nó
vô cùng hữu ích khi giải quyết các vấn đề với các chương trình mà nguồn
không dễ dàng có được vì chúng không cần phải được biên dịch lại để
theo dõi chúng. Sinh viên, tin tặc và những người quá tò mò sẽ thấy rằng
có thể học được rất nhiều điều về một hệ thống và các lệnh gọi hệ thống của nó bằng cách
theo dõi ngay cả các chương trình thông thường. Và các lập trình viên sẽ thấy rằng vì
các lệnh gọi hệ thống và tín hiệu là các sự kiện xảy ra tại giao diện người dùng/nhân
, nên việc kiểm tra kỹ lưỡng ranh giới này rất hữu ích cho việc cô lập lỗi
, kiểm tra tính hợp lệ và cố gắng nắm bắt các điều kiện chạy đua.
Cài đặt lệnh strace
Theo Mặc định, lệnh strace không được cài đặt trên hầu hết các hệ thống, để cài đặt lệnh này trên Debian và Ubuntu, hãy chạy lệnh này:
Mã:
sudo apt-get install strace
Câu hỏi 1. Làm thế nào để sử dụng lệnh strace?
Cách sử dụng cơ bản rất đơn giản, chỉ cần thực thi 'strace' với một lệnh làm đầu vào. Ví dụ, tôi đã sử dụng nó với lệnh ls:
Mã:
strace ls
Câu hỏi 2. Làm thế nào để hiểu đầu ra của strace?
Như bạn có thể thấy trong ảnh chụp màn hình ở phần trước, lệnh strace tạo ra rất nhiều đầu ra. Vì vậy, bạn cần biết cách hiểu nó.Các đoạn trích sau đây từ trang hướng dẫn cung cấp lời giải thích chính xác:
Mã:
Mỗi dòng trong dấu vết chứa tên lệnh gọi hệ thống, theo sau là các đối số của lệnh đó trong dấu ngoặc đơn và giá trị trả về của lệnh. Một ví dụ từ strac?
khi sử dụng lệnh "cat /dev/null" là:
open("/dev/null", O_RDONLY) = 3
Lỗi (thường có giá trị trả về là -1) có ký hiệu errno và chuỗi lỗi
được thêm vào.
open("/foo/bar", O_RDONLY) = -1 ENOENT (Không có tệp hoặc thư mục nào như vậy)
Tín hiệu được in dưới dạng ký hiệu tín hiệu và cấu trúc siginfo được giải mã. Một đoạn trích từ strancing và ngắt lệnh "sleep 666" là:
sigsuspend([]
--- SIGINT {si_signo=SIGINT, si_code=SI_USER, si_pid=...} ---
+++ bị SIGINT giết +++
Câu hỏi 3. Làm thế nào để strace in ra con trỏ lệnh?
Có một tùy chọn -i yêu cầu strace in ra con trỏ lệnh tại thời điểm lệnh gọi hệ thống.Ví dụ:
Mã:
strace -i ls
Vì vậy, bạn có thể thấy rằng con trỏ lệnh đã được in ra ở mỗi dòng trong đầu ra.
Câu hỏi 4. Làm thế nào để strace in dấu thời gian cho mỗi lệnh gọi hệ thống?
Có một tùy chọn dòng lệnh -r yêu cầu strace hiển thị dấu thời gian tương đối khi nhập vào mỗi lệnh gọi hệ thống. Trang hướng dẫn của công cụ cho biết tùy chọn này ghi lại sự khác biệt về thời gian giữa thời điểm bắt đầu của các lệnh gọi hệ thống liên tiếp.Ví dụ:
Mã:
strace -r ls
Vì vậy, bạn có thể thấy rằng dấu thời gian tương đối được tạo ra ở đầu mỗi dòng.
Câu hỏi 5. Làm thế nào để thêm tiền tố thời gian cho mỗi dòng đầu ra?
Nếu bạn muốn mỗi dòng trong đầu ra strace bắt đầu bằng thời gian, thì bạn có thể thực hiện việc này bằng tùy chọn dòng lệnh -t.Ví dụ:
Mã:
strace -t ls
Vì vậy, bạn có thể thấy thời gian hệ thống được in ra ở đầu mỗi dòng.
Lưu ý rằng có thêm hai tùy chọn liên quan mà strace cung cấp:
Mã:
-tt
Nếu đưa ra hai lần, thời gian được in ra sẽ bao gồm cả micro giây.
-ttt
Nếu đưa ra ba lần, thời gian được in ra sẽ bao gồm cả micro giây và phần đầu sẽ
được in ra dưới dạng số giây kể từ kỷ nguyên.
Câu 6. Làm thế nào để strace hiển thị thời gian dành cho các cuộc gọi hệ thống?
Có thể thực hiện việc này bằng cách sử dụng tùy chọn dòng lệnh -T.Ví dụ:
Mã:
strace -T ls
Vì vậy, bạn có thể thấy thời gian dành cho các cuộc gọi hệ thống được in ở cuối mỗi dòng.
Câu hỏi 7. Làm thế nào để strace in ra bản tóm tắt thay vì đầu ra thông thường?
Có thể sử dụng đầu ra dòng lệnh -c nếu bạn muốn công cụ tạo ra bản tóm tắt.Ví dụ, lệnh sau:
Mã:
strace -c ls
Mã:
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
93,66 0,000133 5 28 write
6,34 0,000009 1 11 close
0,00 0,000000 0 7 read
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 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,000142 120 10 tổng cộng