PHP可以检测它是从cron作业还是从命令行运行吗?
我正在寻找PHP的方法来检测脚本是通过shell上的手动调用运行的(我登录并运行它),还是通过crontab条目运行的 我有各种用php编写的维护类型脚本,这些脚本已设置为在crontab中运行。偶尔,我需要提前手动运行它们,或者如果出现故障/故障,我需要运行它们几次 问题是,我也在任务中设置了一些外部通知(发布到twitter、发送电子邮件等),我不希望每次手动运行脚本时都出现这些通知 我使用的是php5(如果有必要的话),它是一个相当标准的linux服务器环境PHP可以检测它是从cron作业还是从命令行运行吗?,php,cron,Php,Cron,我正在寻找PHP的方法来检测脚本是通过shell上的手动调用运行的(我登录并运行它),还是通过crontab条目运行的 我有各种用php编写的维护类型脚本,这些脚本已设置为在crontab中运行。偶尔,我需要提前手动运行它们,或者如果出现故障/故障,我需要运行它们几次 问题是,我也在任务中设置了一些外部通知(发布到twitter、发送电子邮件等),我不希望每次手动运行脚本时都出现这些通知 我使用的是php5(如果有必要的话),它是一个相当标准的linux服务器环境 有什么想法吗?据我所知,可能最
有什么想法吗?据我所知,可能最简单的解决方案是自己提供一个额外的参数来告诉脚本它是如何被调用的。我会查看
$\u ENV
(var\u dump()it)并检查运行它时与运行cronjob时是否有区别。除此之外,我认为没有一个“官方”开关可以告诉您发生了什么。在cron命令中,将?source=cron
添加到脚本路径的末尾。然后,在脚本中,选中$\u GET['source']
编辑:抱歉,这是一个shell脚本,因此无法使用qs。我认为,您可以以
php script.php arg1 arg2
的形式传递参数,然后使用$argv
读取它们。您可以设置一个额外的参数,或者在crontab中添加一行,也许:
CRON=running
然后可以检查环境变量中的“CRON”。另外,请尝试检查$SHELL变量,我不确定/cron是否将其设置为。我不知道PHP的具体情况,但您可以沿着流程树走,直到找到init或cron 假设PHP可以获得自己的进程ID并运行外部命令,那么应该执行
ps-ef | grep pid
,其中pid是您自己的进程ID,并从中提取父进程ID(PPID)
然后对该PPID执行相同的操作,直到到达作为父级的cron或作为父级的init
例如,这是我的流程树,您可以看到所有权链,1->6386->6390->6408
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 16:21 ? 00:00:00 /sbin/init
allan 6386 1 0 19:04 ? 00:00:00 gnome-terminal --geom...
allan 6390 6386 0 19:04 pts/0 00:00:00 bash
allan 6408 6390 0 19:04 pts/0 00:00:00 ps -ef
在cron下运行的相同进程如下所示:
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 16:21 ? 00:00:00 /sbin/init
root 5704 1 0 16:22 ? 00:00:00 /usr/sbin/cron
allan 6390 5704 0 19:04 pts/0 00:00:00 bash
allan 6408 6390 0 19:04 pts/0 00:00:00 ps -ef
这种“向进程树上走”的解决方案意味着您不必担心引入一个人工参数来指示您是否在cron下运行-您可能会忘记在交互式会话中执行此操作并将其填充起来。而不是检测脚本何时从crontab运行,当您手动运行它时,可能更容易检测 从命令行运行脚本时,会设置许多环境变量(在$\u ENV数组中)。这些是什么取决于您的服务器设置和登录方式。在我的环境中,手动运行脚本时会设置以下环境变量,而从cron运行脚本时不存在这些变量:
- 术语
- SSH_客户端
- 嘘
- SSH\u连接
$cron=!isset($_ENV['SSH_CLIENT'])
$\u服务器['SESSIONNAME']
包含控制台(如果从CLI运行)。也许这会有所帮助。我认为最好在命令行中添加一个不需要手动运行的附加选项来运行cron commmand
if(!$_SERVER['HTTP_HOST']) {
blabla();
}
cron可以做到:
command ext_updates=1
command
手册可以:
command ext_updates=1
command
只需在脚本本身中添加一个选项,使ext_updates参数的默认值为false 在我的环境中,我发现TERM
是在$\u SERVER
中设置的,如果从命令行运行,但如果通过Apache作为web请求运行,则没有设置。我将其放在脚本顶部,可以从命令行运行,也可以通过web浏览器访问:
if (isset($_SERVER{'TERM'}))
{
class::doStuffShell();
}
else
{
class::doStuffWeb();
}
正确的方法是在标准文件描述符上使用posix_isatty()函数,如下所示:
if (posix_isatty(STDOUT))
/* do interactive terminal stuff here */
posix_isatty(STDOUT)返回FALSE
如果cli调用的输出被重定向(管道或文件).我很容易。。。只需计数($\u SERVER['argc'])
如果结果大于零,则服务器将耗尽。您只需向$\u服务器['argv']
添加自定义变量,如“CronJob”=true代码>令人毛骨悚然。试一试
if (!isset($_SERVER['HTTP_USER_AGENT'])) {
相反。PHP客户端二进制文件不发送它。术语类型仅在PHP用作模块(即apache)时有效,但在通过CGI接口运行PHP时,请使用上面的示例 下面是我用来发现脚本从何处执行的内容。有关更多信息,请参阅php_sapi_name函数:
编辑:
如果php\u sapi\u name()
不包括cli(可以是cli或cli\u服务器),那么我们检查$\u服务器['REMOTE\u ADDR']
是否为空。当从命令行调用时,它应该是空的。我认为最通用的解决方案是在cron命令中添加一个环境变量,并在代码中查找它。它将在每个系统上工作
例如,如果cron执行的命令为:
"/usr/bin/php -q /var/www/vhosts/myuser/index.php"
换成
"CRON_MODE=1 /usr/bin/php -q /var/www/vhosts/myuser/index.php"
然后您可以在代码上检查它:
if (!getenv('CRON_MODE'))
print "Sorry, only CRON can access this script";
这很容易。Cron守护进程始终导出MAILTO
环境变量。检查它是否存在并且具有非空值-然后从cron运行
getenv('TERM')
填充SO的30个字符分钟。另一个选项是测试一个特定的环境变量,该变量在通过web调用php文件时设置,如果由命令行运行则不设置
在我的web服务器上,我正在测试APACHE_RUN_DIR环境变量是否设置如下:
if (isset($_ENV["APACHE_RUN_DIR"])) {
// I'm called by a web user
}
else {
// I'm called by crontab
}
为了确保它能在您的web服务器上工作,您可以使用以下语句在web服务器上放置一个虚拟php文件:
<?php var_dump($_ENV); ?>
比较
/usr/bin/php /var/www/yourpath/dummy.php