从几个并行的 LSF bsub 作业写入一个输出文件,避免同时写入
Write to one output file from a few parallel LSF bsub jobs, avoiding writing at the same time
我开发了一个由两个文件组成的代码:
一个 'envelop bash file',它做一些事情并写入一个日志文件,然后在某个时候 运行s 进入一个 for 循环,在这个循环中它使用 bsub 一次执行一个作业。
'an internal bash file',它将日志文件的名称作为输入(除了执行所需的其他输入值),并执行进程 X(使用它从 'envelop file' 接收到的输入值) .
进程 X 完成后,'internal script' 将进程 X(及其特定序列号)已完成写入日志文件。
由于信封文件的 for 循环循环了 10 次,因此至少有 10 个并行进程正在执行并且 运行 并行,并且它们都在给定相同日志文件的情况下使用 bsub 执行姓名。这个想法是,一旦他们完成了进程 X 的执行,他们都会向同一个日志文件报告。
一般程序运行良好,在每种情况下进程 X 都在执行,并且日志文件根据需要累积有关进程 X 完成的所有通知。但是,在某些情况下,我们看到写入日志文件受到干扰,两个并行 运行 的输出行相互 运行ning。
我想以一种允许它一次只从一个并行 运行 接收文本的方式锁定日志文件。这个想法是为了避免由于两个进程恰好同时写入日志文件而导致文本混合的情况。
这是我的信封文件中调用 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
如果有任何有用的解决方案,我将不胜感激!
我可以想到以下几种方法:
- 让每个作业将其输出写入不同的文件(在每个作业中使用
$LSB_JOBID
来命名文件)。然后使用另一个 "cleanup" 作业将所有输出连接到一个文件中。您可以使用作业依赖项 (bsub -w
) 来确保清理作业在所有其他作业完成后运行。
- 在您的 "internal" 作业中实施锁定,以确保一次只有其中一个写入文件。这比听起来简单得多,一种方法是让每个作业在写入文件之前尝试创建与
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
我应该在这里提一个重要的警告:如果你的一个作业在 "holding the lock" 期间终止(比如有人在错误的时间向它发送终止信号)那么它永远不会删除目录和所有其他工作无法创建它,所以他们将永远沉睡。
我开发了一个由两个文件组成的代码: 一个 'envelop bash file',它做一些事情并写入一个日志文件,然后在某个时候 运行s 进入一个 for 循环,在这个循环中它使用 bsub 一次执行一个作业。 'an internal bash file',它将日志文件的名称作为输入(除了执行所需的其他输入值),并执行进程 X(使用它从 'envelop file' 接收到的输入值) . 进程 X 完成后,'internal script' 将进程 X(及其特定序列号)已完成写入日志文件。
由于信封文件的 for 循环循环了 10 次,因此至少有 10 个并行进程正在执行并且 运行 并行,并且它们都在给定相同日志文件的情况下使用 bsub 执行姓名。这个想法是,一旦他们完成了进程 X 的执行,他们都会向同一个日志文件报告。
一般程序运行良好,在每种情况下进程 X 都在执行,并且日志文件根据需要累积有关进程 X 完成的所有通知。但是,在某些情况下,我们看到写入日志文件受到干扰,两个并行 运行 的输出行相互 运行ning。
我想以一种允许它一次只从一个并行 运行 接收文本的方式锁定日志文件。这个想法是为了避免由于两个进程恰好同时写入日志文件而导致文本混合的情况。
这是我的信封文件中调用 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
如果有任何有用的解决方案,我将不胜感激!
我可以想到以下几种方法:
- 让每个作业将其输出写入不同的文件(在每个作业中使用
$LSB_JOBID
来命名文件)。然后使用另一个 "cleanup" 作业将所有输出连接到一个文件中。您可以使用作业依赖项 (bsub -w
) 来确保清理作业在所有其他作业完成后运行。 - 在您的 "internal" 作业中实施锁定,以确保一次只有其中一个写入文件。这比听起来简单得多,一种方法是让每个作业在写入文件之前尝试创建与
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
我应该在这里提一个重要的警告:如果你的一个作业在 "holding the lock" 期间终止(比如有人在错误的时间向它发送终止信号)那么它永远不会删除目录和所有其他工作无法创建它,所以他们将永远沉睡。