1

我开发了一个由两个文件组成的代码:一个“信封 bash 文件”,它做一些事情并写入一个日志文件,然后在某个时候运行到一个 for 循环中,它在其中执行一项工作一次使用 bsub。和“一个内部 bash 文件”,它获取日志文件的名称作为输入(除了其执行所需的其他输入值),并执行进程 X(使用它从“信封文件”接收到的输入值. 一旦进程 X 完成,“内部脚本”将进程 X(及其特定序列号)写入日志文件。

由于信封文件的 for-loop 循环了 10 次,因此至少有 10 个并行进程正在执行并并行运行,并且它们都在给定相同的日志文件名的情况下使用 bsub 执行。这个想法是,一旦他们完成了 Process X 的执行,他们都会向同一个日志文件报告。

一般过程运行良好,并且在每种情况下都在执行进程 X,并且日志文件根据需要累积有关进程 X 完成的所有通知。但是,在某些情况下,我们看到写入日志文件得到两条平行运行的干扰线和输出线相互碰撞。
我想以允许它一次仅从一个并行运行接收文本的方式锁定日志文件。这个想法是为了避免由于两个进程恰好同时写入日志文件而导致文本混合的情况。

这是我的信封文件中调用 bsub 的部分(我将内容减少到最低限度):

for ((i=1;i<=$batchesnumber; i++));
do
   bsub -J $SerialName -q normal "bash FetchFasta.bash $genome_fa ${SerialFileName}".bed" $logfile"
done

这是我的内部文件中回显到日志文件的部分:

( 
echo "~~~~~~~~~~~~~~~~~~"
echo "^^^^^^^^^^^^^^^^^^"
echo -n "Completed running "; bedtools -version
echo "bedtools getfasta -s -fi $genome_fasta -bed $mySerialFile -fo ${mySerialFile%.*}".fa" "
echo "Run's completion time is: $timedate"
echo -e "~~~~~~~~~~~~~~~~~~\n"
) >> $logfile

我将不胜感激任何有用的解决方案!

4

1 回答 1

2

我可以想到几种方法来解决这个问题:

  1. 让每个作业将其输出写入不同的文件($LSB_JOBID在每个作业内使用来命名文件)。然后使用另一个“清理”作业将所有输出连接到一个文件中。您可以使用作业依赖项 ( bsub -w) 来确保清理作业在所有其他作业完成后运行。
  2. 在您的“内部”作业中实施锁定,以确保一次只有其中一个写入文件。这比听起来简单得多,一种方法是让每个作业mkdir在写入文件之前尝试创建相同的目录,然后在完成后删除目录。如果他们无法创建目录,那是因为另一个作业首先到达它并且当前正在写入文件。

这是说明 bash 中的 #2 的片段:

# Try to get the lock every second
while ! mkdir lock &> /dev/null ; do
     sleep 1
done

# Got the lock, write to the logfile
echo blahblahblah >> $logfile

# Release the lock
rmdir lock

不过我应该在这里提一个重要的警告:如果你的一个工作在它“持有锁”时死掉了(比如有人在错误的时间向它发送了一个终止信号),那么它永远不会删除目录并且所有其他工作都不会无法创造它,所以他们只会永远沉睡。

于 2015-06-05T19:09:46.663 回答