允许 PHP 脚本通过 SSH 连接到多个服务器

Allow PHP script to SSH into multiple servers

我有一个位于 Raspberry PI 上的 CSV 文件并输出:

2018-03-22 12:43:21,NM_Test.h264,-2

在我的主机服务器上,我有一个 PHP 脚本,它从 CSV 文件中获取输出并将其显示为 HTML table 在我的网页上:

$command = "ssh -p 97 -i /var/www/html/test.rsa pi@192.168.xxx.xxx tail -1 /var/log/playlog.csv";
$output = exec($command);
$array = explode(',',$output);

echo '<div class="container"><table class="table table-striped">
 <tr>
 <th>Status</th>
 <th>Name</th>
 <th>Date/Time</th>
 <th>Playing</th>
 <th>Error</th>
 </tr>
 <tr>
 <td>';
 if(in_array('0', $array, true)){
  echo '<div id="circleGreen"></div>';
 }

 if (in_array('-2', $array, true)){
  echo '<div id="circleRed"></div>';
 }
 echo'</td>
 <td>Guildford test</td>
 <td>'.$array[0].'</td>
 <td>'.$array[1].'</td>
 <td>';

此方法适用于一个 SSH 连接,但我如何 运行 多次 SSH 命令以连接到不同的 PI?

我考虑创建一个 txt 文件并在其中保存每个 SSH 命令,然后让我的 PHP 脚本 read/execute 每个命令行逐行:

// example txt file 
ssh -p 97 -i test.rsa pi@xxx.xxx.xxx.61 
ssh -p 97 -i test2.rsa pi@xxx.xxx.xxx.62 
// and so on..
// only the rsa key name & IP address changes

但我想要一个更有效的解决方案。

更新

按照推荐,我使用 phpsec 库通过 SSH 连接到 PI:

<?php
include('Net/SSH2.php');
include('phpseclib1.0.10/Crypt/RSA.php');

$ssh = new Net_SSH2('192.xxx.xxx.xxx', 97);
$key = new Crypt_RSA();
$key->loadKey(file_get_contents('test.rsa'));

if (!$ssh->login('pi', $key)){
 exit ('Login Failed');
}

echo $ssh->exec('ls -la');
?>

但是这样做我仍然需要输入 IP 地址和 RSA 密钥名称。我想要一个允许我快速 ssh 到多个 PI 并执行 exec 命令的解决方案。

我能想到的一个可能的解决方案是允许我的脚本读取 known_hosts 文件?这可能吗?

这就是我要做的...(制作我自己的配置文件)

//you don't need the ( ) for include/require
//without these files it wont work, should be require then. Classes only need be included 1 time
require_once 'Net/SSH2.php';
require_once 'phpseclib1.0.10/Crypt/RSA.php';
//when you include/require like this it puts the content into the variable
//when that content is a PHP array, it puts it in the variable. This needs to be included each time the script is ran
$config = require 'config.php';
$log = 'logfile.txt';

if(is_array($config)){
    foreach($config as $cred){
        $ssh = new Net_SSH2($cred['ip'], $cred['port']); //i think this is port?
        $key = new Crypt_RSA();
        $key->loadKey($cred['key']);

        if (!$ssh->login('pi', $key)){
             //logging with file_put_contants, Append mode, exclusive lock is more race condition safe then an open file handle.
            file_put_contants($log, "[".date('Y-m-d H:i:s')."]Login Failed for {$cred['ip']}\n", FILE_APPEND|LOCK_EX);
            continue;
            //or you can echo it, but you don't want to kill the whole thing if one fails /maybe?
        }
        //echo or save to file etc.
        echo $ssh->exec('ls -la');
    }
}

然后在 config.php

return [
    [
        "ip" : "127.0.0.1",
        "port": 97,
        "key" : 'ssh-dss AAAAB3NzaC1kc3MAA...c3=',
    ]
    [ ... ]
];

您甚至可以像这样以编程方式修改配置文件

  file_put_contants('config.php', '<?php'."\nreturn ".var_export($config,true).";\n");

var_export 函数以 PHP 兼容格式输出,即。语法正确。然后它的第二个参数是 return 作为字符串。因此,这会将数组转换为与有效 PHP 数组格式相同的字符串。然后添加 <?phpreturn 然后结束 ; 并保存它是非常简单的。

显然,我不建议以这种方式保存任何 "end User" 输入。您可能希望阻止访问此文件。 (例如,放在 webroot 之外)