我已经实现了一种方法来识别脚本是否从cron作业运行。它使用ps
向上爬进程树,并识别是否有任何(递归)父命令包含“cron”或“CRON”。
这个解决方案在工作时很慢(比如说,大约一秒钟),并且每次调用它们都会影响我的所有脚本。我正在寻找更快的解决方案。
我不想在crontab内的脚本中添加任何选项,因为我的目标是在命令行上没有提供通知选项时定义默认的通知行为,并使该默认行为与cron作业不同。
是否有一种合理可靠、快速的方法来确定脚本(或它的递归父脚本)是否是从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
}
3条答案
按热度按时间8e2ybdfx1#
在运行脚本之前,在
crontab
中设置一个环境变量如何?如果它在脚本中设置,则意味着它是从cron运行的。
hpxqektj2#
如果你的操作系统使用的是systemd,你实际上有一个非常可靠的方法来确定你是否在从cron运行。
当且仅当进程由cron启动时,结果将是
crond
。其他方法通常具有假阳性/假阴性:
crond
启动一个 Package 器脚本,然后启动您的脚本,则很难保证crontab中设置的环境变量将被保留)crond
的进程实际上 * 都是 * cron守护进程,并且可能会有误报,因为被拒绝的进程将不再是crond
的子进程。xnifntxz3#
限制速度的因素可能是bash循环,因为bash(像其他shell一样)是解释性的,速度很慢。以下命令避免了循环,并且可能更快。
不安全版本
如果有其他进程包含字符串
cron
,此版本可能会导致误报。我觉得你的剧本也有同样的问题。pstree -s $$
仅打印当前进程及其祖先(即它们的名称)。grep -Fip 'cron'
搜索固定(-F
)、不区分大小写(-i
)的字符串"cron"
,如果匹配则返回0
,如果不匹配则返回1
(-q
)。安全版本
我们不使用
cron
的进程名,而是搜索它的PID。待修复问题:
cron
的PID。这可能是非常罕见的,但是一个进程可以被命名为
something(123)funny
。如果这样的进程是当前进程的祖先,并且123
是cron
s PID,则可能再次产生误报。