【问题标题】:how to do a linux reboot from php file如何从php文件重新启动linux
【发布时间】:2014-07-28 19:11:28
【问题描述】:

我的 linux 系统上有一个用户 brftv,我有运行 nginx 的 www-data。

从终端我可以让我的 brftv 用户运行

sudo /sbin/reboot

它工作正常,因为我将以下内容添加到我的 /etc/sudoers 文件的“#user privilege specification”部分:

brftv ALL=NOPASSWD: /sbin/halt, /sbin/reboot, /sbin/poweroff
www-data ALL=NOPASSWD: /sbin/halt, /sbin/reboot, /sbin/poweroff

但是当我的 php 文件运行以下代码时,什么也没有发生

exec('nohup sudo -u brftv /sbin/reboot');

我在上面的 etc/sudoers 中添加了 www-data 行,以防在运行上述 exec() 时有必要(即使我将它作为 -u brftv 运行,但我不是 linux 专家,只是想得更好以防万一)。

运行这个 exec() 的 php 文件归 www-data 所有,chmod 是 777,因此所有人都应该有权从它执行。

我尝试通过浏览器(我假设将由用户 www-data 运行)和终端 $php myFile.php 运行 php 文件。

------------------- 更新 ------

我做了这个

sudo chmod u s /sbin/reboot

这允许我系统上的所有用户在没有密码的情况下运行重启 cmd。它可以工作,但我宁愿不让它打开,所以 /etc/sudoers 的其他解决方案会更好,如果有人能暗示我的问题是什么......

我遵循了这个 tut http://linux.byexamples.com/archives/315/how-to-shutdown-and-reboot-without-sudo-password/,第二个例子几乎就是我上面得到的,对我不起作用..

【问题讨论】:

  • 尝试通过您的 Web 服务器从 PHP 脚本执行 'whoami' 以验证它运行的用户身份。

标签: php linux nginx exec reboot


【解决方案1】:

我会使用一个非常小的 C 程序来仅授予对 PHP 组的访问权限(在您的情况下可能是 www-data?),在可执行文件上使用 suid 位,然后执行重启命令

phpreboot.c:

#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main() {
   setuid(0); // for uid to be 0, root
   char *command = "/sbin/reboot";
   execl(command, command, NULL);
   return 0; // just to avoid the warning (since never returns)
}

编译

gcc -Wall phpreboot.c -o phpreboot

将 phpreboot 移动到你想运行它的地方(必须可以被 PHP 访问!)

mv phpreboot /home/private/

作为 root(或通过 sudo)确保所有者是 root 并且组设置为 www-data ,并更改权限以拥有 suid 位(按此顺序)

chown root:www-data phpreboot
chmod 4750 phpreboot

结果,ls -l phpreboot 应该类似于(注意 rws 中的 s

-rwsr-x--- 1 root www-data 8565 Jun 12 11:42 phpreboot*

将 PHP 脚本改为执行 phpreboot

exec ("/home/private/phpreboot"); // change the path!

只有一个很小的可执行文件具有运行 reboot 程序的 suid,并且只有 PHP 组才能执行它(当然还有 root)。

【讨论】:

  • 为什么使用 C 程序而不是 shell 脚本?我问的原因是因为我正在尝试使用 bash shell 脚本执行类似的操作,粘性位、所有者和组设置与您描述的完全一样,但是当我在脚本中执行 whoami 时,结果是www-data 而不是root。因此,我的脚本无法按预期工作,因为我无法让它以 root 身份运行。如果程序应该以root身份运行,为什么需要setuid(0)?预先感谢您对此有所了解。我正在运行 Ubuntu 14.04。
  • 好的,所以我找到了Shell脚本here忽略SetUID位的原因。
【解决方案2】:

将重启权限授予www user 是个坏主意。创建一个 cron 并从 cron 而不是 PHP 脚本进行系统重启。 Cron 将每分钟运行一次并检查重启标志。如果已设置,它将执行重新启动。

1) 从你的 php 程序中写入一个标志到一个文件中,这样 cron 就可以决定是否重启。

 $Handle = fopen("/tmp/myfile", 'w');
 fwrite($Handle, "doreboot");
 fclose($Handle);

