当前位置:  开发笔记 > 编程语言 > 正文

PHP可以检测它是从cron作业还是从命令行运行的?

如何解决《PHP可以检测它是从cron作业还是从命令行运行的?》经验,为你挑选了9个好方法。

我正在寻找PHP的方法来检测脚本是从shell上的手动调用(我登录并运行它)运行,还是从crontab条目运行.

我有各种用PHP编写的维护类型脚本,我已设置在我的crontab中运行.偶尔,我需要提前手动运行它们,或者如果出现故障/损坏,我需要运行它们几次.

这个问题是我也有一些外部通知设置到任务(发布到Twitter,发送电子邮件等),我不想每次手动运行脚本时发生.

我正在使用php5(如果它很重要),它是一个相当标准的Linux服务器环境.

有任何想法吗?



1> Paul Stone..:

而不是检测脚本何时从crontab运行,它可能更容易检测您何时手动运行它.

从命令行运行脚本时,会设置许多环境变量(在$ _ENV数组中).这些将根据您的服务器设置和您的登录方式而有所不同.在我的环境中,手动运行脚本时设置以下环境变量,这些变量在从cron运行时不存在:

术语

SSH_CLIENT

SSH_TTY

SSH_CONNECTION

还有其他人.因此,例如,如果您始终使用SSH访问该框,则以下行将检测脚本是否从cron运行:

$cron = !isset($_ENV['SSH_CLIENT']);


似乎默认情况下,默认的php.ini已经发生变化,默认情况下不会填充$ _ENV全局.一种安全的方法是使用getenv('SSH_CLIENT') - 有关详细信息,请参阅此处http://stackoverflow.com/questions/3780866/why-is-my-env-empty

2> MingalevME..:
if (php_sapi_name() == 'cli') {   
   if (isset($_SERVER['TERM'])) {   
      echo "The script was run from a manual invocation on a shell";   
   } else {   
      echo "The script was run from the crontab entry";   
   }   
} else { 
   echo "The script was run from a webserver, or something else";   
}


我不确定最近几年是否有所改变,但是在我的系统(运行Litespeed的CentOS 6.6,PHP 5.4.38)上,当通过cron运行时,php_sapi_name()返回cgi-fcgi。换句话说,如果您的系统类似于我的系统,则可能要用以下内容替换此答案的第一行:`if(php_sapi_name()=='cli'|| php_sapi_name()=='cgi-fcgi') {`。

3> Matthew Scha..:

您可以设置一个额外的参数,或在crontab中添加一行,也许:

CRON=running

然后,您可以检查环境变量"CRON".另外,尝试检查$ SHELL变量,我不确定cron是否设置了它.



4> davethebrave..:

这是我用来发现脚本执行位置的方法.查看php_sapi_name函数以获取更多信息:http://www.php.net/manual/en/function.php-sapi-name.php

$sapi_type = php_sapi_name();
if(substr($sapi_type, 0, 3) == 'cli' || empty($_SERVER['REMOTE_ADDR'])) {
    echo "shell";
} else {
    echo "webserver";
}

编辑: 如果php_sapi_name()不包括cli(可能是clicli_server),那么我们检查是否$_SERVER['REMOTE_ADDR']为空.从命令行调用时,该值应为空.



5> 小智..:

我认为最通用的解决方案是在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";



6> 小智..:

正确的方法是在例如stdout文件描述符上使用posix_isatty()函数,如下所示:

if (posix_isatty(STDOUT))
    /* do interactive terminal stuff here */



7> paxdiablo..:

我不知道具体的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下运行 - 您可能忘记在交互式会话中执行此操作并填充内容.



8> Dominic Rodg..:

不是我所知道的 - 可能最简单的解决方案是自己提供一个额外的参数来告诉脚本它是如何被调用的.



9> 小智..:

爬行。尝试

if (!isset($_SERVER['HTTP_USER_AGENT'])) {

代替。PHP Client Binary不发送它。仅当PHP用作模块(即apache)时,术语类型才有效,但通过CGI接口运行php时,请使用上面的示例!

推荐阅读
赛亚兔备_393
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有