如果您与--joblog path/to/logfile
并行运行GNU,然后在并行运行时从上述日志文件中删除一行,,则GNU并行将不再能够向其追加以后完成的作业。
执行此MWE:
#!/usr/bin/bash
parallel -j1 -n0 --joblog log sleep 1 ::: $(seq 10) &
sleep 5 && sed -i '$ d' log
如果在执行之前tail -f log
,您会看到并行继续写入该文件。但是,如果10秒钟后cat log
,您将看到大约第三次输入之后,什么也没有写入磁盘上的实际文件。
这背后的原因是什么?有没有一种方法可以从文件中删除某些内容,并使GNU parallel仍然能够对其进行写入?
发生这种情况的一些背景:
使用GNU并行,我使用--sshloginfile
在远程计算机上开始了一些工作。然后,我需要在其中一台计算机上pkill
进行一些工作,因为一位同事需要使用它(后来我从sshloginfile中删除了该计算机,以便并行不会将其重新用于新的运行)。如果pkill
这些进程是在远程计算机上启动的,则它们的Exitval为0(看起来没有问题,它们完成了;您不能说它们已被杀死)。我想立即将它们从作业日志中删除,以便稍后重新启动parallel --resume
时,parallel可以查看作业日志并确定缺少的内容。
结果证明,这是一个坏主意,因为现在我的工作日志已无用。
答案 0 :(得分:1)
@MarkSetchell的评论绝对正确,但根本原因是man sed
撒谎:
-i[SUFFIX], --in-place[=SUFFIX]
edit files in place (makes backup if SUFFIX supplied)
sed -i
不能在适当位置编辑文件。
它的作用是在相同的目录中创建一个临时文件,在进行编辑时将输入文件复制到该临时文件中,最后将该临时文件重命名为输入文件的名称。与此类似:
sed '$ d' log > sedXxO11P
mv sedXxO11P log
很明显,原始日志和sedXxO11P具有不同的inode-让我们将它们称为ino1和ino2。 GNU Parallel已打开ino1,但实际上并不知道ino2的存在。 GNU Parallel会很乐意完全附加到ino1,而不会意识到关闭文件时该文件将消失,因为它已经取消链接。
因此,您需要更改文件的内容而不更改inode:
#!/usr/bin/bash
seq 10 | parallel -j1 -n0 --joblog log sleep 1 &
sleep 5
# Obvious race condition here:
# Anything appended to log before sed is done is lost.
# This can be avoided by suspending parallel while running this
tmp=$RANDOM$$
cp log $tmp
(rm $tmp; sed '$ d' >log) < $tmp
wait
cat log
现在可以使用。但是,别指望它成为受支持的功能。