GNU并行:从作业日志中删除行会破坏并行更新行

时间:2018-11-15 19:25:10

标签: gnu-parallel

如果您与--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可以查看作业日志并确定缺少的内容。

结果证明,这是一个坏主意,因为现在我的工作日志已无用。

1 个答案:

答案 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

现在可以使用。但是,别指望它成为受支持的功能。