我正在尝试检测ksh script
是否已在执行,以防止执行第二个实例。
用户cronjob每分钟调用一次脚本:
* * * * * /home/user/job.ksh TESTACTION &>/dev/null
我在剧本开头添加了一名警卫:
#!/usr/bin/ksh
LOGDIR="/home/user"
processes=$(/bin/ps ux | /bin/grep -i "job.ksh TESTACTION" | /bin/grep -v grep | /bin/grep -c "\/usr\/bin\/ksh")
if (( $processes > 1 )); then
datetime=$(/bin/date +'%Y.%m.%d %H:%M:%S')
/bin/echo -e "${datetime} - skipped execution for other ${processes} active process" >> "${LOGDIR}/multiple_ksh_check.log"
exit 0
fi
令我惊讶的是if
条件经常被满足,但并不总是如此,因为我可以从日志文件中获得。
考虑到为了测试目的,我使用此代码片段重现了这个问题,这意味着脚本持续几毫秒,不会持续一分钟,与下一个cronjob调用冲突。
我错过了什么?我该怎么办?
答案 0 :(得分:0)
我遗漏的一点是shell可以在其他进程中生成子shell,这就是ps
找到比预期更多的行的原因。
在@markp和this answer的帮助下,我改写了这样的条件
processes=$(/bin/ps x -o pid,ppid,args | /bin/grep -vw $$ | /bin/grep -i "job.ksh TESTACTION" | /bin/grep -c "\/usr\/bin\/ksh")
if (( $processes > 0 )); then
exit 0
fi
这里要点:
ps
的输出格式化为包含pid和父pid信息
$$
中)grep
次执行1
更改为0
,因为当前流程也从ps
结果中排除