允许 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 数组格式相同的字符串。然后添加 <?php
和 return
然后结束 ;
并保存它是非常简单的。
显然,我不建议以这种方式保存任何 "end User" 输入。您可能希望阻止访问此文件。 (例如,放在 webroot 之外)
我有一个位于 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 数组格式相同的字符串。然后添加 <?php
和 return
然后结束 ;
并保存它是非常简单的。
显然,我不建议以这种方式保存任何 "end User" 输入。您可能希望阻止访问此文件。 (例如,放在 webroot 之外)