我有 shell 脚本,它等待一些文件从远程计算机到达,当它到达时,它将它们捕获到一个新文件。为此,我使用 while 循环,如下所示:
while true
do
if [ $(find ../Test_Data/local_enc* | wc -l) -eq 2 ]
then
break
else
sleep 0.001
fi
done
cat ../Test_Data/local_enc* > ../Test_Data/All_Enc_Coords.txt
Run Code Online (Sandbox Code Playgroud)
问题是 All_Enc_Coords 文件有时被写入,有时不被写入。我认为这是因为,即使文件中没有数据,find 函数也会返回一些值。
如何保证文件写入成功?以及如何在 while 循环中指定它。这意味着,我希望所有文件都被完全写入,然后对它们进行cat?..我在cat之前使用了sleep 1,发现文件已完全写入,但是有什么方法可以检查这一点吗?
您能否让远程计算机在开始上传文件之前创建一个文件,然后将其删除?
例如使用 ssh(类似可以使用 ftp 或 HTTP PUT 完成):
ssh yourhost touch ../Test_Data/upload-in-progress
scp local_enc* yourhost:../Test_Data/
ssh yourhost rm ../Test_Data/upload-in-progress
Run Code Online (Sandbox Code Playgroud)
然后您的脚本所要做的就是等待正在上传的文件消失。这可以通过睡眠循环来完成,或者可以使用包中的内容inotifywait
来完成inotify-tools
。
注意:如果远程主机在完成上传之前死亡或其脚本被终止,它将留下一个陈旧的上传中文件。在我看来,这是一个比尝试猜测上传何时完成而产生竞争条件的风险要小得多的问题(因为仅在目标计算机上运行的所有解决方案都容易出现)
我最初考虑使用lsof | grep local_enc | wc -l
,但这和你的 一样容易出现竞争find .. | wc -l
。
与使用inotify
或类似的方式获取 Test_Data 目录更改的通知 - 您可以知道该目录中文件何时创建/更改,但不会告诉您上传会话何时完成...但是 inotify 与信号量结合使用文件会起作用。inotify 等待 Test_Data 目录更改,然后 inotify 休眠,直到删除正在进行的上传。
此外,如果远程主机上的上传脚本从 cron 运行,过时的上传中文件将在下次运行时自行修复。或者,您的脚本可以编写为假设任何早于 X 分钟的上传文件已过时,应删除/忽略(inotifywait
有一个-t
或--timeout
选项在这里很有用),但网络延迟或临时中断可能会导致您这里出现问题。