Со lsof
страницы руководства
Lsof возвращает единицу (1), если обнаружена какая-либо ошибка, включая ошибку при поиске имен команд, имен файлов, интернет-адресов или файлов, имен входа, файлов NFS, PID, PGID или UID, которые было предложено перечислить. Если указана опция -V, lsof будет указывать элементы поиска, которые не удалось отобразить.
Так что это предполагает, что ваше lsof failed for some other reason
предложение никогда не будет выполнено.
Вы пытались просто переместить файл, пока ваш внешний процесс все еще открыт? Если каталог назначения находится в той же файловой системе, то проблем с этим не должно быть, если только вам не нужен доступ к нему по исходному пути от третьего процесса, поскольку базовый индекс будет оставаться прежним. Иначе я думаю, 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
.