从 cron 运行 php 没有作为 CLI 运行

2022-01-04 00:00:00 cron php

在从 cron 运行的 php 脚本开始超时后,我注意到了这个问题,但是当它从命令行手动运行时,这不是问题.(PHP 默认 CLI 的 max_execution_time 为 0)

I noticed this problem after a php script ran from cron started to timeout but it was not an issue when it was ran manually from command line. (PHP has max_execution_time is 0 for CLI by default)

所以我尝试运行一个简单的 cron,例如:

So I tried to run a simple cron such:

50 8 * * * php -q /tmp/phpinfo.php > /tmp/phpinfo

脚本只会调用 phpinfo().

The script would just call phpinfo().

令人惊讶的是它以html格式写出phpinfo,这表明它没有作为CLI运行.输出中的 max_execution_time 为 30.

Surprisingly it wrote out phpinfo in html format, which suggested that it was not run as CLI. And max_execution_time was 30 in the output.

从命令行手动运行脚本,例如

Running the script manually from command line such

php -q /tmp/phpinfo.php | less

以文本格式写出php信息,输出中max_execution_time为0.

wrote out the php info in text format and max_execution_time was 0 in the output.

我知道某处一定有配置问题,但我就是找不到问题出在哪里.这发生在我完全控制的生产服务器上.在我的开发机器上从 cron 运行相同的脚本工作正常.

I know there must be a configuration issue somewhere, but I just could not find where the problem is. This is happening on a production server, which I have a complete control of. Running the same script from cron on my development machine worked fine.

这里是差异的总结

function             | CLI                     | cron                   |
php_sapi_name        | cli                     | cgi-fcgi               |
php_ini_loaded_file  | /usr/local/lib/php.ini  | /usr/local/lib/php.ini | 

推荐答案

我怀疑您的问题在于缺少环境变量,特别是最重要的 $PATH.当你运行这个:

I suspect your problem lies in a missing environment variable, specifically the all-important $PATH. When you run this:

php -q /tmp/phpinfo.php

系统必须计算出您所说的php 是什么程序.它通过按顺序查看当前 $PATH 环境变量中的目录来完成此操作.

the system must work out what program you mean by php. It does this by looking, in order, through the directories in the current $PATH environment variable.

从普通 shell 执行,您的环境设置方式可以找到 PHP 的 CLI 版本,如您所料.

Executed from a normal shell, your environment is set up in such a way that it finds the CLI version of PHP, as you expect.

然而,当 cron 执行命令时,它不需要交互式 shell 设置的所有环境变量.由于您的系统上可能还有其他名为 php 的可执行文件,对于不同的SAPI",它可能会选择错误"的一个 - 在您的情况下,cgi-fcgi可执行文件,根据您从 php_sapi_name() 报告的输出.

However, when cron executes a command, it does so without all the environment variables that your interactive shell would set up. Since there will probably be other executables called php on your system, for different "SAPIs", it may pick the "wrong" one - in your case, the cgi-fcgi executable, according to the output you report from php_sapi_name().

要解决这个问题,首先要在普通 shell 中找到正确的 php 可执行文件的路径:

To fix this, first find the path to the correct php executable in a normal shell by typing this:

which php

这应该会给你一个类似 /usr/bin/php 的路径.您可以进一步检查这是否实际上是指向不同文件名的符号链接":

This should give you a path like /usr/bin/php. You can go one further and check if this is actually a "symbolic link" pointing at a different filename:

ls -l $(which php)

(如果是,您会在输出中看到一个箭头,例如 /usr/bin/php ->/usr/bin/php5-cli)

(you'll see an arrow in the output if it is, like /usr/bin/php -> /usr/bin/php5-cli)

然后获取 PHP 可执行文件的完整路径并在您的 crontab 条目中使用它,因此它看起来像这样:

Then take this full path to the PHP executable and use that in your crontab entry, so it looks something like this:

50 8 * * * /usr/bin/php5-cli -q /tmp/phpinfo.php > /tmp/phpinfo

相关文章