PHP Conference Japan 2024

ssh2_shell

(PECL ssh2 >= 0.9.0)

ssh2_shell请求交互式 Shell

描述

ssh2_shell(
    资源 $session,
    字符串 $termtype = "vanilla",
    ?数组 $env = null,
    整数 $width = 80,
    整数 $height = 25,
    整数 $width_height_type = SSH2_TERM_UNIT_CHARS
): 资源|false

在远程端打开一个 Shell 并为其分配一个流。

参数

session

一个 SSH 连接链接标识符,从调用 ssh2_connect() 获取。

termtype

termtype 应对应于目标系统 /etc/termcap 文件中的一个条目。

env

env 可以作为名称/值对的关联数组传递,以在目标环境中设置。

width

虚拟终端的宽度。

height

虚拟终端的高度。

width_height_type

width_height_type 应为 SSH2_TERM_UNIT_CHARSSSH2_TERM_UNIT_PIXELS 之一。

返回值

如果成功,则返回一个流 资源,如果失败,则返回 false

示例

示例 #1 请求交互式 Shell

<?php
$connection
= ssh2_connect('shell.example.com', 22);
ssh2_auth_password($connection, 'username', 'password');

$stream = ssh2_shell($connection, 'vt102', null, 80, 24, SSH2_TERM_UNIT_CHARS);
?>

参见

添加注释

用户贡献的注释 9 条注释

stefanov at uk dot ibm dot com
16 年前
不要使用 \n 结束命令。某些服务器将无法处理。始终使用 PHP 的标准换行符:PHP_EOL

'suri at suribala dot com"' 的示例应修改如下(也更改双引号为单引号,以提高性能)

<?php

$con
=ssh2_connect('192.168.0.1', 22);
ssh2_auth_password($con, 'user', 'password');
$shell=ssh2_shell($con, 'xterm');
fwrite( $shell, 'cd /dir_one;'.PHP_EOL);
fwrite( $shell, 'ls -la;'.PHP_EOL);
fwrite( $shell, 'cd /dir_two;'.PHP_EOL);
fwrite( $shell, 'ls -la;'.PHP_EOL);

?>

干杯!

Pimmy
tuxedobob at mac dot com
10 年前
请记住,在使用 ssh2_shell 时,远程系统的 EOL 可能与 PHP 的 EOL 不同,因此使用 PHP_EOL 可能不安全。Windows 的原生 EOL 为 \r\n,而 Unix 通常仅为 \n,而经典 Mac 由于某种原因为 \r。

如果在 Windows(\r\n)上运行 PHP 并 ssh 到 Unix 盒子(\n),则最终会发送额外的行。到目前为止,我的经验是它就像您什么也没输入一样,这可能会导致密码提示出现问题。

哦,还有 \n\r?不要那样做。没有人那样做。
galvao at galvao dot eti dot br
17 年前
回复 webmaster at spectreanime dot com

"出于某些模糊的原因,在您的命令之后,您需要进行休眠以确保命令已到达服务器并正在运行"

实际上,您需要做的是将字符串的阻塞设置为 true,这样它就会等到服务器将数据发送到 STDOUT 然后再将其回显。

因此,而不是

sleep(1);

只需执行

stream_set_blocking($stdio, true);

此致!
webmaster at spectreanime dot com
19 年前
// 连接到 SSH 服务器
echo "SSH 连接 ";
if (!($resource=@ssh2_connect("192.168.0.1"))) {
echo "[失败]<br />";
exit(1);
}
echo "[成功]<br />";

// 通过登录名/密码进行身份验证
echo "身份验证 ";
if (!@ssh2_auth_password($resource,"root","your_password")) {
echo "[失败]<br />";
exit(1);
}
echo "[成功]<br />";

// 我们需要一个 Shell
echo "Shell stdio ";
if (!($stdio = @ssh2_shell($resource,"xterm"))) {
echo "[失败]<br />";
exit(1);
}
echo "[成功]<br />";

// 执行任何命令
// 注意在命令末尾添加 '\n'
$command = "/bin/ls /tmp\n";
fwrite($stdio,$command);

// 重要
// 出于某些模糊的原因,在您的命令之后,您需要进行休眠以确保命令已到达服务器并正在运行
sleep(1);

// 然后您可以获取流以查看 stdio 上发生了什么
while($line = fgets($stdio)) {
flush();
echo $line."<br />";
}

// 关闭所有流始终更干净
fclose($stdio);

我真心希望我能帮助到某人 :)
josh at hydril dot com
17 年前
要运行一个包含您在交互式登录时拥有的所有变量的 Shell 脚本,请在命令前面添加 bash -l 或 sh --login。我使用的脚本创建了一个 Shell 脚本,使用 ssh2_scp_send 将脚本复制到盒子,然后使用 ssh2_exec 执行脚本。希望这对某些人有所帮助。

<?php

//示例

$script1 = "bash -l /etc/rc.d/rc.httpd restart";

