З lsof
чоловічої сторінки
Lsof повертає один (1), якщо виявлено будь-яку помилку, у тому числі невдало знайти імена команд, імена файлів, інтернет-адреси чи файли, імена входу, файли NFS, PID, PGID або UID, про які було запропоновано перерахувати. Якщо параметр -V заданий, lsof вкаже пошукові елементи, які не вдалося внести до списку.
Тож це дозволило б припустити, що ваш lsof failed for some other reason
пункт ніколи не буде виконаний.
Ви намагалися просто перемістити файл, поки ваш зовнішній процес все ще відкритий? Якщо каталог призначення знаходиться в одній і тій же файловій системі, то з цим не повинно виникнути жодних проблем, якщо тільки вам не потрібно буде отримати доступ до нього під початковим шляхом з третього процесу, оскільки базовий inode залишиться тим самим. Інакше я думаю mv
, що все-таки провалиться.
Якщо вам дійсно потрібно дочекатися, коли ваш зовнішній процес закінчиться файлом, краще використовувати команду, яка блокує замість багаторазового опитування. У Linux ви можете використовувати inotifywait
для цього. Наприклад:
inotifywait -e close_write /path/to/file
Якщо потрібно використовувати lsof
(можливо, для портативності), ви можете спробувати щось на кшталт:
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
Оновлення
Як зазначає @JohnWHSmith нижче, найбезпечніший дизайн завжди використовує lsof
цикл, як зазначено вище, можливо, що більш ніж один процес матиме файл, відкритий для запису (приклад може бути погано записаним демоном індексації, який відкриває файли з прочитаним / пишіть прапор, коли його дійсно слід читати лише). inotifywait
все ще можна використовувати замість сну, хоча просто замініть спальну лінію inotifywait -e close /path/to/file
.