it-swarm-id.com

Daftar file yang diakses oleh suatu program

time adalah perintah yang brilian jika Anda ingin mengetahui berapa banyak waktu CPU yang dibutuhkan oleh perintah yang diberikan.

Saya mencari sesuatu yang serupa yang dapat membuat daftar file yang sedang diakses oleh suatu program dan anak-anaknya. Baik secara real time atau sebagai laporan sesudahnya.

Saat ini saya menggunakan:

#!/bin/bash

strace -ff -e trace=file "[email protected]" 2>&1 | Perl -ne 's/^[^"]+"(([^\\"]|\\[\\"nt])*)".*/$1/ && print'

tetapi gagal jika perintah untuk menjalankan melibatkan Sudo. Itu tidak terlalu cerdas (akan lebih baik jika hanya bisa mendaftar file yang ada atau yang memiliki masalah izin atau mengelompokkannya ke dalam file yang dibaca dan file yang ditulis). Juga strace lambat, jadi akan lebih baik dengan pilihan yang lebih cepat.

65
Ole Tange

Saya menyerah dan memberi kode alat saya sendiri. Mengutip dari dokumennya:

SYNOPSIS
    tracefile [-adefnu] command
    tracefile [-adefnu] -p pid

OPTIONS
    -a        List all files
    -d        List only dirs
    -e        List only existing files
    -f        List only files
    -n        List only non-existing files
    -p pid    Trace process id
    -u        List only files once

Ini hanya menampilkan file sehingga Anda tidak perlu berurusan dengan output dari strace.

https://gitlab.com/ole.tange/tangetools/tree/master/tracefile

56
Ole Tange

Anda dapat melacak panggilan sistem dengan strace, tetapi memang ada penalti kecepatan yang tak terhindarkan. Anda perlu menjalankan strace sebagai root jika perintah dijalankan dengan privilege yang ditingkatkan:

Sudo strace -f -o foo.trace su user -c 'mycommand'

Metode lain yang mungkin lebih cepat adalah dengan memuat pustaka yang membungkus fungsi akses sistem file: LD_PRELOAD=/path/to/libmywrapper.so mycommand. LD_PRELOAD variabel lingkungan tidak akan diteruskan ke program yang dipanggil dengan privilege yang ditingkatkan. Anda harus menulis kode perpustakaan pembungkus itu ( inilah contoh dari “Membangun interposer perpustakaan untuk kesenangan dan keuntungan” ); Saya tidak tahu apakah ada kode yang dapat digunakan kembali tersedia di web.

Jika Anda memantau file dalam hierarki direktori tertentu, Anda dapat membuat tampilan sistem file dengan LoggedFS sehingga semua akses melalui tampilan itu dicatat.

loggedfs -c my-loggedfs.xml /logged-view
mycommand /logged-view/somedir

Untuk mengonfigurasi LoggedFS, mulailah dengan konfigurasi sampel yang dikirimkan bersama program dan baca sintaks file konfigurasi LoggedFS .

Kemungkinan lain adalah Linux subsistem audit . Pastikan daemon auditd dimulai, kemudian konfigurasikan apa yang ingin Anda logi auditctl . Setiap operasi yang dicatat dicatat dalam /var/log/audit/audit.log (pada distribusi tipikal). Untuk mulai menonton file tertentu:

auditctl -a exit,always -w /path/to/file

Jika Anda menaruh arloji di direktori, file di dalamnya dan subdirektori secara rekursif juga ditonton. Berhati-hatilah untuk tidak melihat direktori yang berisi log audit. Anda dapat membatasi penebangan untuk proses tertentu, lihat halaman manual auditctl untuk filter yang tersedia. Anda harus menjadi root untuk menggunakan sistem audit.

Saya pikir Anda ingin lsof (mungkin disalurkan ke grep pada program dan itu anak-anak). Ini akan memberi tahu Anda setiap file yang saat ini sedang diakses di sistem file. Untuk informasi tentang file mana yang diakses oleh proses ( dari sini ):

lsof -n -p `pidof your_app`
7
unclejamil

Saya mencobanya tracefile. Bagi saya itu memberi kecocokan jauh lebih sedikit daripada strace ... | sed ... | sort -u Saya sendiri. Saya bahkan menambahkan -s256 Ke strace(1) baris perintah tetapi tidak banyak membantu ...

Kemudian saya mencobanya loggedfs. Pertama gagal karena saya tidak memiliki akses baca/tulis ke direktori saya mencoba login dengannya. Setelah melakukan chmod 755 untuk sementara saya mendapatkan beberapa hit ...

Tetapi, bagi saya, melakukan hal berikut tampaknya bekerja paling baik:

inotifywait -m -r -e OPEN /path/to/traced/directory

Dan kemudian postprocess output setelah menjalankan proses yang menarik.

Ini tidak menangkap file proses akses luar dari direktori dilacak atau ini tidak tahu apakah beberapa proses lain mengakses pohon direktori yang sama, tetapi dalam banyak kasus ini adalah alat yang cukup baik untuk mendapatkan pekerjaan selesai.

EDIT: inotifywait tidak menangkap akses symlink (hanya target setelah symlink diselesaikan). Saya terpana oleh hal ini ketika saya mengarsipkan perpustakaan yang diakses oleh sebuah program untuk digunakan di masa depan. Menggunakan beberapa peretasan Perl glob tambahan untuk memilih symlink di sepanjang pustaka yang diberitahukan untuk menyelesaikan pekerjaan dalam satu kasus tertentu.

EDIT2: setidaknya ketika inotifying file dan symlinks sendiri dari inotifywait command line (mis. inotifywait -m file symlink Atau inotifywait symlink file) Output akan menunjukkan akses ke mana yang pertama di baris perintah (terlepas dari mana, file dari symlink diakses). inotifywait tidak mendukung IN_DONT_FOLLOW - yang, ketika saya coba secara terprogram hanya membuat orang melihat akses ke file (yang mungkin, atau mungkin tidak, menjadi apa yang diharapkan ...) terlepas dari urutan baris perintah

2
Tomi Ollila

Walaupun mungkin tidak memberi Anda cukup kontrol (belum?) Saya telah menulis sebuah program, yang setidaknya sebagian memenuhi kebutuhan Anda, menggunakan fanotify dan unshare linux-kernel untuk memantau hanya file yang dimodifikasi (atau dibaca) oleh proses tertentu dan anak-anaknya . Dibandingkan dengan strace, ini cukup cepat (;

Itu dapat ditemukan di https://github.com/tycho-kirchner/shournal

Contoh di Shell:

$ shournal -e sh -c 'echo hi > foo1; echo hi2 > foo2'
$ shournal -q --history 1
  # ...
  Written file(s):                                                                                                                                                                              
 /tmp/foo1 (3 bytes) Hash: 15349503233279147316                                                                                                                                             
 /tmp/foo2 (4 bytes) Hash: 2770363686119514911    
1
spawn