Ubuntu 20.04からCentOS Linux 8までの単純な並列実行を処理するためにbashスクリプトを調整するのに問題があります。スクリプトでは、FIFOから文字列を読み取って共通ファイルに出力する複数の「リーダー」を作成しました。文字列は、基本スクリプトからFIFOに直接渡されます。プロセスをきれいにするためにファイル記述子とロックを使用します。私はまだFIFOに書き込む前にすべての読者が起動するのを待っています。スクリプト全体を最後に配置しました。
スクリプトはUbuntuで完全に実行され、出力は次のようになります(最初の列はリーダーID、2番目の列はリーダーがFIFOから取得することです)。
2 1
4 2
1 3
...
3 4998
2 4999
4 5000
読み取りが完了すると、メッセージは1つずつ送信されます。
CentOSで同じスクリプトを使ってこれを得ました。
4 1
1 7
2 8
...
3 153
4 154
1 155
目立つジャンプがあり、メッセージ2〜6が完全に失われます。さらに、プロセスは155で早期に停止する。
何が起こったのか本当にわからない。どんなアイデアがありますか?
スクリプト:
#!/bin/bash
readers=4
objs=5000
echo "" > output.txt
# Temporary files and fifo
FIFO=$(mktemp -t fifo-XXXX)
START=$(mktemp -t start-XXXX)
START_LOCK=$(mktemp -t lock-XXXX)
FIFO_LOCK=$(mktemp -t lock-XXXX)
OUTPUT_LOCK=$(mktemp -t lock-XXXX)
rm $FIFO
mkfifo $FIFO
# Cleanup trap
cleanall() {
rm -f $FIFO
rm -f $START
rm -f $START_LOCK
rm -f $FIFO_LOCK
rm -f $OUTPUT_LOCK
}
trap cleanall exit
# Reader process
reader() {
ID=$1
exec 3<$FIFO
exec 4<$FIFO_LOCK
exec 5<$START_LOCK
exec 6<$OUTPUT_LOCK
# Signal the reader has started
flock 5
echo $ID >> $START
flock -u 5
exec 5<&-
# Reading loop
while true; do
flock 4
read -su 3 item
read_status=$?
flock -u 4
if [[ $read_status -eq 0 ]]; then
flock 6
echo "$ID $item" >> output.txt
flock -u 6
else
break # EOF reached
fi
done
exec 3<&-
exec 4<&-
exec 6<&-
}
# Spawn readers
for ((i=1;i<=$readers;i++)); do
reader $i &
done
exec 3>$FIFO
# Wait for all the readers
exec 5<$START_LOCK
while true; do
flock 5
started=$(wc -l $START | cut -d \ -f 1)
flock -u 5
if [[ $started -eq $readers ]]; then
break
else
sleep 0.5s
fi
done
exec 5<&-
# Writing loop
for ((i=1;i<=$objs;i++)); do
echo $i 1>&3
done
exec 3<&-
wait
echo "Script done"
exit 0