1

私は、2 つのファイルで構成されるコードを開発しました。「エンベロープ bash ファイル」は、いくつかのことを実行してログ ファイルに書き込み、その後、ある時点で for ループに遭遇し、その中で 1 つのジョブを実行します。 bsubを使用する時間。そして、ログファイルの名前を入力として取得し(その実行に必要な他の入力値に加えて)、「エンベロープファイル」から受け取った入力値を使用してプロセスXを実行する「内部bashファイル」 . プロセス X が完了すると、「内部スクリプト」は、プロセス X (その特定のシリアル番号を含む) が完了したことをログ ファイルに書き込みます。

エンベロープ ファイルの for ループは 10 回ループするため、少なくとも 10 個の並列プロセスが実行され、並行して実行されます。それらはすべて、同じログ ファイル名を指定して bsub で実行されます。アイデアは、プロセス X の実行が完了すると、すべてが同じログ ファイルに報告されるというものです。

一般的な手順はうまく機能し、各ケースでプロセス X が実行され、プロセス X の完了に関するすべての通知が必要に応じてログ ファイルに蓄積されます。 2 つの並列ランの乱れと出力ラインが互いに衝突しています。
一度に 1 つの並列実行からのみテキストを受信できるように、ログ ファイルをロックしたいと考えています。これは、2 つのプロセスがたまたま同時にログ ファイルに書き込みを行ったために、テキストが混在するケースを回避するためです。

これは、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各ジョブ内で使用してファイルに名前を付けます)。次に、別の「クリーンアップ」ジョブを使用して、すべての出力を 1 つのファイルに連結します。ジョブの依存関係 ( bsub -w) を使用して、他のすべてのジョブが完了した後にクリーンアップ ジョブが実行されるようにすることができます。
  2. 「内部」ジョブ内にロックを実装して、一度に 1 つのみがファイルに書き込むようにします。これは思ったよりずっと簡単です。1 つの方法は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

ただし、ここで重要な注意点を述べておく必要があります。ジョブの 1 つが「ロックを保持している」間に停止した場合 (誰かが間違ったタイミングで kill シグナルを送信したとします)、ディレクトリは決して削除されず、他のすべてのジョブは削除されません。それを作成することはできないので、彼らは永遠に眠り続けるだけです.

于 2015-06-05T19:09:46.663 に答える