![从外部进程获取 SSH 客户端进程内的工作目录](https://linux22.com/image/181604/%E4%BB%8E%E5%A4%96%E9%83%A8%E8%BF%9B%E7%A8%8B%E8%8E%B7%E5%8F%96%20SSH%20%E5%AE%A2%E6%88%B7%E7%AB%AF%E8%BF%9B%E7%A8%8B%E5%86%85%E7%9A%84%E5%B7%A5%E4%BD%9C%E7%9B%AE%E5%BD%95.png)
我已经通过 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>
答案2
您可以做到这一点的唯一方法是
使用 ioctl 将命令注入本地终端
TIOCSTI
。这在 OpenBSD 上不起作用,而在 Linux 上,您需要 capCAP_SYS_ADMIN
(即 root)才能在调用进程的控制 tty 之外的其他 tty 上使用它。您已经TIOCSTI
在此站点上找到了很多使用示例。ptrace(2)
通过(例如通过或其他调试器)操纵 ssh 客户端,gdb(1)
并将命令注入其加密通道。如何做到这一点很大程度上取决于 ssh 客户端内部结构(对于准备运行的示例,您需要一个使用调试符号编译的 ssh 客户端)。就像任何其他解决方案一样ptrace(2)
,它不适用于其他用户的进程(或者如果该进程使其自身不可转储),除非您有上限CAP_SYS_PTRACE
(即您是 root)。按照第 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
.