我已经实现了一种识别脚本是否从cron作业运行的方法。它使用ps
来爬上进程树,并确定是否有任何(递归)父命令包含" cron"或" CRON"。
这个解决方案在工作时很慢(比如大约一秒钟)并且每次调用它时都会影响我拥有的所有脚本。我正在寻找更快的解决方案。
我不想在crontab中为脚本添加任何选项,因为我的目标正是在命令行上没有提供通知选项时定义默认通知行为,并且cron作业的默认行为不同。 / p>
是否有一种相当可靠,快速的方法来确定脚本(或其中一个递归父项)是否是从cron作业启动的?
在我的初始帖子之后,我已经重新编写了代码并且能够对其进行改进,但仍然使用了ps
。代码如下,任何建议都是受欢迎的。
is_cron_job()
{
local PS
local CMD
local PID=$$
while :
do
PS="$(ps -h -o ppid,comm -p $PID)"
[[ "$PS" =~ ^[[:space:]]*([0-9]+)[[:space:]]+(.*)$ ]] || return 1
PID="${BASH_REMATCH[1]}"
[[ "$PID" -ge 1 ]] || return 1
CMD="${BASH_REMATCH[2]}"
! [[ "$CMD" =~ crond|CROND ]] || return 0
done
return 1
}
答案 0 :(得分:1)
在运行脚本之前如何在crontab
中设置环境变量?
如果在脚本中设置,则意味着它是从cron运行的。
答案 1 :(得分:0)
如果你的操作系统使用的是systemd,你实际上有一种非常可靠的方法可以找出你是否从cron运行。
loginctl show-session $(</proc/self/sessionid) | sed -n '/^Service=/s/.*=//p'
当且仅当该过程由cron启动时,结果为crond
。
其他方法通常有误报/漏报:
crond
启动包装脚本,然后启动脚本,则更难保证在crontab中设置的环境变量将被保留)crond
的进程实际上都是 cron守护进程并且可能有错误否定,因为不相关的进程将不再是crond
的孩子。答案 2 :(得分:0)
限制速度因子可能是bash循环,因为bash(就像其他shell一样)被解释并且很慢。以下命令可以避免循环,并且可能更快。
如果存在包含字符串cron
的其他进程,则此版本可能会导致误报。我认为你的脚本有同样的问题。
function is_cron_job {
pstree -s $$ | grep -Fip 'cron'
}
pstree -s $$
仅打印当前进程及其祖先(即其名称)。
grep -Fip 'cron'
搜索固定(-F
),不区分大小写(-i
)字符串"cron"
,如果匹配,则返回0
{ {1}}如果没有匹配项(1
)。
我们不是使用-q
的进程名称,而是搜索其PID。
cron
需要解决的问题:
以可靠的方式确定function is_cron_job {
local cronpid="$(pgrep cron)"
if [ $(wc -w <<< "$cronpid") -ne 1 ]; then
echo "No or multiple PIDs for cron!"
exit 1
fi
pstree -sp $$ | grep -Po '\(\d+\)' | grep -Fq "($cronpid)"
}
的PID。
以安全的方式从pstree中提取PID
它将非常不常见,但进程可以命名为cron
。如果这样的过程是当前过程的祖先,并且something(123)funny
是123
的PID,我们可能会再次产生误报。