【问题标题】:bash script execution from php and instantaneous output back to webpage从 php 执行 bash 脚本并即时输出回网页
【发布时间】:2012-06-14 04:04:34
【问题描述】:

我有一组 bash 和 Perl 脚本来

  1. 开发一个在 linux box 上部署所需的目录结构
  2. (可选) 从 svn 导出代码
  3. 从此源构建一个包

这在终端上运行良好。现在我的客户请求此过程的 Web 界面。

例如,特定页面上的“创建新包”按钮将一一调用上述步骤,并将输出作为脚本回显返回给用户,而不是在整个脚本执行时。

是否可以将 bash 脚本的瞬时输出发送到通过程序执行功能(系统、执行程序、passthru ... 或任何其他适合此流程的东西)调用它的网页或 php 脚本?

为什么要这样做有什么优雅的?

在做这样的事情时我应该采取哪些安全预防措施(如果可能的话)?

编辑 经过一番搜索,我找到了部分解决方案,但仍然无法正常工作:

$cmd = 'cat ./password.txt|sudo  -S  ./setup.sh ';

$descriptorspec = array(
        0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
        1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
        2 => array("pipe", "w") // stderr is a pipe that the child will read from
);

flush();

$process = proc_open($cmd, $descriptorspec, $pipes, './', array());
echo "<pre>";
if (is_resource($process)) {    

    while ($s = fgets($pipes[1])) {
        print "Message:".$s;
        flush();
    }
    while ($s = fgets($pipes[2])) {
        print "Error:".$s;
        flush();
    }
}
echo "</pre>";

输出:(网页)

Error:WARNING: Improper use of the sudo command could lead to data loss
Error:or the deletion of important system files. Please double-check your
Error:typing when using sudo. Type "man sudo" for more information.
Error:
Error:To proceed, enter your password, or type Ctrl-C to abort.
Error:
Error:Password:
Error:Sorry, try again.
Error:Password:
Error:Sorry, try again.
Error:Password:
Error:Sorry, try again.
Error:sudo: 3 incorrect password attempts**

我现在遇到的第一个问题是通过 sudo 密码

请帮忙!

【问题讨论】:

标签: php perl bash nonblocking


【解决方案1】:

最简单的方法是使用shell_exec 来达到您的目的。它通过 shell 执行命令并将完整的输出作为字符串返回,因此您可以将其显示在您的网站上。

如果这不适合您的目的,因为也许您在等待命令完成时需要一些响应,请查看 php 中的其他 program execution functions available(提示:手册页上有一些很好的 cmets)。

请记住,以这种方式调用命令行脚本时,生成的输出将具有您的网络服务器的文件所有者、组和权限(例如 wwwrun 或其他)。如果您的部分部署需要单独的所有者、组和/或文件权限,您必须在脚本中或在调用 shell_exec 之后手动设置它们(chmod、chown 和 chgrp 可以在php).

关于安全: 很多基于网络的应用程序将这种功能放在一个单独的安装目录中,并请您在安装后删除该目录。我什至记得他们中的一些人非常顽固地对管理员大喊大叫,除非它被删除。这是一种防止此脚本在错误的时间被错误的人调用的简单方法。如果您的应用程序在安装后可能需要它,那么您必须将其放入只有授权用户才能访问的区域(例如管理区域或类似区域)。

【讨论】:

    【解决方案2】:

    我会使用一种主/从设计。从站将是您的 perl / bash 脚本,只是做一项工作(打包、编译、导出代码等),并提供一个日志条目。

    主将是您的 php 进程。所以原理是这样的:主从共享一个通信通道,从那个通道异步通信。

    你可以想象一个像这样的数据库:

    create table tasks ( id INT primary key, status INT, argument VARCHAR(100));
    

    你的 php 页面应该切换用户选择,并且 filter 输入:

    switch ($_GET['action']) {
       case 'export':
           $argument = sanitize($_GET['arg']);
           add_task('export', $argument);
           break;
       case '...': 
         // ...
    }
    

    add_task 函数可能类似于:

    function add_task($action, $arg)
    {
       return $db->add('tasks', array($action, NEW_TASK, $arg);
    }
    

    slave 可以通过cron job 运行,并查询数据库,提供任务的进展。

    专业人士是:

    • 独立系统,轻松进化。
    • 如果客户端断开连接,作业永远不会丢失
    • 更容易保护

    缺点是:

    • 一开始有点复杂。
    • 反应较少,因为从属设备运行的轮询时间(例如,如果它们每 5 分钟运行一次)
    • 输出比命令直接输出少

    请注意,您可以实现类似 xml-rpc 的触发器来运行从属服务器,而不是使用消息传递系统。

    【讨论】:

    • 您的回答提供了一些有趣的选项来处理系统。如果您有一些工作代码或以这种方式设计的类似脚本/系统,我将不胜感激。谢谢
    • 抱歉,我只在 java 项目中使用它们进行分布式计算,以及在 vhffs(vhffs.org,参见 bots/ 文件夹)中的 perl 中使用它们。
    • +1 对 Alf 的建议方法。这是满足此类要求的非常标准的模式。它有助于解决大多数安全和控制问题,因为它将“请求和监视”域与执行分开。您可以对这些前端和后端服务使用单独的标识和身份验证,并通过接口的数据和流程模型将它们的交互形式化。
    【解决方案3】:

    您可以使用Comet web application model实时更新结果页面。

    对于 sudo 问题,作为一种快速而肮脏的解决方案,我将使用 Web 服务器无需密码即可执行的受限命令集。示例(添加/etc/sudoers):

    apache ALL=(ALL) NOPASSWD: /sbin/service myproject *

    这将允许 apache 运行 /sbin/service myproject stop、/sbin/service myproject start 等等。

    看看Jenkins,它很好地完成了网络部分,您只需在构建中添加脚本。

    按照Aif 的建议,更好的解决方案是分离逻辑。一个等待任务的守护进程和一个可视化结果的 Web 应用程序。

    【讨论】:

      【解决方案4】:

      为了安全起见,在通过 PHP 执行系统命令时始终使用 escapeshellarg 和 escapeshellcmd。还建议尽可能限制用户在 chroot'd 目录中。

      【讨论】:

        【解决方案5】:

        您似乎已经解决了使用proc_open 将标准输出和标准输入输出到您的网页的问题。现在问题似乎是通过 sudo 执行脚本。

        从安全角度来看,让 PHP 应用程序以 root 身份运行脚本(通过 sudo)让我感到畏缩。在 password.txt 中包含 root 密码是一个相当大的安全漏洞。

        我要做的(如果可能的话)是进行必要的更改,以便运行 Apache 的 unix 用户可以运行 setup.sh。 (我假设您使用 Apache 运行 PHP。)如果 setup.sh 将由网络服务器执行,它应该能够运行它而无需借助 sudo。

        如果您确实需要以其他用户身份执行脚本,您可以查看suPHP,它旨在以非标准用户身份运行 PHP 脚本。

        【讨论】:

          【解决方案6】:

          使用 /etc/sudoers 的 NOPASSWD 选项为特定用户提供自动 sudo 权限,然后运行带有前缀 sudo -u THE_SUDO_USER 的命令,以使该命令以该用户身份执行。这可以防止授予整个 apache 用户 sudo 权限的安全漏洞,但也允许从 apache 内部对脚本执行 sudo。

          【讨论】:

            猜你喜欢
            • 2017-07-17
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-06-18
            • 1970-01-01
            • 2011-07-22
            相关资源
            最近更新 更多