本文目录导读:

在PHP项目中通过SSH远程管理服务器并执行命令,主要有以下几种方法:
使用 PHP SSH2 扩展(推荐)
安装 SSH2 扩展
# Ubuntu/Debian sudo apt-get install php-ssh2 # CentOS/RHEL sudo yum install php-devel php-pear libssh2 libssh2-devel sudo pecl install ssh2 # 启用扩展 echo "extension=ssh2.so" | sudo tee /etc/php/7.4/mods-available/ssh2.ini
基础使用示例
<?php
class SSHManager {
private $connection;
private $host;
private $port;
public function __construct($host, $port = 22) {
$this->host = $host;
$this->port = $port;
}
public function connect($username, $password) {
$this->connection = ssh2_connect($this->host, $this->port);
if (!$this->connection) {
throw new Exception("无法连接到服务器");
}
if (!ssh2_auth_password($this->connection, $username, $password)) {
throw new Exception("认证失败");
}
return true;
}
public function executeCommand($command) {
if (!$this->connection) {
throw new Exception("未建立连接");
}
$stream = ssh2_exec($this->connection, $command);
if (!$stream) {
throw new Exception("命令执行失败");
}
stream_set_blocking($stream, true);
$output = stream_get_contents($stream);
fclose($stream);
return $output;
}
public function disconnect() {
if ($this->connection) {
ssh2_disconnect($this->connection);
$this->connection = null;
}
}
}
// 使用示例
try {
$ssh = new SSHManager('192.168.1.100', 22);
$ssh->connect('root', 'password');
// 执行单个命令
$result = $ssh->executeCommand('ls -la');
echo "命令输出:\n" . $result;
// 执行多个命令
$commands = [
'pwd',
'whoami',
'df -h',
'free -m'
];
foreach ($commands as $cmd) {
echo "执行: $cmd\n";
echo $ssh->executeCommand($cmd) . "\n";
}
$ssh->disconnect();
} catch (Exception $e) {
echo "错误: " . $e->getMessage();
}
?>
使用密钥认证
生成SSH密钥对
ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa_php ssh-copy-id -i ~/.ssh/id_rsa_php.pub user@remote_server
PHP代码实现
<?php
class SSHKeyAuth extends SSHManager {
private $publicKeyFile;
private $privateKeyFile;
private $passphrase;
public function __construct($host, $port = 22) {
parent::__construct($host, $port);
}
public function setKeyFiles($publicKey, $privateKey, $passphrase = null) {
$this->publicKeyFile = $publicKey;
$this->privateKeyFile = $privateKey;
$this->passphrase = $passphrase;
}
public function connectWithKey($username) {
$this->connection = ssh2_connect($this->host, $this->port);
if (!ssh2_auth_pubkey_file(
$this->connection,
$username,
$this->publicKeyFile,
$this->privateKeyFile,
$this->passphrase
)) {
throw new Exception("密钥认证失败");
}
return true;
}
}
// 使用示例
try {
$ssh = new SSHKeyAuth('192.168.1.100');
$ssh->setKeyFiles(
'/home/user/.ssh/id_rsa_php.pub',
'/home/user/.ssh/id_rsa_php',
'your_passphrase' // 可选,如果密钥没有密码可以设为null
);
$ssh->connectWithKey('remote_user');
// 执行命令
$result = $ssh->executeCommand('uptime');
echo "服务器运行时间:\n" . $result;
$ssh->disconnect();
} catch (Exception $e) {
echo "错误: " . $e->getMessage();
}
?>
使用 phpseclib 库(纯PHP实现)
安装 phpseclib
composer require phpseclib/phpseclib
使用示例
<?php
require 'vendor/autoload.php';
use phpseclib3\Net\SSH2;
class PHPSSHManager {
private $ssh;
public function __construct($host, $port = 22) {
$this->ssh = new SSH2($host, $port);
}
public function connect($username, $password = null, $key = null) {
if ($key) {
// 密钥认证
$auth = $this->ssh->login($username, $key);
} elseif ($password) {
// 密码认证
$auth = $this->ssh->login($username, $password);
} else {
throw new Exception("请提供密码或密钥");
}
if (!$auth) {
throw new Exception("登录失败");
}
return true;
}
public function executeCommand($command) {
return $this->ssh->exec($command);
}
public function executeInteractiveCommand($command, $callback = null) {
if ($callback) {
$this->ssh->exec($command, $callback);
} else {
return $this->ssh->exec($command);
}
}
public function getLastError() {
return $this->ssh->getLastError();
}
public function disconnect() {
$this->ssh->disconnect();
}
}
// 密码认证示例
$ssh = new PHPSSHManager('192.168.1.100');
$ssh->connect('root', 'password');
echo $ssh->executeCommand('ls -la');
// 密钥认证示例
$key = \phpseclib3\Crypt\PublicKeyLoader::load(
file_get_contents('/home/user/.ssh/id_rsa'),
'your_passphrase' // 如果密钥有密码
);
$ssh2 = new PHPSSHManager('192.168.1.100');
$ssh2->connect('remote_user', null, $key);
echo $ssh2->executeCommand('whoami');
// 交互式命令执行
$ssh3 = new PHPSSHManager('192.168.1.100');
$ssh3->connect('root', 'password');
$output = $ssh3->executeInteractiveCommand('tail -f /var/log/syslog', function($data) {
echo $data;
});
?>
最佳实践 - 完整的SSH管理类
<?php
require 'vendor/autoload.php';
use phpseclib3\Net\SSH2;
use phpseclib3\Crypt\RSA;
class SecureSSHManager {
private $ssh;
private $connected = false;
private $error = null;
private $timeout = 30;
public function __construct($host, $port = 22, $timeout = 30) {
$this->ssh = new SSH2($host, $port);
$this->ssh->setTimeout($timeout);
}
public function connectWithPassword($username, $password) {
try {
if (!$this->ssh->login($username, $password)) {
throw new Exception("密码认证失败");
}
$this->connected = true;
return true;
} catch (Exception $e) {
$this->error = $e->getMessage();
return false;
}
}
public function connectWithKey($username, $privateKeyPath, $passphrase = null) {
try {
$key = RSA::load(file_get_contents($privateKeyPath));
if ($passphrase) {
$key = $key->withPassword($passphrase);
}
if (!$this->ssh->login($username, $key)) {
throw new Exception("密钥认证失败");
}
$this->connected = true;
return true;
} catch (Exception $e) {
$this->error = $e->getMessage();
return false;
}
}
public function execute($command) {
if (!$this->connected) {
$this->error = "未连接到服务器";
return false;
}
$output = $this->ssh->exec($command);
if ($output === false) {
$this->error = "命令执行失败";
return false;
}
return $output;
}
public function executeCommands(array $commands, $separator = ' && ') {
return $this->execute(implode($separator, $commands));
}
public function uploadFile($localFile, $remoteFile) {
try {
return $this->ssh->put($remoteFile, $localFile, SSH2::SOURCE_LOCAL_FILE);
} catch (Exception $e) {
$this->error = $e->getMessage();
return false;
}
}
public function downloadFile($remoteFile, $localFile) {
try {
return $this->ssh->get($remoteFile, $localFile);
} catch (Exception $e) {
$this->error = $e->getMessage();
return false;
}
}
public function getError() {
return $this->error;
}
public function isConnected() {
return $this->connected;
}
public function disconnect() {
if ($this->connected) {
$this->ssh->disconnect();
$this->connected = false;
}
}
public function __destruct() {
$this->disconnect();
}
}
// 完整使用示例
$ssh = new SecureSSHManager('192.168.1.100', 22);
// 连接方式1:密码认证
if ($ssh->connectWithPassword('root', 'your_password')) {
echo "连接成功\n";
// 执行单个命令
$result = $ssh->execute('ls -la /var/www');
echo $result;
// 执行多个命令
$commands = [
'cd /var/www',
'git pull origin master',
'composer install',
'php artisan migrate'
];
$result = $ssh->executeCommands($commands);
echo $result;
// 上传文件
$ssh->uploadFile('/local/file.txt', '/remote/file.txt');
// 下载文件
$ssh->downloadFile('/remote/backup.sql', '/local/backup.sql');
$ssh->disconnect();
} elseif ($ssh->connectWithKey('webuser', '/home/user/.ssh/id_rsa', 'passphrase')) {
// 连接方式2:密钥认证
echo "密钥认证连接成功\n";
// ... 执行命令
} else {
echo "连接失败: " . $ssh->getError();
}
?>
安全性建议
配置示例
<?php
// 安全配置
$config = [
'host' => '192.168.1.100',
'port' => 22,
'username' => 'webapp',
'key_file' => '/etc/ssh/keys/webapp_rsa',
'known_hosts' => '/etc/ssh/ssh_known_hosts',
'timeout' => 30,
'allowed_commands' => [
'deploy' => 'cd /var/www && git pull && composer install',
'backup' => 'mysqldump -u root mydb > /backup/db.sql',
'status' => 'systemctl status nginx',
]
];
// 使用白名单命令执行
class SafeSSHExecutor {
private $config;
private $ssh;
public function __construct($config) {
$this->config = $config;
}
public function executeAllowedCommand($commandName) {
if (!isset($this->config['allowed_commands'][$commandName])) {
throw new Exception("不允许的命令: $commandName");
}
$command = $this->config['allowed_commands'][$commandName];
return $this->executeWithTimeout($command);
}
private function executeWithTimeout($command) {
// 设置命令执行超时
$timeout = $this->config['timeout'];
// ... 执行命令
}
}
?>
日志记录
<?php
class LoggingSSHManager extends SecureSSHManager {
private $logFile;
public function __construct($host, $port = 22, $logFile = '/var/log/ssh_commands.log') {
parent::__construct($host, $port);
$this->logFile = $logFile;
}
public function execute($command) {
$result = parent::execute($command);
// 记录日志
$logEntry = sprintf(
"[%s] User: %s | Command: %s | Result length: %d\n",
date('Y-m-d H:i:s'),
$this->getCurrentUser(),
$command,
strlen($result ?? '')
);
file_put_contents($this->logFile, $logEntry, FILE_APPEND);
return $result;
}
}
?>
注意事项
- 安全第一:不建议直接在代码中硬编码密码,使用密钥认证更安全
- 错误处理:始终包含适当的异常处理
- 命令注入:对用户输入进行严格过滤
- 超时设置:避免长时间等待
- 日志记录:记录所有执行的命令用于审计
- 最小权限:使用最低权限的SSH用户
- 连接池:频繁操作时考虑复用连接
选择合适的方案取决于你的具体需求、服务器配置和安全要求,phpseclib 是最兼容的方案,因为它不需要安装额外的扩展。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播