cron在运行程序时是否设置了任何变量?如果脚本是由cron运行的,我想跳过一些部分。否则调用这些部分。
我怎么知道Bash脚本是否由cron启动?
ps
记录不充分(尤其是Linux的版本,它支持几种不同的语法样式),并且手册页比大多数工具更加密集和神秘。我怀疑大多数人甚至都没有意识到工具的实用性和多功能性ps
。
cron在运行程序时是否设置了任何变量?如果脚本是由cron运行的,我想跳过一些部分。否则调用这些部分。
我怎么知道Bash脚本是否由cron启动?
ps
记录不充分(尤其是Linux的版本,它支持几种不同的语法样式),并且手册页比大多数工具更加密集和神秘。我怀疑大多数人甚至都没有意识到工具的实用性和多功能性ps
。
Answers:
我不知道cron
默认情况下可以对它的环境执行任何操作,但是可以做一些事情以获得所需的效果。
1)建立与脚本文件的硬链接或软链接,例如,myscript
然后myscript_via_cron
指向同一文件。然后,$0
当您想要有条件地运行或忽略代码的某些部分时,可以测试脚本内部的值。在您的crontab中输入适当的名称,即可设置好。
2)在脚本中添加一个选项,然后在crontab调用中设置该选项。例如,添加一个选项-c
,告诉脚本运行或忽略代码的适当部分,然后-c
在crontab中添加到命令名称。
当然,cron 可以设置任意环境变量,因此您只需RUN_BY_CRON="TRUE"
在crontab中放置一行,然后在脚本中检查其值即可。
从cron运行的脚本不在交互式shell中运行。启动脚本也不都是。区别在于,交互式外壳程序将STDIN和STDOUT附加到tty。
方法1:检查是否$-
包含该i
标志。 i
为交互式外壳设置。
case "$-" in
*i*)
interactive=1
;;
*)
not_interactive=1
;;
esac
方法2:检查是否$PS1
为空。
if [ -z "$PS1" ]; then
not_interactive=1
else
interactive=1
fi
参考:http : //techdoc.kvindesland.no/linux/gnubooks/bash/bashref_54.html
方法3:测试您的tty。它不那么可靠,但是对于简单的cron作业,您应该没问题,因为cron默认情况下不会为脚本分配tty。
if [ -t 0 ]; then
interactive=1
else
non_interactive=1
fi
请记住,您可以使用来强制使用交互式外壳-i
,但是您可能会知道是否正在执行此操作...
bash
我可以访问的都有$-,dash
以及和ksh
。甚至Solaris中受限制的Shell都有它。您要在无法使用的平台上使用它?是什么case "$-" in *i*) echo true ;; *) echo false ;; esac
给你?
首先,获取cron的PID,然后获取当前进程的父PID(PPID),并进行比较:
CRONPID=$(ps ho %p -C cron)
PPID=$(ps ho %P -p $$)
if [ $CRONPID -eq $PPID ] ; then echo Cron is our parent. ; fi
如果脚本是由cron可能已启动的另一个进程启动的,则可以逐步备份父PID,直到获得$ CRONPID或1(init的PID)。
可能是这样的(也许未经测试但可能会起作用<TM>):
PPID=$$ # start from current PID
CRON_IS_PARENT=0
CRONPID=$(ps ho %p -C cron)
while [ $CRON_IS_PARENT -ne 1 ] && [ $PPID -ne 1 ] ; do
PPID=$(ps ho %P -p $PPID)
[ $CRONPID -eq $PPID ] && CRON_IS_PARENT=1
done
来自Deian:这是在RedHat Linux上测试的版本
# start from current PID
MYPID=$$
CRON_IS_PARENT=0
# this might return a list of multiple PIDs
CRONPIDS=$(ps ho %p -C crond)
CPID=$MYPID
while [ $CRON_IS_PARENT -ne 1 ] && [ $CPID -ne 1 ] ; do
CPID_STR=$(ps ho %P -p $CPID)
# the ParentPID came up as a string with leading spaces
# this will convert it to int
CPID=$(($CPID_STR))
# now loop the CRON PIDs and compare them with the CPID
for CRONPID in $CRONPIDS ; do
[ $CRONPID -eq $CPID ] && CRON_IS_PARENT=1
# we could leave earlier but it's okay like that too
done
done
# now do whatever you want with the information
if [ "$CRON_IS_PARENT" == "1" ]; then
CRON_CALL="Y"
else
CRON_CALL="N"
fi
echo "CRON Call: ${CRON_CALL}"
如果脚本文件是由调用的,cron
并且它在第一行中包含一个shell,例如#!/bin/bash
您需要找到用于目的的父/母名称。
1)cron
在您的给定时间调用crontab
,执行shell 2)shell执行您的脚本3)您的脚本正在运行
父PID在bash中可用作变量$PPID
。ps
获取父PID的父PID 的命令是:
PPPID=`ps h -o ppid= $PPID`
但是我们需要命令的名称而不是pid,因此我们调用
P_COMMAND=`ps h -o %c $PPPID`
现在我们只需要测试结果“ cron”
if [ "$P_COMMAND" == "cron" ]; then
RUNNING_FROM_CRON=1
fi
现在您可以在脚本中的任何位置进行测试
if [ "$RUNNING_FROM_CRON" == "1" ]; then
## do something when running from cron
else
## do something when running from shell
fi
祝好运!
P_COMMAND=$(basename -a $(ps h -o comm $PPPID))
没有权威性的答案,但在这里,提示($PS1
)和终端($TERM
)变量相当不错。一些系统已设置,TERM=dumb
而大多数系统将其保留为空,因此我们仅检查以下任一情况:
if [ "${TERM:-dumb}$PS1" != "dumb" ]; then
echo "This is not a cron job"
fi
当没有的值时,以上代码将替换“哑巴”一词$TERM
。因此,条件查询在没有$TERM
或$TERM
设置为“哑”或$PS1
变量不为空时触发。
我已经在Debian 9(TERM=
),CentOS 6.4和7.4(TERM=dumb
)和FreeBSD 7.3(TERM=
)上进行了测试。
ps
?