如何通过 PHP 执行 SSH 命令
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6270419/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How To Execute SSH Commands Via PHP
提问by Justin
I am looking to SSH out via PHP. What is the best/most secure way to go about this? I know I can do:
我正在寻找通过 PHP 进行 SSH 输出。最好/最安全的方法是什么?我知道我可以做到:
shell_exec("SSH [email protected] mkdir /testing");
Anything better? That feels so 'naughty' :).
有什么更好的吗?那感觉太“顽皮”了:)。
回答by
I would use phpseclib, a pure PHP SSH implementation. An example:
我会使用phpseclib,一个纯 PHP SSH 实现。一个例子:
<?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');
?>
回答by Chris Baker
Do you have the SSH2 extension available?
你有可用的 SSH2 扩展吗?
Docs: http://www.php.net/manual/en/function.ssh2-exec.php
文档: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');
回答by Romeo M.
I've had a hard time with ssh2 in php mostly because the output stream sometimes works and sometimes it doesn't. I'm just gonna paste my lib here which works for me very well. If there are small inconsistencies in code it's because I have it plugged in a framework but you should be fine porting it:
我在 php 中使用 ssh2 时遇到了困难,主要是因为输出流有时有效,有时无效。我只是将我的库粘贴在这里,这对我来说非常有用。如果代码中存在小的不一致,那是因为我将它插入了一个框架中,但您应该可以很好地移植它:
<?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 );
}
}
回答by Ziad Akiki
For those using the Symfonyframework, the phpseclibcan also be used to connect via SSH. It can be installed using composer:
对于那些使用Symfony框架的人,phpseclib也可用于通过 SSH 进行连接。它可以使用 composer 安装:
composer require phpseclib/phpseclib
Next, simply use it as follows:
接下来,只需按如下方式使用它:
use phpseclib\Net\SSH2;
// Within a controller for example:
$ssh = new SSH2('hostname or ip');
if (!$ssh->login('username', 'password')) {
// Login failed, do something
}
$return_value = $ssh->exec('command');
回答by T.Todua
//Update 2018, works//
// 2018 年更新,有效//
Method1:
方法一:
Download phpseclib v1and use this code:
下载phpseclib v1并使用以下代码:
<?php
set_include_path(__DIR__ . '/phpseclib1.0.11');
include("Net/SSH2.php");
$key ="MyPassword";
/* ### if using PrivateKey ###
include("Crypt/RSA.php");
$key = new Crypt_RSA();
$key->loadKey(file_get_contents('private-key.ppk'));
*/
$ssh = new Net_SSH2('www.example.com', 22); // Domain or IP
if (!$ssh->login('your_username', $key)) exit('Login Failed');
echo $ssh->exec('pwd');
?>
or Method2:
或方法2:
Download newest phpseclib v2(requires composer install
at first):
下载最新的phpseclib v2(composer install
首先需要):
<?php
set_include_path($path=__DIR__ . '/phpseclib-master/phpseclib');
include ($path.'/../vendor/autoload.php');
$loader = new \Composer\Autoload\ClassLoader();
use phpseclib\Net\SSH2;
$key ="MyPassword";
/* ### if using PrivateKey ###
use phpseclib\Crypt\RSA;
$key = new RSA();
$key->load(file_get_contents('private-key.ppk'));
*/
$ssh = new SSH2('www.example.com', 22); // Domain or IP
if (!$ssh->login('your_username', $key)) exit('Login Failed');
echo $ssh->exec('pwd');
?>
p.s. if you get "Connection timed out" then it's probably the issue of HOST/FIREWALL (local or remote) or like that, not a fault of script.
ps 如果你得到“连接超时”,那么它可能是主机/防火墙(本地或远程)或类似的问题,而不是脚本的错误。