我在调整 bash 脚本来处理从 Ubuntu 20.04 到 CentOS Linux 8 的简单并行执行时遇到问题。在脚本中,我生成了多个“读取器”,它们从 FIFO 读取字符串并将其输出到公共文件中。字符串直接从主脚本传递到 FIFO。我使用文件描述符和锁来使进程变得干净。我还在等待所有读取器在写入 FIFO 之前启动。我将整个脚本放在最后。
该脚本在 Ubuntu 上完美运行,输出如下(第一列是读卡器 ID,第二列是读卡器从 FIFO 获取的内容)
2 1
4 2
1 3
...
3 4998
2 4999
4 5000
读取完毕,消息一一传送。
在 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