Dari lsof
halaman manual
Lsof mengembalikan satu (1) jika ada kesalahan yang terdeteksi, termasuk kegagalan menemukan nama perintah, nama file, alamat Internet atau file, nama login, file NFS, PID, PGID, atau UID yang diminta untuk dicantumkan. Jika -Voption ditentukan, lsof akan menunjukkan item pencarian yang gagal dicantumkan.
Jadi itu menunjukkan bahwa lsof failed for some other reason
Anda klausa tidak akan pernah dieksekusi.
Sudahkah Anda mencoba memindahkan file sementara proses eksternal Anda masih terbuka? Jika direktori tujuan berada pada sistem file yang sama, maka seharusnya tidak ada masalah dengan melakukannya kecuali jika Anda perlu mengaksesnya di bawah jalur asli dari proses ketiga karena inode yang mendasarinya akan tetap sama. Kalau tidak, saya pikir mv
toh akan gagal.
Jika Anda benar-benar harus menunggu hingga proses eksternal Anda selesai dengan file tersebut, Anda lebih baik menggunakan perintah yang memblokir daripada polling berulang kali. Di Linux, Anda dapat menggunakan inotifywait
untuk ini. Misalnya:
inotifywait -e close_write /path/to/file
Jika Anda harus menggunakan lsof
(mungkin untuk portabilitas), Anda dapat mencoba sesuatu seperti:
until err_str=$(lsof /path/to/file 2>&1 >/dev/null); do
if [ -n "$err_str" ]; then
# lsof printed an error string, file may or may not be open
echo "lsof: $err_str" >&2
# tricky to decide what to do here, you may want to retry a number of times,
# but for this example just break
break
fi
# lsof returned 1 but didn't print an error string, assume the file is open
sleep 1
done
if [ -z "$err_str" ]; then
# file has been closed, move it
mv /path/to/file /destination/path
fi
Perbarui
Seperti yang dicatat oleh @JohnWHSmith di bawah ini, desain teraman akan selalu menggunakan lsof
loop seperti di atas karena ada kemungkinan bahwa lebih dari satu proses akan membuat file terbuka untuk ditulis (contoh kasus mungkin daemon pengindeksan yang ditulis dengan buruk yang membuka file dengan flag baca/tulis padahal seharusnya hanya dibaca saja). inotifywait
masih bisa digunakan sebagai pengganti sleep, cukup ganti baris sleep dengan inotifywait -e close /path/to/file
.
Sebagai pendekatan alternatif, ini adalah kasus yang sempurna untuk pipa - proses kedua akan memproses keluaran dari proses pertama segera setelah tersedia, daripada menunggu proses penuh selesai:
process1 input_file.dat | process2 > output_file.dat
Keuntungan:
- Jauh lebih cepat secara umum:
- Tidak harus menulis dan membaca dari disk (hal ini dapat dihindari jika Anda menggunakan ramdisk).
- Harus menggunakan sumber daya mesin secara lebih lengkap.
- Tidak ada file perantara untuk dihapus setelah selesai.
- Tidak perlu penguncian yang rumit, seperti di OP.
Jika Anda tidak memiliki cara untuk membuat pipa secara langsung tetapi Anda memiliki GNU coreutils Anda dapat menggunakan ini:
tail -F -n +0 input_file.dat | process2 > output_file.dat
Ini akan mulai membaca file input dari awal, tidak peduli seberapa jauh proses pertama adalah melalui penulisan file (meskipun belum dimulai atau sudah selesai).