Các công cụ để hiển thị các tập tin được truy cập bởi một chương trình?


12

Tôi sẽ không sử dụng các công cụ phức tạp như chế độ khiếu nại của AppArmor, tôi cần các công cụ dễ dàng để cho tôi biết các tệp nào được truy cập bởi một chương trình cụ thể.


7
Theo hệ điều hành nào?
Jeff Schaller

Cũng có thể hữu ích để giải thích bạn mong đợi chương trình truy cập các tệp theo cách nào - đọc, viết, nối thêm, chỉ nhận fstat()hoặc lstat()thông tin, v.v.
Sergiy Kolodyazhnyy

Cả Suse và Ubuntu
Boll19

Không có vấn đề gì tôi phải biết, đó là fstat () hay lstat () đang lập trình?
Boll19

Nói cách khác, Sergiy Kolodyazhnyy bình luận: nếu một chương trình kiểm tra độ dài của tệp, ngày sửa đổi, quyền hoặc các thuộc tính khác nhưng không truy cập dữ liệu của tệp, bạn có tính nó là "truy cập tệp" hay không?
telcoM

Câu trả lời:


12

Theo Chris Down, bạn có thể sử dụng strace -pđể kiểm tra một quy trình đã chạy , để xem các tệp nào sẽ mở từ bây giờ cho đến khi bạn chấm dứt bước hoặc quá trình tự kết thúc.

Nếu bạn muốn xem các tệp được mở trong toàn bộ thời gian của một quy trình, ngay từ đầu, hãy sử dụng stracevới tên thực thi. Thêm -fđảm bảo rằng bất kỳ quy trình phụ rẽ nhánh cũng được báo cáo. Thí dụ

