使用命名管道在 BASH 中控制远程 ssh 会话

使用命名管道在 BASH 中控制远程 ssh 会话

我的问题主要基于此 https://stackoverflow.com/questions/22479631/pipe-timely-commands-to-ssh?rq=1

我正在关注上述问题,并且能够连接到服务器,如下所示:

mkfifo CMDs.txt
exec 7> CMDs.txt

然后从另一个终端我连接到服务器,如下所示:

sshpass -p 'mypass' ssh -tt myuser@${IP} < CMDs.txt 

会话已建立,但不是交互式会话(应该是)。但我能够通过将命令重定向到文件描述符 7 来将命令发送到远程服务器,例如:

echo "some command" >&7 
echo "some more command" >&7 

这工作正常,并在我启动会话的另一个终端中显示输出。我的目标是发送命令,并在变量中捕获每个命令的输出,以便在发送另一个命令之前对其进行分析。我认为通过读取 stdout 应该可以做到这一点,但我无法弄清楚,因此发布了这个问题。我可以通过将其重定向到文件中来捕获文件中的输出,如下所示:

sshpass -p 'mypass' ssh -tt myuser@${IP} < CMDs.txt >>outfile.txt

另外,正如参考问题中提到的,exec 7>&-应该终止会话,但是没有,那么在我发送所有命令后如何终止会话?

答案1

这是一个很有趣(而且非常有用!)的练习。在输入/输出重定向领域,灵活性很高,因此有多种选择,但以下是对我有用的方法。

首先,真正地使用ssh-keygen来创建私钥/公钥对,并在远程服务器文件上安装公钥authorized_keys(这很简单,可以增强安全性,网上有很多指南可以做到这一点)。为了获得额外的奖励,请用密码保护它,然后使用ssh-agent & ssh-add——实际上每次启动时只需运行ssh-agent & ssh-add一次,之后一切就绪了。

无论如何,我像您一样使用 7 个文件描述符,并根据 7 设置我的 FIFO 名称,这样我就可以轻松记住我需要重定向到哪个 FD。;)

fd=7
server=[whatever_your_server_name_is]
mkfifo $server.$fd.in $server.$fd.out

# ssh-agent if needed
ssh -tt $server <$server.$fd.in >$server.$fd.out &
exec 7>$server.$fd.in

现在舞台已经准备好了。我可以将一些脚本/进程附加到$server.$fd.out,但在以下示例中,我仅将 cat 作为侦听器启动——为了更好的可读性,我在单独的 ssh 会话中启动了它,但如果使用“&”将其置于后台,则这并不是绝对必要的:

cat $server.$fd.out

然后,无论你想要什么任意命令:

echo "hostname" >&7
echo "date" >&7
echo -e '\003' >&7  # ctrl+c...you're welcome ;)

您将看到输出。请注意,首先,您将获得初始登录 motd/banner/等,因此,无论您将什么脚本/应用程序附加到输出 FIFO,都需要能够处理它。

值得注意的是,单个 FIFO 很可能可以用于读取和写入,但是 x.input/output 更适合我的个人目的,所以我在这里展示的就是这样的。

仅供参考:非常感谢您“带我到那里”。我一直在尝试弄清楚如何拥有一个“快速”的 ssh RPC,在其中我建立一个长时间运行的 ssh 会话,然后可以稍后运行任意命令,而无需在每个命令上进行 ssh 身份验证的开销——我总是将尽可能多的命令串在一起以减少开销(甚至发送小脚本来读取输出并发出适当的后续命令),但底线是,当想要发出快速命令时,ssh 连接和身份验证总是需要几秒钟的开销(当然是使用密钥 ;) ),而当想要快速从多个设备获取某些东西时,这些秒数可能会很痛苦。一些基本的逻辑来处理 ssh 或主机出去吃午饭,并自动重新建立,我有一个相当不错的设置来管理我的基础设施。

你的问题中的见解实际上填补了缺失的空白需要构建我需要的东西。希望这个答案也能帮到你!:)

相关内容