通过 exec() 的 Crontab 不适用于 PHP 7.4 / Deb 10
Crontab via exec() not working with PHP 7.4 / Deb 10
调试起来有点困难,因为我在新服务器上同时使用新版本的 PHP 和新的 OS。
我在 PHP 中有一个 cron 管理系统,它允许我添加/删除或启用/禁用 cronjobs。
在另一台 PHP 7.2 的当前 Deb 8 服务器上,它可以完美地使用以下函数创建作业...
public static function createCronjob($job)
{
exec('echo -e "`crontab -l`\n'. $job .'" | crontab -', $output);
return $output;
}
其中 $job
类似于:
10 0 * * * wget -O - https://website.com/cxs?job=jobTitle >/dev/null 2>&1
而且我还可以用这个列出 crontab 的内容,它也吐出两个单独的数组,一个用于活动作业,一个用于非活动作业...
public static function getCronjobs()
{
exec('crontab -l', $data);
$active = [];
$inactive = [];
foreach ($data as $j) {
if (!empty($j)) {
if (substr($j,0,1) == '#') {
array_push($inactive, $j);
} else {
array_push($active, $j);
}
}
}
$arr = [
'active' => $active,
'inactive' => $inactive
];
return $arr;
}
但我刚刚用 PHP 7.4 和 none 设置了一个新的 Debian 10 服务器,这似乎还能做什么?它不会添加工作并且 crontab -l
总是 returns 一个空数组(我认为这是因为没有找到工作)。
我检查过 exec()
是否正常工作,并尝试按照我发现的几篇文章的建议将 www-data
用户添加到 /etc/cron.allow
,尽管我从来没有这样做过在 Deb 8 服务器上,但我一点也不高兴。
在 Deb 10 或 PHP 7.4 中是否引入了新的安全措施或代码更改,我不知道这会阻止它的工作,或者我在这里明显遗漏了什么?
-- 编辑以包括下面@summea 友情提供的解决方案--
我敢肯定其他人会偶然发现这个,所以这里是答案:
a) PHP 7.4(似乎是 7.3)需要 exec()
中 echo
的完整路径
public static function createCronjob($job)
{
exec('/usr/bin/echo -e "`crontab -l`\n'. $job .'" | crontab -', $output);
return $output;
}
但奇怪的是 crontab
的完整路径 不需要 (但可能是好的做法),因为这仍然有效:
exec('crontab -l', $data);
b) 创建 /etc/cron.allow
对我来说是个错误。它拒绝未在此文件中声明的所有其他用户访问 crontab
。在我删除它并重新启动 cron 服务后 /etc/init.d/cron restart
一切正常。
真的希望这能为其他人节省一些时间,因为它是一个错误!
我的本地计算机上有一个 Debian 10 虚拟机,上面装有 PHP 7.3.19。经过大量时间尝试不同的方法来解决您所面临的问题,在我这边,问题原来与需要包含 echo
程序的完整路径有关。我不知道 PHP 在我的机器上是否有其他 echo
程序在不同的路径或其他地方找到(这可能与 ). At one point I was wondering if the backticks in the command were causing a problem with PHP, because the shell_exec()
is evidently like the PHP backtick operator.[=23 间接相关) =]
以下是我从 PHP 方面成功将您的 createCronjob()
升级为 运行 所做的工作:
// ref: q21.php
function createCronjob($job)
{
exec('/usr/bin/echo -e "`crontab -l`\n'. $job .'" | crontab -', $output);
return $output;
}
当我将完整路径添加到 echo
命令时,它开始工作了。您的 echo
路径可能不同,但可能相同,因为我们应该使用相似的系统。
我使用这个命令找到了 echo
路径:
which echo
它返回了这个位置:
/usr/bin/echo
此外,为了将来参考,我不知道在这种情况下,将来使用 escapeshellcmd()
是否是个好主意?我不是很熟悉它,所以我不确定在这种情况下您是否希望将它包含在 shell 命令的某处(并且它可能会使命令不是 运行 作为无论如何都打算),但想提一下!
调试起来有点困难,因为我在新服务器上同时使用新版本的 PHP 和新的 OS。
我在 PHP 中有一个 cron 管理系统,它允许我添加/删除或启用/禁用 cronjobs。
在另一台 PHP 7.2 的当前 Deb 8 服务器上,它可以完美地使用以下函数创建作业...
public static function createCronjob($job)
{
exec('echo -e "`crontab -l`\n'. $job .'" | crontab -', $output);
return $output;
}
其中 $job
类似于:
10 0 * * * wget -O - https://website.com/cxs?job=jobTitle >/dev/null 2>&1
而且我还可以用这个列出 crontab 的内容,它也吐出两个单独的数组,一个用于活动作业,一个用于非活动作业...
public static function getCronjobs()
{
exec('crontab -l', $data);
$active = [];
$inactive = [];
foreach ($data as $j) {
if (!empty($j)) {
if (substr($j,0,1) == '#') {
array_push($inactive, $j);
} else {
array_push($active, $j);
}
}
}
$arr = [
'active' => $active,
'inactive' => $inactive
];
return $arr;
}
但我刚刚用 PHP 7.4 和 none 设置了一个新的 Debian 10 服务器,这似乎还能做什么?它不会添加工作并且 crontab -l
总是 returns 一个空数组(我认为这是因为没有找到工作)。
我检查过 exec()
是否正常工作,并尝试按照我发现的几篇文章的建议将 www-data
用户添加到 /etc/cron.allow
,尽管我从来没有这样做过在 Deb 8 服务器上,但我一点也不高兴。
在 Deb 10 或 PHP 7.4 中是否引入了新的安全措施或代码更改,我不知道这会阻止它的工作,或者我在这里明显遗漏了什么?
-- 编辑以包括下面@summea 友情提供的解决方案--
我敢肯定其他人会偶然发现这个,所以这里是答案:
a) PHP 7.4(似乎是 7.3)需要 exec()
echo
的完整路径
public static function createCronjob($job)
{
exec('/usr/bin/echo -e "`crontab -l`\n'. $job .'" | crontab -', $output);
return $output;
}
但奇怪的是 crontab
的完整路径 不需要 (但可能是好的做法),因为这仍然有效:
exec('crontab -l', $data);
b) 创建 /etc/cron.allow
对我来说是个错误。它拒绝未在此文件中声明的所有其他用户访问 crontab
。在我删除它并重新启动 cron 服务后 /etc/init.d/cron restart
一切正常。
真的希望这能为其他人节省一些时间,因为它是一个错误!
我的本地计算机上有一个 Debian 10 虚拟机,上面装有 PHP 7.3.19。经过大量时间尝试不同的方法来解决您所面临的问题,在我这边,问题原来与需要包含 以下是我从 PHP 方面成功将您的 当我将完整路径添加到 我使用这个命令找到了 它返回了这个位置: 此外,为了将来参考,我不知道在这种情况下,将来使用 echo
程序的完整路径有关。我不知道 PHP 在我的机器上是否有其他 echo
程序在不同的路径或其他地方找到(这可能与 shell_exec()
is evidently like the PHP backtick operator.[=23 间接相关) =]
createCronjob()
升级为 运行 所做的工作:// ref: q21.php
function createCronjob($job)
{
exec('/usr/bin/echo -e "`crontab -l`\n'. $job .'" | crontab -', $output);
return $output;
}
echo
命令时,它开始工作了。您的 echo
路径可能不同,但可能相同,因为我们应该使用相似的系统。echo
路径:which echo
/usr/bin/echo
escapeshellcmd()
是否是个好主意?我不是很熟悉它,所以我不确定在这种情况下您是否希望将它包含在 shell 命令的某处(并且它可能会使命令不是 运行 作为无论如何都打算),但想提一下!