bash脚本执行从php和瞬时输出回到网页

时间:2012-06-11 08:50:52

标签: php perl bash nonblocking

我有一个bash和Perl脚本的集合

  1. 开发在linux box上部署所需的目录结构
  2. (可选)从svn
  3. 导出代码
  4. 从此来源构建一个包
  5. 这在终端上运作良好。现在我的客户端请求此过程的Web界面。

    例如某个页面上的“Create New Package”按钮将逐个调用上述步骤并将输出作为脚本回声返回给用户,而不是在整个脚本执行时。

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

    为什么这么做是优雅的?

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

    修改 经过一些搜索后,我找到了解决方案的一部分,但仍无法正常工作:

    $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 passoword

    请帮忙!

6 个答案:

答案 0 :(得分:4)

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

主人将是你的php进程。所以原理如下:主设备和从设备共享一个通信通道,并从该通道异步通信。

您可以想象一个像以下的数据库:

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

你的php页面应该切换用户选择,过滤输入:

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);
}

奴隶可以通过cron job运行,并查询数据库,为任务的进展提供支持。

专业人士:

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

缺点是:

  • 一开始有点复杂。
  • 反应性较低,因为奴隶的轮询时间正在运行(例如,如果它们每5分钟运行一次)
  • 输出少于命令的直接输出

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

答案 1 :(得分:1)

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

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

请记住,在以这种方式唤起命令行脚本时,生成的输出将具有您的网络服务器的文件所有者,组和权限(p.e. wwwrun或其他)。如果部署的某些部分需要单独的所有者,组和/或文件权限,则必须在脚本中或在调用shell_execchmodchown和{{}之后手动设置它们。 3}}可以在php中处理这个问题。

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

答案 2 :(得分:1)

您可以使用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应用程序可视化结果。

答案 3 :(得分:0)

在通过PHP执行系统命令时始终使用escapeshellargescapeshellcmd以确保安全性。还建议让用户在chroot目录中尽可能地限制。

答案 4 :(得分:0)

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

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

我会做的(如果可能的话)是进行必要的更改,以便setup.sh可以由运行Apache的unix用户运行。 (我假设您正在使用Apache运行PHP。)如果setup.sh将由Web服务器执行,它应该能够在不使用sudo的情况下运行它。

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

答案 5 :(得分:0)

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