proc1.sh
#!/bin/sh
touch /tmp/proc1.signature.mutex
#do something for long time
sleep 100
rm -rf /tmp/proc1.signature.mutex
proc2.sh
#!/bin/sh
touch /tmp/proc2.signature.mutex
#do something for long time
sleep 100
rm -rf /tmp/proc2.signature.mutex
proc3.sh
#!/bin/sh
touch /tmp/proc3.signature.mutex
#do something for long time
sleep 100
rm -rf /tmp/proc3.signature.mutex
核心文件
现在有没有办法等待使用循环或其他方式删除 /tmp/proc[?][*].signature.mutex 所有此类文件,然后继续进一步执行
如何实现core.sh的目标
答案1
互斥锁是一种互斥锁。您的procN.sh
脚本在“锁定”之前从不测试互斥锁是否由另一个进程持有。
如果您core.sh
启动其他脚本,那么它很容易等待它们完成:
#!/bin/sh
./proc1.sh &
./proc2.sh &
./proc3.sh &
wait
# other processing
这完全消除了对锁定文件的需要。如果不可能,请考虑
#!/bin/sh
while [ -e "$HOME/locks/proc1.signature.mutex" ] ||
[ -e "$HOME/locks/proc2.signature.mutex" ] ||
[ -e "$HOME/locks/proc3.signature.mutex" ]
then
echo 'waiting...'
sleep 10
done
# other processing
为了避免脚本因非自然原因死亡而留下文件procN.sh
,请使用陷阱:
#!/bin/sh
lockfile="$HOME/locks/proc1.signature.mutex"
while [ -e "$lockfile" ]; do
echo 'Can not get lock. Waiting...' >&2
sleep 10
done
## alternatively:
# [ -e "$lockfile" ] && { echo 'something is wrong' >&2; exit 1; }
trap 'rm "$lockfile"; exit' EXIT INT TERM HUP
touch "$lockfile"
# etc.
# no need to rm the lock file at the end
-e "$lockfile"
请注意,测试和测试之间有一个空格,touch
其中另一个进程可能会锁定同一文件。
为了避免这种情况,请使用锁目录反而:
#!/bin/sh
lockdir="$HOME/locks/proc1.signature.mutex"
while ! mkdir "$lockdir"; do
echo 'Can not get lock. Waiting...' >&2
sleep 10
done
trap 'rmdir "$lockdir"; exit' EXIT INT TERM HUP
# etc.
# no need to rmdir the lock dir at the end
您也可以以类似的方式使用符号链接。
请注意,我使用了下面的路径$HOME
作为锁定文件/目录。如果使用/tmp
,任何用户都可能通过简单地创建正确的文件/目录来锁定您的脚本,使其无法运行。
答案2
我写https://github.com/acbits/sema正是出于这个原因。很久没关注SE了,才注意到这个问题。我只在Linux上测试过
答案3
使用https://github.com/acbits/sema在 shell 脚本中使用信号量。
A.sh
_____________________________________________
#!/bin/sh
echo A.sh started
sema -c S1
./B.sh &
echo A.sh more work
echo waiting for B.sh to finish
sema -w S1
echo B.sh finished execution
echo A.sh do more work
# cleanup semaphores
sema -d S1
_____________________________________________
B.sh
_____________________________________________
#!/bin/sh
echo Hello from B.sh
sleep 5
sema -r S1
echo Bye bye from B.sh
____________________________________________