2) 创建一个 bash 脚本来读取该文件并在 PHP 脚本告诉它这样做时重新启动。

#!/bin/bash
arg=$(head -n 1 /tmp/myfile)   
if [ "$arg" == "doreboot" ]; then
  >/tmp/myfile
  echo "Rebooting"
  echo 'password' | sudo -S reboot
fi

在shell中执行 chmod +x mycron.sh

3) 在crontab中配置脚本

crontab -e 并粘贴此

* * * * * path/mycron.sh

4) 设置 cron 的用户应该有 sudo 权限。将他添加到 sudoers。

【讨论】:

    【解决方案3】:

    我让它在我的系统上工作的唯一方法是通过更改 /sbin/reboot 上的 chmod 来“破解”它 就像这家伙做的那样

    http://linux.byexamples.com/archives/315/how-to-shutdown-and-reboot-without-sudo-password/

    sudo chmod u+s /sbin/reboot

    我意识到这在很多情况下可能不是最佳选择,但是这个 mediaPlayer 被非常锁定,所以无论如何其他人都无法访问终端。

    【讨论】:

      【解决方案4】:

      允许从 PHP 重新启动:

      1. vim /etc/sudoers
      2. 列表项粘贴新行“%www-data ALL=NOPASSWD: /sbin/reboot”并写入更改。
      3. 重启操作系统。
      4. 确保您的脚本归 www-data chown www-data:www-data filename.php(apache 用户)所有
      5. 运行脚本

      享受:)

      (在带有 php5-7 的 ubuntu 服务器 14.40 LTS 上测试,也应该适用于任何基于 debian 的发行版。)

      【讨论】:

        【解决方案5】:

        你为什么把-u brftv放在那里?这会使您的 PHP 脚本尝试以您的用户身份运行 reboot,但这是行不通的。只有 root 可以重新启动系统。删除它。

        【讨论】:

        • 好吧,你是说我添加到 /etc/sudoers 没有效果?而且 - 如果我删除它,我怎么知道它将作为 root 运行,在这种情况下它不会作为 www-data 运行吗?
        • 不,我是说-u brftv 不属于命令。删除它。
        • 好的,我删除了它,然后我收到了密码提示。显然不是一个解决方案,因为这应该从一个 php 脚本自动运行。我是否错过了 /etc/sudoers 中的某些内容,或者您​​的答案实际上不起作用?
        • @duskwuff 的回答是正确的。通过指定-u brftv,您告诉sudo 使用brftv 的权限,这将永远无法工作。删除它 (exec('nohup sudo /sbin/reboot');) 告诉 sudo 以 root 权限运行(但仍然“成为”任何用户),使用 /etc/sudoers 中指定的任何额外权限运行命令的用户。您缺少的是ALL=NOPASSWD: 之间的空格。
        • 没什么区别,还是不行,错误:“必须是root”。
        【解决方案6】:

        试试这段代码 exec('sudo shutdown -r now');

        或“shutdown -r +5”5分钟后关机

        【讨论】:

        • 那么sudo需要的密码呢?
        【解决方案7】:

        试试这个代码

        brftv ALL=NOPASSWD: /sbin/halt, /sbin/reboot, /sbin/poweroff
         www-data ALL=(brftv) NOPASSWD: /sbin/halt, /sbin/reboot, /sbin/poweroff 
        

        然后从 php

        exec('sudo /sbin/reboot');
        

        【讨论】:

          猜你喜欢
          • 2014-05-26
          • 1970-01-01
          • 2023-03-30
          • 2019-12-10
          • 2012-07-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多