$connection = ssh2_connect('shell.example.com', 22);
ssh2_auth_password($connection, 'username', 'password');

$stream = ssh2_exec($connection, $script1);
?>
[email protected]
17 年前
您好,

我们还可以使用 shell_exec 执行多个相关的命令
用分号 (;) 分隔。

我发现有时在执行复杂的 Java、C/C++ 程序时会出现问题。我们只需设置所需的 环境变量即可。我在 .bash_profile 中有一个环境变量。当通过 shell 以正常方式登录到我的帐户时,此变量将被设置。但是,当我们使用 ssh2_connect() 时,.bash_profile 中的环境变量不会被设置,我们只需使用 shell_exec() 导出所需的 环境变量即可;

示例

$conn = ssh2_connect($ipaddress);
ssh2_auth_password($conn,$username,$passwd);
$cmd1="/path/to/program1";
$cmd2="/path/to/program2";
$env1="export Variable_name1=path1";
$env2="export Variable_name2=path2"
$stream = ssh2_exec($connection,"$env1; $env2; $cmd1; $cmd2");//这将执行所有//命令并返回
// 流
stream_set_blocking($stream, true);
while($o=fgets($stream)){
echo $o.'<br>';
}

...
...

谢谢,
Vikram Gopu。
http:\\my.lsu.edu/vgopu1
[email protected]
4 年前
我得到了一个用于执行多个命令的工作脚本。此脚本将每个命令的输出返回到数组中,并按“命令”索引。

注意:ssh2_cmd() 不适用于多个命令,因此使用 ssh2_shell()。请注意不同操作系统上的 EOL(行结束符)。我在每个命令的末尾使用了“\n”,但可能还有其他选项,例如“<br>”、“;”等;

$connection = ssh2_connect($input_host_ip, 22);

if (false === $connection) {
error_log("ERROR 函数 SSH_UMTELECOM:连接失败!\n",3,$log_file);
exit();
}else{
if($debugar){error_log("SSH_UMTELECOM:成功连接到 $input_host_ip!\n",3,$log_file);}

$auth = @ssh2_auth_password($connection, $user, $pass);
if (false === $auth) {
error_log("ERROR 函数 SSH_UMTELECOM:$input_host_ip 上的身份验证失败(用户:$user)!\n",3,$log_file);
exit();
}else{
if($debugar){error_log("SSH_UMTELECOM:成功连接到 $input_host_ip!\n",3,$log_file);}

error_log("启动流:$connection\n",3,$log_file);
$output_array = array();
$shell = ssh2_shell($connection, 'vt100');

foreach($input_cmd as $cmd){
if($debugar){error_log("shell:$cmd\n",3,$log_file);}
$output_stream = ""; # 清空每次迭代的变量
fwrite($shell, "$cmd\n"); # 不要忘记在每个命令末尾加上“\n”
#stream_set_blocking($shell, true); # 不起作用,无限期等待
sleep(2); # 对于高延迟网络,等待 2 秒
while($output_streams = fgets($shell)){
$output_stream .= $output_streams;
flush();# 清空内容以进行下一次迭代
}
$output_array[] = $output_stream; # 将每个返回值合并到其相应的命令中
}
fclose($shell); # 优雅地退出 shell
}# 结束 if false === $auth
}# 结束 if false === $conenection
[email protected]
13 年前
在我的情况下,ssh2_shell 并非每次都能正常工作。遇到了很多问题
- 如果我使用 stream_get_contents,则命令永远不会执行
- 使用 while ($buf = fgets...) 循环永远不会停止
- 在 stream_set_blocking 之前没有使用 sleep(1),命令并非每次都能执行。有人知道为什么吗?
这是我所做的,它可以工作 - 但我认为这不是它应该有的样子
<?php
$strCommand
= 'tar -C /path/to/extract -xjf /path/from/file.tar.bz2';
$sshStream = ssh2_shell($this->sshSession, 'xterm', null, 120, 24, SSH2_TERM_UNIT_CHARS);
fwrite($sshStream, $strCommand . PHP_EOL);
sleep(1);
stream_set_blocking($sshStream, true);
$sshUntarRetval = "";
while (
$buf = fgets($sshStream,4096)) {
flush();
$sshUntarRetval .= $buf;
if (
strpos($buf, 'tar -C') !== false)
{
break;
}
}
fclose($sshStream);
?>
[email protected]
19 年前
使用 ssh_exec,一次只能执行一个命令。但是,ssh_shell 提供了更大的灵活性。

这是一个示例

<?php

$con
=ssh2_connect('192.168.0.1', 22);
ssh2_auth_password($con, "user", "password");
$shell=ssh2_shell($con, 'xterm');
fwrite( $shell, "cd /dir_one\n");
fwrite( $shell, "ls -la\n");
fwrite( $shell, "cd /dir_two\n");
fwrite( $shell, "ls -la\n");

?>

感谢 Sara 的实现和帮助!
To Top