检查进程A写入的文件是否已准备好由进程B读取

时间:2015-05-27 05:55:23

标签: javascript linux shell wait lsof

我有一个执行k-shell的Java脚本,该脚本调用写入文件A的程序。此后,相同的Java脚本解析输出文件A.没有其他进程读取或写入文件A.

问题是文件A并不总是准备好及时解析,我认为这是因为即使在程序和文件系统之后文件系统仍在完成其工作。调用shell返回。只有在有很多进程在运行时才会发生这种情况。

lsof似乎不适用于我的系统。如果我用编辑器打开文件,lsof会向我显示编辑器进程,但如果我将文件名传递给lsof,我会得到: lsof:找不到文件: filename

我不认为fileLock会起作用,因为在从程序或k-shell返回之前我必须解锁它,到那时文件仍然可能没有被完全关闭。

我的想法是编写一个重命名(mv)文件的短脚本,然后让解析器解析重命名的文件,我的理解是文件在完全写入之前无法重命名。我把mv命令放在while循环中,检查mv命令中的stdOut是否有任何内容,理论上如果它是空的,我们就可以了。

#! /bin/ksh
# Move a file. The idea is that this script will not return until the mv is
# complete. If mv is successful, mv.out.txt should be empty.

mv $1/camber.out $1/camber.out.copy > mv.out.txt
while [[ -s mv.out.txt ]] ; 
do
    echo "mv did not happen"
    mv $1/camber.out $1/camber.out.rename > mv.out.txt
done
echo "mv should have taken place"

exit

我还没有看到mv被阻止的实例。任何评论,建议,提示或侮辱将不胜感激。在此先感谢所有人。

1 个答案:

答案 0 :(得分:2)

我缺乏评论能力,所以答案就是这样。无论如何,它听起来像异步执行的问题 - java程序调用bash脚本,它由OS作为一个单独的程序处理,因此与java程序同时运行。要使一切正常运行,您只需确保bash脚本同步运行 - 也就是说,脚本必须在Java继续之前完成。我相信this所以有关阻止应该做你需要的答案。解决方案是:

ProcessBuilder pb = new ProcessBuilder("myscript.sh");
Process p = pb.start();     // Start the process.
p.waitFor();                // Wait for the process to finish.
System.out.println("Script executed successfully");

这应该强制Java程序休眠,直到bash脚本完成。

正如您在下面的评论中指出的那样,可能需要将相同的逻辑应用于k-shell。您可以使用wait命令(将作业作为可选参数)等待进程(如果您未传入特定作业,则该进程将等待所有子进程完成的过程。)