# strace -e open -f /bin/id
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libpcre.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
open("/proc/thread-self/attr/current", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/proc/self/task/1581/attr/current", O_RDONLY|O_CLOEXEC) = 3
open("/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 3
open("/usr/share/locale/en_US.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_US.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_US/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 3
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = 3
open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3
open("/etc/group", O_RDONLY|O_CLOEXEC)  = 3
open("/etc/group", O_RDONLY|O_CLOEXEC)  = 3
uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
+++ exited with 0 +++
#

Sử dụng lsofđể xem những gì một quy trình hiện đang mở

# lsof -p $(pidof NetworkManager)
COMMAND   PID USER   FD      TYPE             DEVICE  SIZE/OFF     NODE NAME
NetworkMa 722 root  cwd       DIR              253,0       224       64 /
NetworkMa 722 root  rtd       DIR              253,0       224       64 /
NetworkMa 722 root  txt       REG              253,0   2618520   288243 /usr/sbin/NetworkManager
NetworkMa 722 root  mem       REG              253,0     27776    34560 /usr/lib64/libnss_dns-2.17.so
[...]
#

Nếu bạn có SystemTap, bạn có thể giám sát toàn bộ máy chủ để xem các tệp đang được mở.

[root@localhost tmp]# cat mon
#!/usr/bin/env stap
probe syscall.open { printf ("pid %d program %s opened %s\n", pid(), execname(), filename) }
# ./mon
pid 14813 program touch opened "/etc/ld.so.cache"
pid 14813 program touch opened "/lib64/libc.so.6"
pid 14813 program touch opened 0x7f7a8c6ec8d0
pid 14813 program touch opened "foo2"
[...]
#

2
openkhông phải là cuộc gọi hệ thống duy nhất có liên quan. Ví dụ, có thể truyền mô tả tệp giữa các quy trình qua ổ cắm unix và có openatlệnh gọi hệ thống cũng có thể mở tệp.
kasperd

---- SIGUSR1 {si_signo = SIGUSR1, si_code = SI_TKILL, si_pid = 6026, si_uid = 1002} ---- whats that
Boll19

kaspers, tôi chỉ cần tìm kiếm 'openat' tại lệnh đầu ra strace?
Boll19

Thử mở một tệp (nhưng tệp có thể không tồn tại) cũng được hiển thị trong các đầu ra 'strace'?
Boll19

Boll19, các tệp không mở được do chúng không tồn tại được báo cáo vui vẻ bên trong strace, xem các dòng ENOENT trong ví dụ.
steve

5

Bạn có thể sử dụng opensnooptừ BCC, sử dụng eBPF trong phần mềm:

# ./opensnoop -p 1576
PID    COMM      FD ERR PATH
1576   snmpd     11   0 /proc/sys/net/ipv6/conf/lo/forwarding
1576   snmpd     11   0 /proc/sys/net/ipv6/neigh/lo/base_reachable_time_ms
1576   snmpd      9   0 /proc/diskstats
1576   snmpd      9   0 /proc/stat
1576   snmpd      9   0 /proc/vmstat
[...]

Điều này khá hiệu quả vì nó sử dụng kprobes thay vì phải khởi động lại các tòa nhà cao tầng, giống như stracevậy.

Bạn cũng có thể làm điều này với strace(có khả năng -ftheo dõi quá trình truy tìm dấu vết của con cái), nhưng cách vận hành của nó, liên quan đến việc khởi động lại các tòa nhà cao tầng vì một phần của ptrace sẽ làm chậm ứng dụng của bạn:

# strace -e open -p 15735
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/gconv/gconv-modules.cache", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib/gconv/gconv-modules", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/python2.7/site-packages", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 4
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
open("/etc/localtime", O_RDONLY|O_CLOEXEC) = 8
[...]

Bạn cũng có thể bắt đầu ứng dụng của mình theo cách này nếu muốn, sử dụng strace [executable]hoặc strace -f [executable].


5

Công cụ yêu thích của tôi để theo dõi tập tin nào ứng dụng mở ra là khung giám sát mạnh mẽ sysdig.

Để theo dõi tất cả các tệp đang mở được mở bởi một chương trình có tên exe_file:

sudo sysdig -p "proc.name=exe_file %12user.name %6proc.pid %12proc.name %3fd.num %fd.typechar %fd.name" evt.type=open

Giám sát tất cả các tệp được mở trong máy chủ:

sudo sysdig -p "%12user.name %6proc.pid %12proc.name %3fd.num %fd.typechar %fd.name" evt.type=open

Tạo một tệp theo dõi sẽ chỉ chứa các sự kiện bằng văn bản trong các thư mục nhà (mà chúng ta có thể kiểm tra sau này sysdig -r writetrace.scap.gz):

sudo sysdig -p "%user.name %proc.name %fd.name" "evt.type=write and fd.name contains /home/" -z -w writetrace.scap.gz

Nhìn thấy mọi thứ ở cấp độ tòa nhà, một quá trình có tên là exe_file:

sudo sysdig proc.name=exe_file

Sysdig có nhiều cái đục, hãy xem những điều thú vị hơn nó có thể làm:

Bạn cũng đã nhận được dtracerằng nó không được sử dụng nhiều trong Linux, nhưng vẫn được sử dụng rất nhiều với các hệ điều hành * BSD:

# Files opened by process,
dtrace -n 'syscall::open*:entry { printf("%s %s",execname,copyinstr(arg0)); }'

Ngoài ra sysdig, stracedtrace, bạn cũng đã nhận được ltrace, ghi / chặn tín hiệu / thư viện động / lệnh gọi hệ thống được gọi / nhận bởi một quy trình:

ltracelà một chương trình chỉ đơn giản là chạy lệnh được chỉ định cho đến khi nó thoát. Nó chặn và ghi lại các cuộc gọi thư viện động được gọi bởi quá trình thực thi và các tín hiệu được nhận bởi quá trình đó. Nó cũng có thể chặn và in các cuộc gọi hệ thống được thực hiện bởi chương trình.

$ltrace exe_file
_libc_start_main(0x400624, 1, 0x7ffcb7b6d7c8, 0x400710 <unfinished ...>  
time(0)                                                                              = 1508018406  
srand(0x59e288e6, 0x7ffcb7b6d7c8, 0x7ffcb7b6d7d8, 0)                                 = 0  
sprintf("mkdir -p -- '/opt/sms/AU/mo'", "mkdir -p -- '%s'", "/opt/sms/AU/mo")        = 28  
system("mkdir -p -- '/opt/sms/AU/mo'" <no return ...>  
--- SIGCHLD (Child exited) ---  
<... system resumed> )                                                               = 0  
rand(2, 0x7ffcb7b6d480, 0, 0x7f9d6d4622b0)                                           = 0x2d8ddbe1  
sprintf("/opt/sms/AU/mo/tmp.XXXXXX", "%s/tmp.XXXXXX", "/opt/sms/AU/mo")      = 29  
mkstemp(0x7ffcb7b6d5c0, 0x40080b, 0x40081a, 0x7ffffff1)                              = 3  
sprintf("/opt/sms/AU/mo/tmp.XXXXXX", "%s/tmp.XXXXXX", "/opt/sms/AU/mo")      = 29  
mkstemp(0x7ffcb7b6d5c0, 0x40080b, 0x40081a, 0x7ffffff1)                              = 4  
+++ exited (status 0) +++  

Nếu chương trình nhỏ, bạn cũng có thể xem xét tháo rời chương trình objdump -d exe_filehoặc phân tách / dịch ngược chương trình Hopper, để xem tất cả các tệp mà nó xử lý.

Để biết thêm chi tiết, hãy xem: Hiểu những gì một nhị phân Linux đang làm

Cách tiếp cận đầu tiên, tôi cũng sẽ làm:

strings exe_file

Đây là một cách tiếp cận chi phí thấp và may mắn, một số tên tệp có thể xuất hiện trong chế độ ASCII trong tệp nhị phân một cách may mắn.

Xem thêm câu trả lời liên quan Tại sao đúng và sai quá lớn?

Nếu tệp nhị phân / tệp đi kèm với bản phân phối, bạn cũng có thể tìm nạp các nguồn từ kho lưu trữ nguồn của bản phân phối hoặc kho chính thức của tiện ích thực tế.

Là tài nguyên cuối cùng, bạn luôn có thể sử dụng các công cụ như gdb hoặc rr để gỡ lỗi nhị phân trong thời gian thực.


aaa43bb66: ~ # sudo Proc.name = exe_file sysdig -p "% 12user.name% 6proc.pid% 12proc.name% 3fd.num% fd.typechar% fd.name" evt.type = mở Không thể tải trình điều khiển mở thiết bị / dev / sysdig0. Hãy chắc chắn rằng bạn có thông tin gốc và mô-đun thăm dò sysdig đã được tải.
Boll19

/ * <pre> aaa43bb66: ~ # sudo Proc.name = exe_file sysdig -p "% 12user.name% 6proc.pid% 12proc.name% 3fd.num% fd.typechar% fd.name" evt.ty để tải thiết bị mở lỗi trình điều khiển / dev / sysdig0. Hãy chắc chắn rằng bạn có thông tin gốc và mô-đun thăm dò sysdig đã được tải. <Code> * /
Boll19

@ Boll19 Có một lỗi ở đó, sửa nó. Thông báo đó có vẻ như về một sysdiglỗi (bạn đang sử dụng ARM?), Vui lòng gửi câu hỏi mới cho nó.
Rui F Ribeiro
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.