【问题标题】:sudo in php exec()php exec() 中的 sudo
【发布时间】:2011-03-11 12:48:53
【问题描述】:

我不知道这里的交易是什么……

所以我想运行一个applescript:sudo osascript myscript.scpt

这在终端中可以正常工作,但是当我通过 PHP 的 exec() 执行它时就不行了;什么都没发生。控制台说

no tty present and no askpass program specified ; TTY=unknown ; …

我进行了研究,似乎我缺少sudo 命令的密码。我尝试了几种不同的方法来解决这个问题,包括:

  • %admin ALL=(ALL) ALL 写入/etc/sudoers
  • proc_open() 而不是exec()

似乎都没有工作,因此让我发疯!

所以基本上,有没有一种明确的方法可以让 PHP 执行一个简单的终端命令?

编辑:澄清一下,myscript.scpt 是一个简单的 appleScript,它改变了屏幕 UI(对于更大的项目)。理论上,简单的osascript myscript.scpt 就足够了,但是出于某种原因,sudo 是从系统调用 some 响应所必需的。如果sudo 可以以某种方式消除,我认为我不会遇到这个权限问题。

【问题讨论】:

  • 有办法解决这个问题,但最好的办法可能是让myscript.script 在没有root 权限的情况下运行。
  • 从技术上讲,您可以采取的任何方式都是一个坏主意。您可以在不需要密码的情况下授予 PHP 对 sudo 的访问权限,或者使用始终以 root 权限运行的 setuid 帮助程序脚本。在处理 PHP 前端时,两者都不是很理智。您能否更新您的问题,告诉我们myscript.scpt 实际完成了什么?

标签: php linux sudo


【解决方案1】:

听起来您需要设置无密码 sudo。试试:

%admin ALL=(ALL) NOPASSWD: osascript myscript.scpt

如果存在以下行(通过 visudo 在 /etc/sudoers 中),请同时注释掉:

Defaults    requiretty

【讨论】:

  • 我尝试将它添加到 etc/sudoers,但没有骰子。我仍然得到“没有 tty 存在并且没有指定 askpass 程序”
  • 你有没有运气注释掉 requiretty 行?
  • 不。它根本不在文件中。我开始同意 Matchu(下)关于所有这些安全问题的看法。如果我的系统让它变得如此困难,那可能是出于良好的安全原因。
  • 我认为这是一个明智的决定 :) 尽管我试图帮助回答您最初的问题,但我确实认为在 web 应用程序中使用 sudo 可能会引发很多安全问题。
  • 需要放在哪里 %admin ALL=(ALL) NOPASSWD: ALL
【解决方案2】:

php: bash 控制台被创建,它执行第一个脚本,它调用 sudo 到第二个,见下文:

$dev = $_GET['device'];
$cmd = '/bin/bash /home/www/start.bash '.$dev;
echo $cmd;
shell_exec($cmd);
  1. /home/www/start.bash

    #!/bin/bash
    /usr/bin/sudo /home/www/myMount.bash $1
    
  2. myMount.bash:

    #!/bin/bash
    function error_exit
    {
      echo "Wrong parameter" 1>&2
      exit 1
    }
    ..........
    

oc,您想在没有 root 权限的情况下从 root 级别运行脚本,为此创建和修改 /etc/sudoers.d/mount 文件:

www-data ALL=(ALL:ALL) NOPASSWD:/home/www/myMount.bash

别忘了chmod:

sudo chmod 0440 /etc/sudoers.d/mount

【讨论】:

    【解决方案3】:

    我认为您可以使用 visudo 为用户和命令带来特定访问权限,如下所示:

    nobody ALL = NOPASSWD: /path/to/osascript myscript.scpt
    

    和 php:

    @exec("sudo /path/to/osascript myscript.scpt ");
    

    假设 nobody 用户正在运行 apache。

    【讨论】:

      【解决方案4】:

      我最近发布了一个项目,它允许 PHP 获取真实的 Bash shell 并与之交互。在这里获取:https://github.com/merlinthemagic/MTS shell 有一个 pty(伪终端设备,与您在 ssh 会话中的相同),如果需要,您可以作为 root 获取 shell。不确定您是否需要 root 才能执行您的脚本,但鉴于您提到 sudo,它很可能。

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

      $shell    = \MTS\Factories::getDevices()->getLocalHost()->getShell('bash', true);
      $return1  = $shell->exeCmd('/path/to/osascript myscript.scpt');
      

      【讨论】:

        【解决方案5】:

        运行sudo visudo 命令,然后将-%sudo ALL=(ALL:ALL) 设置为%sudo ALL=(ALL:ALL) NOPASSWD: ALL 即可。

        【讨论】:

          【解决方案6】:

          我在尝试 exec() 一个后端命令时遇到了类似的情况,并且还在 Web 服务器错误日志中获得了 no tty present and no askpass program specified。原始(错误)代码:

          $output = array();
          $return_var = 0;
          exec('sudo my_command', $output, $return_var);
          

          bash 包装器解决了这个问题,例如:

          $output = array();
          $return_var = 0;
          exec('sudo bash -c "my_command"', $output, $return_var);
          

          不确定这是否适用于所有情况。此外,请务必在 my_command 部分应用适当的引用/转义规则。

          【讨论】:

            【解决方案7】:

            最好的安全方法是使用 crontab。即,将所有命令保存在数据库中,例如 mysql 表并创建一个 cronjob 来读取这些 mysql entreis 并通过 exec() 或 shell_exec() 执行。请阅读此link 了解更多详细信息。

                    • killProcess.php

            【讨论】:

              【解决方案8】:

              我认为直接调用 sudo 命令可能会很困难,因为您将整个服务器设置为无需密码即可工作。
              也许作为替代方案,您可以将 CRONjob 设置为 root 并监视标志文件。一旦标志文件存在,它将运行 osascript myscript.scpt 然后删除标志文件。 这样,您将从配置的角度保持 SUDO 的安全,并使服务器更安全。要运行脚本,您只需从 PHP 中触摸标志文件。 当然,无论您运行 CRON 作业多少分钟,它都会造成延迟。这也意味着您必须将输出重定向到文件并具有输出的异步监视器,但这是否存在问题取决于您的应用程序。

              但它是一种可能保护服务器的替代方案。

              【讨论】:

              • 我不确定将命令存储在数据库中,因为这也可能被滥用。我更喜欢把事情弄得更紧。以 root 身份运行任何命令都应该尽可能安全。
              猜你喜欢
              • 2014-05-17
              • 1970-01-01
              • 2012-10-17
              • 1970-01-01
              • 2014-07-28
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多