运行shell脚本时,我想绝对确定它的一个实例在给定时间运行。
我应该使用文件锁机制,例如
touch lockfile
do_work
rm lockfile
那够了吗?
答案 0 :(得分:3)
您可以使用flock
:
(
flock -s 200
# .... commands executed under lock....
)200>/var/lock/mylockfile
它可以在Util-linux下一代包装下使用...... http://en.wikipedia.org/wiki/Util-linux
答案 1 :(得分:3)
由于flock
没有安装在我使用的某些系统上 - 我在Ubuntu(有它)和Mac OS X(没有)之间跳过很多 - 我使用这个简单的框架没有任何实际问题:
LOCK_NAME="MY_GREAT_BASH_SCRIPT"
LOCK_DIR='/tmp/'${LOCK_NAME}.lock
PID_FILE=${LOCK_DIR}'/'${LOCK_NAME}'.pid'
if mkdir ${LOCK_DIR} 2>/dev/null; then
# If the ${LOCK_DIR} doesn't exist, then start working & store the ${PID_FILE}
echo $$ > ${PID_FILE}
echo "Hello world!"
rm -rf ${LOCK_DIR}
exit
else
if [ -f ${PID_FILE} ] && kill -0 $(cat ${PID_FILE}) 2>/dev/null; then
# Confirm that the process file exists & a process
# with that PID is truly running.
echo "Running [PID "$(cat ${PID_FILE})"]" >&2
exit
else
# If the process is not running, yet there is a PID file--like in the case
# of a crash or sudden reboot--then get rid of the ${LOCK_DIR}
rm -rf ${LOCK_DIR}
exit
fi
fi
我的想法是,我拥有echo "Hello world!"
的一般核心是你脚本的核心所在。其余部分基本上是基于mkdir
的锁定机制。对概念is in this answer的一个很好的解释:
mkdir 会创建一个目录(如果该目录尚不存在),如果存在, 它设置退出代码。更重要的是,它完成了所有这一切 原子动作使它适合这种情况。
答案 2 :(得分:1)
它认为你的逻辑更像是:
if [ ! -e lockfile ]; then
touch lockfile
do_work
rm lockfile
fi
但请注意,即使这还不够。实际上,它为微妙的错误铺平了道路。由于整个事情不是原子的,第二个过程也可能在if
子句之后但在touch
之前开始。
一个不太天真的实现你的想法会尝试锁定获取操作的原子性。这可以在Bash中完成。
一个可能的解决方案是noclobber
选项,它禁止写入现有文件,从而在更多的情况下完成if
子句和touch
命令原子时尚。
我的锁定获取代码将如下所示:
if ! ( set -o noclobber; echo > lockfile ) exit
答案 3 :(得分:0)
创建锁定文件或失败(无竞争条件),同时方便地在程序的锁定文件中记录shell的PID。如果程序被赋予任何列出的信号
,则清除#!/bin/bash
# Garbage clean up with trap given any of these SIGNALS
# INT Pressing Control-C kill -2 pid
# TERM Termination signal kill -15 pid
# EXIT Shell exit
LockFile="/tmp/${0}.lock"
if ( set -o noclobber; echo "$$" > "$LockFile") 2> /dev/null; then
trap 'rm -f "$LockFile"; exit $?' INT TERM EXIT
else
echo -e "Program \"$0\" already running"
exit 1
fi