【问题标题】:Allow PHP script to SSH into multiple servers允许 PHP 脚本通过 SSH 连接到多个服务器
【发布时间】:2018-09-10 21:30:49
【问题描述】:

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

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

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

$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 脚本逐行读取/执行每个命令行:

// 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 文件?这可能吗?

【问题讨论】:

  • 我建议使用 PHPSecLib2.0,它比其他任何 SSH (sFTP) IMO 都好>
  • 您能否给我举个例子来说明如何使用它?关于它的文档不多
  • 有很多文档你只需要知道在哪里看 就像HERE 它比 ssh2 扩展更容易使用大约 1000 倍。 exec 的另一个问题是它不是交互式 shell,每个命令本身都是无状态的。你必须/可以尝试使用 ssh2 扩展,最后我知道它在 windows 上坏了。
  • 作为奖励,它还可以完成AES SSL(例如制作自签名证书)和许多其他加密操作。我发现它唯一缺少的是没有 PGP 加密,但实际上并没有任何易于使用的库。
  • 感谢您的详细回复和链接。我设法让phpseclib woking!我会更新我的答案,这样你就可以看到我做了什么

标签: javascript php for-loop ssh phpseclib


【解决方案1】:

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

//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 兼容格式输出,即。语法正确。然后它的第二个参数作为字符串返回。因此,这会将数组转换为与有效 PHP 数组格式相同的字符串。然后添加&lt;?php 和return 然后添加结尾; 并保存它是非常简单的。

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

【讨论】:

  • 没问题
猜你喜欢
  • 2018-01-28
  • 2014-10-27
  • 1970-01-01
  • 2010-10-02
  • 1970-01-01
  • 1970-01-01
  • 2015-09-04
相关资源
最近更新 更多