如何通过PHP执行SSH命令
我正在通过PHP寻找SSH。什么是最好/最安全的方式去做这件事?我知道我可以这样做:如何通过PHP执行SSH命令
shell_exec("SSH [email protected] mkdir /testing");
还好吗?这感觉很“调皮”:)。
您是否有可用的SSH2扩展?
文档:http://www.php.net/manual/en/function.ssh2-exec.php
$connection = ssh2_connect('shell.example.com', 22);
ssh2_auth_password($connection, 'username', 'password');
$stream = ssh2_exec($connection, '/usr/local/bin/php -i');
我在PHP中使用ssh2很困难,主要是因为输出流有时会起作用,有时却不起作用。我只是要把我的lib放在这里,这对我很好。如果在代码不一致小是因为我把它插在一个框架,但你应该罚款将它移植:
<?php
class Components_Ssh {
private $host;
private $user;
private $pass;
private $port;
private $conn = false;
private $error;
private $stream;
private $stream_timeout = 100;
private $log;
private $lastLog;
public function __construct ($host, $user, $pass, $port, $serverLog) {
$this->host = $host;
$this->user = $user;
$this->pass = $pass;
$this->port = $port;
$this->sLog = $serverLog;
if ($this->connect()->authenticate()) {
return true;
}
}
public function isConnected() {
return (boolean) $this->conn;
}
public function __get ($name) {
return $this->$name;
}
public function connect() {
$this->logAction ("Connecting to {$this->host}");
if ($this->conn = ssh2_connect ($this->host, $this->port)) {
return $this;
}
$this->logAction ("Connection to {$this->host} failed");
throw new Exception ("Unable to connect to {$this->host}");
}
public function authenticate() {
$this->logAction ("Authenticating to {$this->host}");
if (ssh2_auth_password ($this->conn, $this->user, $this->pass)) {
return $this;
}
$this->logAction ("Authentication to {$this->host} failed");
throw new Exception ("Unable to authenticate to {$this->host}");
}
public function sendFile ($localFile, $remoteFile, $permision = 0644) {
if (! is_file ($localFile)) throw new Exception ("Local file {$localFile} does not exist");
$this->logAction ("Sending file $localFile as $remoteFile");
$sftp = ssh2_sftp ($this->conn);
$sftpStream = @fopen ('ssh2.sftp://' . $sftp . $remoteFile, 'w');
if (! $sftpStream) {
// if 1 method failes try the other one
if (! @ssh2_scp_send ($this->conn, $localFile, $remoteFile, $permision)) {
throw new Exception ("Could not open remote file: $remoteFile");
}
else {
return true;
}
}
$data_to_send = @file_get_contents ($localFile);
if (@fwrite ($sftpStream, $data_to_send) === false) {
throw new Exception ("Could not send data from file: $localFile.");
}
fclose ($sftpStream);
$this->logAction ("Sending file $localFile as $remoteFile succeeded");
return true;
}
public function getFile ($remoteFile, $localFile) {
$this->logAction ("Receiving file $remoteFile as $localFile");
if (ssh2_scp_recv ($this->conn, $remoteFile, $localFile)) {
return true;
}
$this->logAction ("Receiving file $remoteFile as $localFile failed");
throw new Exception ("Unable to get file to {$remoteFile}");
}
public function cmd ($cmd, $returnOutput = false) {
$this->logAction ("Executing command $cmd");
$this->stream = ssh2_exec ($this->conn, $cmd);
if (FALSE === $this->stream) {
$this->logAction ("Unable to execute command $cmd");
throw new Exception ("Unable to execute command '$cmd'");
}
$this->logAction ("$cmd was executed");
stream_set_blocking ($this->stream, true);
stream_set_timeout ($this->stream, $this->stream_timeout);
$this->lastLog = stream_get_contents ($this->stream);
$this->logAction ("$cmd output: {$this->lastLog}");
fclose ($this->stream);
$this->log .= $this->lastLog . "\n";
return ($returnOutput) ? $this->lastLog : $this;
}
public function shellCmd ($cmds = array()) {
$this->logAction ("Openning ssh2 shell");
$this->shellStream = ssh2_shell ($this->conn);
sleep (1);
$out = '';
while ($line = fgets ($this->shellStream)) {
$out .= $line;
}
$this->logAction ("ssh2 shell output: $out");
foreach ($cmds as $cmd) {
$out = '';
$this->logAction ("Writing ssh2 shell command: $cmd");
fwrite ($this->shellStream, "$cmd" . PHP_EOL);
sleep (1);
while ($line = fgets ($this->shellStream)) {
$out .= $line;
sleep (1);
}
$this->logAction ("ssh2 shell command $cmd output: $out");
}
$this->logAction ("Closing shell stream");
fclose ($this->shellStream);
}
public function getLastOutput() {
return $this->lastLog;
}
public function getOutput() {
return $this->log;
}
public function disconnect() {
$this->logAction ("Disconnecting from {$this->host}");
// if disconnect function is available call it..
if (function_exists ('ssh2_disconnect')) {
ssh2_disconnect ($this->conn);
}
else { // if no disconnect func is available, close conn, unset var
@fclose ($this->conn);
$this->conn = false;
}
// return null always
return NULL;
}
public function fileExists ($path) {
$output = $this->cmd ("[ -f $path ] && echo 1 || echo 0", true);
return (bool) trim ($output);
}
}
谢谢!这一个帮助了很多。我重写了它使用公钥/私钥身份验证,但睡眠(1)杀死了我的生产力。如果我有时间想出解决办法,我会让你知道。谢谢! – jbrahy 2014-10-13 22:01:48
我会用phpseclib, a pure PHP SSH implementation。举个例子:
<?php
include('Net/SSH2.php');
$ssh = new Net_SSH2('www.domain.tld');
if (!$ssh->login('username', 'password')) {
exit('Login Failed');
}
echo $ssh->exec('pwd');
echo $ssh->exec('ls -la');
?>
这些可以是异步的吗?我需要同时与多个系统通话 - 我可以启动多个ssh会话,然后“选择”(或轮询)所有这些会话吗?.. – 2013-11-01 04:25:44
有点。真的,你的问题会更适合作为一个新的而不是回复,但无论如何。您可以为每个$ ssh实例执行'$ ssh-> setTimeout(...)'并循环执行它们。互动模式可能对你更好,因为阅读和写作有点不相干。同样的,你可以做enablePTY()我猜想''ssh-> exec()'用'ssh-> read()'/'$ ssh-> write()'。 – neubert 2014-01-02 21:57:34
请注意,这个库不支持readlink() – Alexander 2014-03-27 16:43:56
无法获取血腥SSH2模块去,渐渐在错误日志中的以下内容:PHP的警告:PHP启动:SSH2:无法初始化模块 模块与模块API = 20050922 PHP编译编译与模块API = 20090626 这些选项需要匹配 未知的行0 – Justin 2011-06-07 19:34:20
什么操作系统和版本,以及什么PHP版本? – 2011-06-07 19:39:12
另请注意,您必须拥有OpenSSL和libssh2才能使ssh2模块正常工作。如果您手动构建PHP,则必须确保您具有两个所需模块的兼容版本。该错误表示版本不匹配。 – 2011-06-07 19:41:18