从lsof
手册页
如果检测到任何错误,则Lsof将返回一(1),包括未能找到要求列出的命令名称,文件名,Internet地址或文件,登录名,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
循环,因为可能有多个进程打开了要写入的文件(示例情况可能是编写不良的索引守护程序,该后台驻留程序打开了具有读取操作的文件/ write标志,则该标志应为只读)。inotifywait
仍然可以代替睡眠使用,只需用替换睡眠行inotifywait -e close /path/to/file
。