douwei8672 2015-02-08 18:03
浏览 39
已采纳

在远程计算机上从php发出多个bash命令

I try to issue:

sudo apt-get update

and

sudo apt-get install openjdk-7-jre joe wget

on a remote machine from php,

I've been looking around and tried two approaches:

first:

session_start();

$command = "ssh -o 'StrictHostKeyChecking no' -i /var/www/.ssh/my-keypair555.pem ubuntu@{$_SESSION['host']} \"sudo apt-get update\"";

echo $command."<br/>";

echo exec($command, $output);

print_r($output);

$command = "ssh -o 'StrictHostKeyChecking no' -i /var/www/.ssh/my-keypair555.pem ubuntu@{$_SESSION['host']} \"sudo apt-get install -y openjdk-7-jre joe wget\"";

echo $command."<br/>";

echo exec($command, $output);

print_r($output);

this code doesn't seem to get executed at all, (The commands get printed but the output array seems empty.)

and secondly: an adapted version from http://php.net/manual/en/function.ssh2-exec.php

session_start();

$connection = ssh2_connect($_SESSION['host'], 22, array('hostkey'=>'ssh-rsa'));

if (ssh2_auth_pubkey_file(
    $connection, 
    'ubuntu',
    '/var/www/.ssh/id_rsa.pub',
    '/var/www/.ssh/id_rsa')
    ) {

    $shell = ssh2_shell($connection,"bash"); 

    $cmd = "echo '[start]';sudo apt-get update;sudo apt-get install -y openjdk-7-jre joe wget;echo '[end]'"; 
    $output = user_exec($shell,$cmd); 

    fclose($shell); 

    echo $output."<br/>";

} else {

    die('Public Key Authentication Failed');
}

function user_exec($shell,$cmd) { 
    fwrite($shell,$cmd . "
"); 
    $output = ""; 
    $start = false; 
    $start_time = time(); 
    $max_time = 900; //time in seconds 
    while(((time()-$start_time) < $max_time)) { 
        $line = fgets($shell); 
        //echo $line;
        if(!strstr($line,$cmd)) { 
            if(preg_match('/\[start\]/',$line)) { 
                $start = true; 
                echo "start";
            }elseif(preg_match('/\[end\]/',$line)) { 
                return $output; 
            }elseif($start){ 
                $output[] = $line; 
                echo $line."<br/>";
            } 
        } 
    } 
}   

If I use this code the command:

echo '[start]';sudo apt-get update;sudo apt-get install -y openjdk-7-jre joe wget;echo '[end]'

does show up if I log in to the machine and issue

history

but doesn't seem to be executed because if I issue

java

I get the message that I need to install it.

if I issue

!1

the apt-get update and apt-get install do get executed properly.

If I run the php file in a browser I get following output:

Welcome to Ubuntu 14.04.1 LTS (GNU/Linux 3.13.0-36-generic x86_64) * Documentation: https://help.ubuntu.com/ System information as of Sun Feb 8 17:20:45 UTC 2015 System load: 0.69 Processes: 104 Usage of /: 9.8% of 7.74GB Users logged in: 0 Memory usage: 1% IP address for eth0: 10.74.190.178 Swap usage: 0% Graph this data and manage this system at: https://landscape.canonical.com/ Get cloud support with Ubuntu Advantage Cloud Guest: http://www.ubuntu.com/business/services/cloud 0 packages can be updated. 0 updates are security updates. Last login: Sun Feb 8 17:20:50 2015 from ec2-54-77-56-210.eu-west-1.compute.amazonaws.com echo '[start]';sudo apt-get update;sudo apt-get install -y openjdk-7-jre joe wget;echo '[end]' ubuntu@ip-10-74-190-178:~$ echo '[start]';sudo apt-get update;sudo apt-get in

  • a lot of empty lines and now and then a double message like alal or l -l -

-> note that the command is truncated at 'install'

which would explain why the command isn't executed.

Can anyone give me a hand on this one, I've been searching for almost two weeks now and don't seem to progress a lot...

thanks,

Sander

  • 写回答

1条回答 默认 最新

  • douyi6755 2015-02-09 19:49
    关注

    Apparently the max_execution_time in php.ini was the issue here.

    I debugged the second script with

    ...
    }elseif(preg_match('/\[end\]/',$line)) { 
        echo "[end]:".$line;
        return $output; 
    }elseif($start){ 
    ...
    

    and

        } //while loop
        echo "out of time";
    }//function user_exec($shell,$cmd) { 
    

    and neither got executed in the output of the page in the browser.

    the

    $max_time = 900; //time in seconds 
    

    wasn't enough and should be proceded with:

    set_time_limit(900);
    

    The original command was executed but whilst executing it the timeout of php stopped the execution.

    Also the first script should have suffered from the same issue, it just took to long to execute the commands and php returned in the midst of the execution.

    I also, but I don't think this was the cause of the problem used a:

    $stream = ssh2_exec($connection,$cmd);
    

    in stead of the original

    fwrite($shell,$cmd . "
    "); 
    

    the total script:

    <?php
    
    sleep(30);
    
    session_start();
    
    $connection = ssh2_connect($_SESSION['host'], 22, array('hostkey'=>'ssh-rsa'));
    
    if (ssh2_auth_pubkey_file(
        $connection, 
        'ubuntu',
        '/var/www/.ssh/id_rsa.pub',
        '/var/www/.ssh/id_rsa')
        ) {
    
        $cmd = "echo '[start]';sudo apt-get update;sudo apt-get install -y openjdk-7-jre joe wget;echo '[end]'"; 
    
        $output = user_exec($connection,$cmd); 
    
        fclose($shell); 
    
        ob_end_flush();
    
        echo $output."Halleluia!!!";
    
    } else {
    
        die('Public Key Authentication Failed');
    }
    
    function user_exec($connection,$cmd) { 
        $stream = ssh2_exec($connection,$cmd);
    
        $output = ""; 
        $start = false; 
        $start_time = time(); 
    
        set_time_limit(900);
    
        $max_time = 900; //time in seconds 
        while(((time()-$start_time) < $max_time)) { 
            $line = fgets($stream); 
            if(!strstr($line,$cmd)) { 
                if(preg_match('/\[start\]/',$line)) { 
                    $start = true; 
                }elseif(preg_match('/\[end\]/',$line)) { 
                    echo "[end]:".$line;
                    return $output; 
                }elseif($start){ 
                    if($line != ""){
                        ob_flush();
                        flush();
                        $output[] = $line; 
                        echo $line."<br/>";
                    }
                } 
            } 
        } 
        echo "out of time";
    }   
    ?>
    

    Hope this helps anyone with a similar issue.

    S.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 file converter 转换格式失败 报错 Error marking filters as finished,如何解决?
  • ¥15 ubuntu系统下挂载磁盘上执行./提示权限不够
  • ¥15 Arcgis相交分析无法绘制一个或多个图形
  • ¥15 关于#r语言#的问题:差异分析前数据准备,报错Error in data[, sampleName1] : subscript out of bounds请问怎么解决呀以下是全部代码:
  • ¥15 seatunnel-web使用SQL组件时候后台报错,无法找到表格
  • ¥15 fpga自动售货机数码管(相关搜索:数字时钟)
  • ¥15 用前端向数据库插入数据,通过debug发现数据能走到后端,但是放行之后就会提示错误
  • ¥30 3天&7天&&15天&销量如何统计同一行
  • ¥30 帮我写一段可以读取LD2450数据并计算距离的Arduino代码
  • ¥15 飞机曲面部件如机翼,壁板等具体的孔位模型