Daftar file yang diakses oleh suatu program

64

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

Saya mencari sesuatu yang mirip 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 "$@" 2>&1 | perl -ne 's/^[^"]+"(([^\\"]|\\[\\"nt])*)".*/$1/ && print'

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

Ole Tange
sumber
Mengingat penggunaan Anda strace, saya menganggap Anda secara khusus tertarik pada Linux. Benar?
Gilles 'SO- berhenti bersikap jahat'
Linux adalah perhatian utama saya.
Ole Tange

Jawaban:

51

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

Ole Tange
sumber
Terima kasih! Output strace benar-benar tidak dapat dibaca. Saya tidak tahu di mana menemukan dokumen itu - alangkah baiknya jika memiliki opsi bantuan - h /. Saya juga menghargai opsi yang hanya menampilkan pengeditan file, bukan akses.
Xerus
@Xerus Clone gitlab.com/ole.tange/tangetools dan jalankan make && sudo make install. Maka Anda bisa lari man tracefile.
Ole Tange
4
Alat yang bagus. Dikemas, untuk menginstal: yum -y install https://extras.getpagespeed.com/release-el7-latest.rpmdanyum -y install tracefile
Danila Vershinin
27

Anda dapat melacak panggilan sistem dengan strace, tetapi memang ada penalti kecepatan yang tak terelakkan. Anda perlu menjalankan stracesebagai root jika perintah dijalankan dengan hak istimewa yang ditinggikan:

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

Metode lain yang mungkin lebih cepat adalah untuk preload perpustakaan yang membungkus di sekitar fungsi akses filesystem: LD_PRELOAD=/path/to/libmywrapper.so mycommand. The LD_PRELOADvariabel lingkungan tidak akan diteruskan ke program dipanggil dengan hak tinggi. Anda harus menulis kode perpustakaan pembungkus itu ( inilah contoh dari “Membangun perpustakaan penukar 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 mengkonfigurasi LoggedFS, mulailah dengan konfigurasi sampel yang dikirimkan bersama program dan baca sintaksis file konfigurasi LoggedFS .

Kemungkinan lain adalah subsistem audit Linux . Pastikan auditddaemon dimulai, kemudian konfigurasikan dengan apa Anda ingin login 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 auditctlhalaman manual untuk filter yang tersedia. Anda harus menjadi root untuk menggunakan sistem audit.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
LD_PRELOADjuga tidak akan berfungsi pada binari statis.
David Diberi
6

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`
Uncjamil
sumber
11
Tapi itu hanya memberi saya snapshot. Yang saya butuhkan adalah file apa yang coba diakses. Pikirkan situasi di mana sebuah program menolak untuk memulai karena dikatakan "File tidak ada". Bagaimana cara mengetahui file apa yang dicari?
Ole Tange
2

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

Kemudian saya mencobanya loggedfs. Pertama gagal karena saya tidak punya akses baca / tulis ke direktori saya mencoba login dengannya. Setelah melakukan chmod 755 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 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 menyelesaikan pekerjaan.

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 perl tambahan untuk memilih symlink di sepanjang perpustakaan yang diberitahukan untuk menyelesaikan pekerjaan dalam satu kasus tertentu.

EDIT2: setidaknya ketika inotifying file dan symlinks sendiri dari inotifywait baris perintah (misalnya inotifywait -m file symlinkatau inotifywait symlink file) output akan menunjukkan akses ke mana yang pertama di baris perintah (terlepas dari mana, filedari symlinkdiakses). 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 pesanan dalam baris perintah

Tomi Ollila
sumber
"Bagi saya itu memberikan kecocokan jauh lebih sedikit daripada milik saya" Dapatkah Anda membagikan contoh tracefilekehilangan akses file?
Ole Tange
Saya tidak yakin apa yang sebenarnya Anda tanyakan:) ... Jika saya mencoba untuk melihat file di dalam / path / ke / dilacak / direktori / Saya melihat OPEN di inotify output ... TAPI stat (1) ing file yang sepertinya untuk tidak mendapatkan hasil dalam beberapa kasus yang saya coba (saya bertanya-tanya mengapa, ada beberapa caching yang menyembunyikan konten direktori yang dibaca dari tampilan)
Tomi Ollila
Saya mengomentari pos fanotify di bawah ini (saya hanya memiliki 21 reputasi, walaupun saya sudah memiliki akun selama lebih dari satu dekade; membutuhkan 50 untuk berkomentar selalu menjadi kendala bagi saya ...) - fanotify adalah hal yang baik, tetapi tidak bisa berkeliling masalah symlink dereference (yaitu dalam kasus symlinks, file terakhir diakses ditemukan dengan membaca / proc / self / fd / <fd> .. pokoknya +1: ing jawabannya: D
Tomi Ollila
1

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 pada 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    
muncul
sumber