前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【PHP小课堂】一起学习PHP中SSH相关扩展的使用

【PHP小课堂】一起学习PHP中SSH相关扩展的使用

作者头像
硬核项目经理
发布2024-06-13 17:43:28
760
发布2024-06-13 17:43:28
举报

一起学习PHP中SSH相关扩展的使用

对于 PHP 来说,很少有用它来做运维相关管理系统的,不过,这并不代表我们 PHP 就不能远程管理服务器了。其实,也是有直接进行远程操作相关的扩展工具供我们使用的,就像我们今天要学习的这个 SSH 扩展。扩展的安装就是正常的 PHP 安装,使用的是 ssh2 这个扩展包,具体的安装过程就不详细说了,直接来看如何使用吧。

连接远程 SSH 服务器

连接过程非常简单,建立连接,然后登录就可以了。

代码语言:javascript
复制
$conn = ssh2_connect('192.168.56.106');
var_dump(ssh2_auth_password($conn, 'root', '123456')); // bool(true)

使用 ssh2_connect() 就可以建立连接并且获得连接句柄。这里我们是本地建立的一台虚拟机,所以直接就使用 root 而且密码也非常简单,大家操作线上服务器时可不能这么任性。而且如果真的需要操作线上真实环境的主机的话,更建议使用密钥的方式来连接,而不是像我们这样直接用户名密码的方式。关于密钥方式也有很多函数可以供大家使用,大家可以自行了解一下。

执行远程命令

连接服务器成功后,最主要的就是能够执行各种操作命令,这个也是我们要使用 ssh2 这个扩展的核心。当然,目的也是为了要进行远程服务器的操控管理。我们有两种执行命令的方式。

单条语句执行

代码语言:javascript
复制
$stream = ssh2_exec($conn, "ls -l /");

$dio_stream = ssh2_fetch_stream($stream, SSH2_STREAM_STDIO);
$err_stream = ssh2_fetch_stream($stream, SSH2_STREAM_STDERR);

stream_set_blocking($dio_stream, true);
stream_set_blocking($err_stream, true);

echo stream_get_contents($dio_stream);
echo  stream_get_contents($err_stream);

// total 152
// drwxrwx---    1 root vboxsf 131072 Dec 31  1979 adata_hd330
// lrwxrwxrwx.   1 root root        7 May 10  2019 bin -> usr/bin
// dr-xr-xr-x.   6 root root     4096 Jan 29 01:54 boot
// drwxr-xr-x   20 root root     3080 Mar  4 19:42 dev
// drwxr-xr-x. 103 root root     8192 Mar  4 19:42 etc
// drwxr-xr-x.   3 root root       23 Mar  4 20:33 home
// lrwxrwxrwx.   1 root root        7 May 10  2019 lib -> usr/lib
// lrwxrwxrwx.   1 root root        9 May 10  2019 lib64 -> usr/lib64
// drwxr-xr-x.   3 root root       19 Jan 29 01:40 media
// drwxr-xr-x.   2 root root        6 May 10  2019 mnt
// drwxr-xr-x.   3 root root       39 Jan 29 02:07 opt
// dr-xr-xr-x  118 root root        0 Mar  4 19:42 proc
// dr-xr-x---.  15 root root     4096 Feb 25 04:58 root
// drwxr-xr-x   32 root root      940 Mar  4 19:43 run
// lrwxrwxrwx.   1 root root        8 May 10  2019 sbin -> usr/sbin
// drwxr-xr-x.   2 root root        6 May 10  2019 srv
// dr-xr-xr-x   13 root root        0 Mar  4 19:41 sys
// drwxrwxrwt.   5 root root      118 Mar  4 20:36 tmp
// drwxr-xr-x.  12 root root      144 Mar 16  2020 usr
// drwxr-xr-x.  21 root root     4096 Mar 16  2020 var

fclose($stream);

对于单独的一条语句来说,我们可以使用 ssh2_exec() 这个函数来直接执行这条命令。它返回的结果是一个流,所以我们需要通过流的方式来读取返回的内容。在这里,我们就是简单地查看一下根目录下的内容。这块的操作非常简单,不过需要注意的是,如果返回的内容非常多的话,就不要使用 stream_get_contents() 了,它的返回大小是有限制的,我们可以使用 fgets() 这类的文件流相关函数来遍历读取。具体内容大家可以查阅官方文档,其中有不少 Notes 都会讲到这个问题。

多条语句批量执行

有时候,我们想一次执行多条命令,这时就可以使用另外一种方式来进行操作。

代码语言:javascript
复制
$shell = ssh2_shell($conn, 'xterm');
fwrite($shell, "mkdir /home/shelltest/;".PHP_EOL);
fwrite($shell, "cd /home;".PHP_EOL);
fwrite($shell, "ls -l /home;". PHP_EOL);
sleep(1);

echo stream_get_contents($shell);
// Activate the web console with: systemctl enable --now cockpit.socket

// Last login: Thu Mar  4 20:36:36 2021 from 192.168.56.102
// mkdir /home/shelltest/;
// cd /home;
// ls -l /home;
// [root@localhost ~]# mkdir /home/shelltest/;
// [root@localhost ~]# cd /home;
// [root@localhost home]# ls -l /home;
// total 0
// drwxr-xr-x 2 root root 20 Mar  4 20:36 shelltest

