通过PHP的Shell:向crontab添加新的cron作业时出现问题


Shell via PHP: Trouble adding new cron job to crontab

我有几个脚本计划在我的crontab中运行,但只能将它们视为root(或使用sudo)。我需要一个PHP脚本(作为nginx运行),以便能够在crontab文件中添加新行。为此,我创建了一个shell脚本(由root拥有),并通过/etc/sudoers文件授予nginx用户对sudo的权限。

/etc/sudoers文件的最后一行:

nginx ALL=NOPASSWD: /etc/nginx/addcron.sh

执行脚本的PHP调用:

chdir("/etc/nginx/");
echo exec("2>&1 ./addcron.sh $custname", $output);
echo "<pre>".print_r($output, true)."</pre>";

我当前的crontab:

[ec2-user@ip-172-31-xx-xxx nginx]$ sudo crontab -l
* * * * * env > /tmp/env.output
* * * * * /usr/bin/php -f /var/www/html/example/cron/cron.php
* * * * * /usr/bin/php -f /var/www/html/demo/cron/cron.php
0 23 * * * rm /tmp/cachegrind.out.*

关于我的addcron.sh文件的元信息:

[ec2-user@ip-172-31-xx-xxx nginx]$ pwd
/etc/nginx
[ec2-user@ip-172-31-xx-xxx nginx]$ ls -al addcron.sh
-rwxr-xr-x 1 root root 129 Nov 24 22:16 addcron.sh

addcron.sh:的内容

#!/bin/bash
custname="$1"
(crontab -l; echo '"* * * * * /usr/bin/php -f /var/www/html/$custname/cron/cron.php'" ) | crontab -

当我尝试运行这个时,我得到了以下错误:

errors in crontab file, can't install.
Array
(
    [0] => "-":102: bad minute
    [1] => errors in crontab file, can't install.
)

它似乎不喜欢addcron.sh中的-标记,但我在谷歌上的搜索表明这是正确的。此外,我还尝试将sudo添加到PHP的exec命令中,但随后我只得到以下错误:

sorry, you must have a tty to run sudo

我做错了什么或错过了什么,为什么?

附带说明:从安全角度来看,在root的帐户下运行与系统管理员无关的cron作业是一个坏主意。在nginx用户下安装您的cron。

这个问题是由bash脚本中引号的转义引起的(您可以直接在bash中逐段检查,顺便说一句):

> (crontab -l; echo '"* * * * * /usr/bin/php -f /var/www/html/$custname/cron/cron.php'" )
no crontab for username
"* ... <all kinds of filenames in here> ... /usr/bin/php -f /var/www/html/the_customer/cron/cron.php"

如果没有引号转义,情况会好一点:

> (crontab -l; echo "* * * * * /usr/bin/php -f /var/www/html/$custname/cron/cron.php" )
no crontab for username
* * * * * /usr/bin/php -f /var/www/html/the_customer/cron/cron.php

您可能想要添加一些防止重复条目的保护,以下是crontab在几次调用后的外观:

> crontab -l
# DO NOT EDIT THIS FILE - edit the master and reinstall.
# (- installed on Tue Nov 24 20:54:10 2015)
# (Cronie version 4.2)
# DO NOT EDIT THIS FILE - edit the master and reinstall.
# (- installed on Tue Nov 24 20:54:09 2015)
# (Cronie version 4.2)
# DO NOT EDIT THIS FILE - edit the master and reinstall.
# (- installed on Tue Nov 24 20:54:09 2015)
# (Cronie version 4.2)
# DO NOT EDIT THIS FILE - edit the master and reinstall.
# (- installed on Tue Nov 24 20:54:08 2015)
# (Cronie version 4.2)
# DO NOT EDIT THIS FILE - edit the master and reinstall.
# (- installed on Tue Nov 24 20:54:07 2015)
# (Cronie version 4.2)
* * * * * /usr/bin/php -f /var/www/html/the_customer/cron/cron.php
* * * * * /usr/bin/php -f /var/www/html/the_customer/cron/cron.php
* * * * * /usr/bin/php -f /var/www/html/the_customer/cron/cron.php
* * * * * /usr/bin/php -f /var/www/html/the_customer/cron/cron.php
* * * * * /usr/bin/php -f /var/www/html/the_customer/cron/cron.php

我最近发布了一个项目,该项目允许PHP获得真正的Bash shell并与之交互。在这里获取:https://github.com/merlinthemagic/MTS

下载后,您只需使用以下代码:

$custname= "someone";
$strCmd = "echo '"* * * * * /usr/bin/php -f /var/www/html/".$custname."'" >> /cron/cron.php";
$shell    = 'MTS'Factories::getDevices()->getLocalHost()->getShell('bash', true);
$return1  = $shell->exeCmd($strCmd);
//assuming your distribution reloads / restarts using 'service'
$return2  = $shell->exeCmd('service crond restart');

这将把您的行附加到cron文件中。