从外部进程获取 SSH 客户端进程内的工作目录

从外部进程获取 SSH 客户端进程内的工作目录

我已经通过 SSH 连接到远程计算机。我想获取ls该远程计算机上的当前工作目录(并且最好执行类似的命令),但要从该进程外部获取。

这是我的流程

$ ps
49100 ttys001    0:00.21 -zsh
52134 ttys002    0:00.21 -zsh
52171 ttys002    0:00.05 ssh [email protected]

终端 2 (ttys002) 是我当前通过 SSH 连接到远程计算机的位置。

是否可以从客户端计算机获取远程主机的当前工作目录?即无需pwd在终端 2 中输入。

如果我运行lsof,我可以获取进程本地计算机上的当前工作目录,但不能获取远程计算机的当前工作目录。

~ $ lsof -p 52171
COMMAND   PID    USER   FD      TYPE             DEVICE SIZE/OFF                NODE NAME
ssh     52175   falky  cwd       DIR                1,4     2816              994619 /Users/falky

如果这是不可能的,那么在通过 SSH 连接到远程计算机之前我是否可以做一些事情来允许我执行此操作?例如,我可以设置一个伪终端吗?或者我可以在远程计算机上安装一些东西,将 ping 发送回我的本地计算机吗?这里的任何建议/方向都会有帮助。

答案1

如果这是不可能的,那么在通过 SSH 连接到远程计算机之前我是否可以做一些事情来允许我执行此操作?

您可以在“连接共享模式”下启动 ssh 客户端:

ssh -M -S ~/.ssh/%r@%h:%p user@localhost
user@localhost's password:
...
user@localhost$ echo $$
5555
user@localhost$ cd /some/path

在另一个终端中:

ssh -S ~/.ssh/%r@%h:%p user@localhost
<no need to enter the password again>
user@localhost$ ls -l /proc/5555/cwd
<listing of /some/path>

请参阅ssh(1)联机帮助页以了解-S-M选项,并ssh_config(1)Control*配置选项。

答案2

您可以做到这一点的唯一方法是

  1. 使用 ioctl 将命令注入本地终端TIOCSTI。这在 OpenBSD 上不起作用,而在 Linux 上,您需要 cap CAP_SYS_ADMIN(即 root)才能在调用进程的控制 tty 之外的其他 tty 上使用它。您已经TIOCSTI在此站点上找到了很多使用示例。

  2. ptrace(2)通过(例如通过或其他调试器)操纵 ssh 客户端,gdb(1)并将命令注入其加密通道。如何做到这一点很大程度上取决于 ssh 客户端内部结构(对于准备运行的示例,您需要一个使用调试符号编译的 ssh 客户端)。就像任何其他解决方案一样ptrace(2),它不适用于其他用户的进程(或者如果该进程使其自身不可转储),除非您有上限CAP_SYS_PTRACE(即您是 root)。

  3. 按照第 2 点进行操作。控制 ssh 客户端运行的伪 tty 主机端的进程,并将命令写入伪 tty 主机的文件描述符中。因为我们必须将数据写入文件描述符,而不是写入某些内部通道,所以给出一个示例可能更容易:

在终端中:

$ tty
echo $PPID
6666
$ ssh localhost
localhost$ cd /tmp
localhost$

在另一个终端中,假设PPID=6666(本地 shell 的父进程)是终端仿真器的进程(不能保证!),并且您可以正确猜测哪个文件描述符引用该 shell 的终端(当终端仿真器运行时很难做到这一点)是某种单进程多路复用器,如 GNU screen):

$ pid=6666
$ ls -l /proc/$pid/fd
...

lrwx------ 1 xxx xxx 64 Oct 12 08:52 3 -> /dev/ptmx  # the pty master
...
$ grep flags /proc/$pid/fdinfo/3
flags:  0104002    # OK, it's opened in rw mode (2)
$ gdb -p $pid
...
(gdb) call write(3, "pwd\r", 4)
$1 = 4
(gdb) continue
Continuing.
...

如果一切顺利,该pwd命令将在远程 ssh 中运行。

如果您能够控制 ssh 的启动方式,则可以确保按照第 3 点控制伪 tty 的进程是一些简单的进程,而不是一些复杂的多路复用器。在 Linux 上,您可以使用script(1)实用程序:

script /dev/null -c 'ssh user@host'

script=进程内 tty master 的文件描述符总是在 Linux 上为 3,您不必担心 ssh 是直接运行还是通过/bin/some/sh -c.

相关内容