fclose($shell);

使用 ssh2_shell() 可以看作是打开了一个可以写入的流句柄,然后我们使用 fwrite() 向这个流中写入命令。在这里为什么要 sleep() 一下呢?其实这个流的写入操作并不是同步的,所以如果不加一个暂停的话,可能 PHP 就直接执行过去了,而命令并没有正常地发送完成就中断了。这个是需要注意的地方。同样,我们可以使用 stream_get_contents() 或者其它读取流的方式来获得执行的结果。

在这段代码中,我们建立了一个目录,然后进入它的上级 home 目录中,最后返回目录里面的内容信息。从打印的结果还能够看出,它会输出整个登录后的信息,就像我们真的打开了一个 ssh shell 工具一样。

文件传输

除了命令的操控之外,SSH 中另外一个非常重要的能力就是可以实现 sftp 以及 scp 之类的文件传输的功能,这些功能在 ssh2 扩展中也是支持的。

sftp 上传下载

代码语言:javascript
复制
$sftp = ssh2_sftp($conn);
ssh2_sftp_mkdir($sftp, '/tmp/test/');
copy('./1.txt', "ssh2.sftp://{$sftp}/tmp/test/11.txt");

$stream = ssh2_exec($conn, "ls -l /tmp/test/");

$dio_stream = ssh2_fetch_stream($stream, SSH2_STREAM_STDIO);
$err_stream = ssh2_fetch_stream($stream, SSH2_STREAM_STDERR);

stream_set_blocking($dio_stream, true);
stream_set_blocking($err_stream, true);

echo stream_get_contents($dio_stream);
echo  stream_get_contents($err_stream);

// total 1
// -rw-r--r-- 1 root root 73 Mar  4 20:37 11.txt

fclose($stream);

echo file_get_contents("ssh2.sftp://{$sftp}/tmp/test/11.txt"); // 123123123123123123123123123123123123123123123123123123123123123123123123

首先,我们使用 ssh2_sftp() 函数获取一个 sftp 句柄。然后通过 ssh2_sftp_mkdir() 创建了一个目录。接着,通过普通的 PHP 函数配合 ssh2.sftp 这个伪协议,就可以像操作本地文件一样来操作远程的文件了。是不是非常高大上。

中间的一段代码是通过 ssh2_exec() 去查看我们上传的文件,可以看到文件和目录都是正常存在的。最后,我们通过 file_get_contents() 并且配合伪协议来读取文件的内容,其实这就相当于从远程服务器下载文件了。

之前的文章中我们已经简单地学习过一些伪协议相关的内容,所以这里也就不多解释了,但是不得不说,这种形式的操作真的非常方便和直观。不管是 copy() 还是 file_get_contents() 真的就和我们操作本地文件一样的感觉。

当然,除了上面介绍的 ssh2_sftp() 和 ssh2_sftp_mkdir() 之外,扩展中还有 ssh2_sftp_chmod()、ssh2_sftp_rename()、ssh2_sftp_unlink() 等等的函数,相信从名字大家也能看出它们的作用,这里就不多做解释了,大家可以查阅文档获取相关的资料。

scp 传输文件

最后,我们再来看看更为简单的 scp 方式的文件传输。

代码语言:javascript
复制
ssh2_scp_send($conn, './1.txt', '/home/shelltest/22.txt'); // /home/shelltest/22.txt
ssh2_scp_recv($conn, '/home/shelltest/22.txt', './222.txt'); // ./222.txt

虽说 scp 现在用得不多了(没 rsync 快),不过它的使用可真是方便。ssh2_scp_send() 用于发送一个本地文件到远程服务器,ssh2_scp_recv() 用于从远程服务器拉取一个文件,是不是有点简单的过头了。就跟我们平常使用的 copy() 之类的函数一样的感觉。

总结

今天我们简单的了解了一下 ssh2 这个扩展的一些简单操作,核心的东西也就是这些了。在官方文档中还有很多其它的函数不过都是和密钥登录相关的内容,在这里也就不多赘述了,有需要的小伙伴自己查阅一下就可以,而且他们的使用都并不复杂。剩下的就是 sftp 和 scp 相关的内容了。总体来说,这个扩展还是比较方便好用的,如果只是简单的小型的运维管理功能,是完全可以满足的,当然,具体业务具体分析,使用什么还是大家自己定夺。

测试代码:

https://github.com/zhangyue0503/dev-blog/blob/master/php/2021/03/source/3.%E4%B8%80%E8%B5%B7%E5%AD%A6%E4%B9%A0PHP%E4%B8%ADSSH%E7%9B%B8%E5%85%B3%E6%89%A9%E5%B1%95%E7%9A%84%E4%BD%BF%E7%94%A8.php

参考文档:

https://www.php.net/manual/zh/book.ssh2.php

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-06-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码农老张 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一起学习PHP中SSH相关扩展的使用
    • 连接远程 SSH 服务器
      • 执行远程命令
        • 单条语句执行
        • 多条语句批量执行
      • 文件传输
        • sftp 上传下载
        • scp 传输文件
      • 总结
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档