我想在 php 中开发一些脚本来调用以下命令;使用 exec() 函数
service network restart
crontab -u root /xyz/abc/fjs/crontab
ETC。
问题是 Apache 以 apache 用户身份执行脚本(我在 CentOS 5 上),无论将 apache 添加到 wheel 中还是做好事、坏事和丑事 组分配不运行命令(如上所述)。
以下是我的配置;
我的 /etc/sudoers
root ALL=(ALL) ALL
apache ALL=(ALL) NOPASSWD: ALL
%wheel ALL=(ALL) ALL
%wheel ALL=(ALL) NOPASSWD: ALL
当我尝试将 sudoer 和 httpd.conf 进行几种组合时,最近的 httpd.conf 看起来如下所示;
我的 httpd.conf
User apache
Group wheel
我的 PHP 脚本
exec("service network start", $a);
print_r($a);
exec("sudo -u root service network start", $a);
print_r($a);
输出
Array
(
[0] => Bringing up loopback interface: [FAILED]
[1] => Bringing up interface eth0: [FAILED]
[2] => Bringing up interface eth0_1: [FAILED]
[3] => Bringing up interface eth1: [FAILED]
)
Array
(
[0] => Bringing up loopback interface: [FAILED]
[1] => Bringing up interface eth0: [FAILED]
[2] => Bringing up interface eth0_1: [FAILED]
[3] => Bringing up interface eth1: [FAILED]
)
毫不奇怪,当我使用类似 apache 的用户通过 ssh 调用重新启动网络服务时,命令成功执行。这都是关于通过 HTTP 协议访问此类命令。我确信 cPanel/Plesk 类软件确实使用类似 sudoer 之类的东西,而我尝试做的事情基本上是可行的。但我需要你的帮助来了解我遗漏了哪一部分?
多谢!
答案1
如果您采用 troyengel 的解决方案,在根 cron 表中添加一个条目,然后稍加修改,您可能会得到一个可行的解决方案。
如果您绝对、肯定需要使用 apache 来发出接口重新启动信号,为什么不让 PHP 创建一个充当标志的文件,然后让每分钟(或其他时间)运行一次的 root cronjob 检查该标志是否存在。如果存在,则重新启动接口。如果不存在,则死机。(请记住让 cronjob 在成功重新启动接口后删除该标志)。
这实现了目标(重新启动界面,从 apache/php 触发)并避免了授予 web/脚本服务根级别访问权限所涉及的所有可能问题。
答案2
您必须将它们编写为 PHP 命令行驱动工具(确保通过 yum 安装 php-cli 包),然后直接在 root crontab 中运行它们,而不是以普通用户的身份运行。您可能还想将其编写在基本的 bash(shell)脚本中,如果您只是通过 exec() 运行命令,那么使用 php 就有点小题大做了。
答案3
您应该使用 -- 调用需要以其他用户身份运行的命令sudo
,然后sudoers
适当地设置配置文件,以便允许运行 PHP 脚本的用户以其他用户身份运行脚本。请参阅sudoers
(5) 和大约十几个有关使用 sudo 的先前问题。
答案4
您可以使用粘滞位使 shell 脚本以 root 身份运行。但是,这样做会更加复杂。
但是,您不能只在 shell 脚本上设置 UID。您需要使用 C/C++ 等语言制作常规可执行文件,这些文件不会像 shell 脚本那样调用解释器,然后让其执行 shell 脚本。