我正在通過PHP尋找SSH。什麼是最好/最安全的方式去做這件事?我知道我可以這樣做:如何通過PHP執行SSH命令
shell_exec("SSH [email protected] mkdir /testing");
還好嗎?這感覺很「調皮」:)。
我正在通過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');
使用ssh2
功能。任何通過exec()調用完成的任務都可以使用這些函數直接完成,爲您節省大量連接和shell調用。
我在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