引用命令中的反引号评估问题,在 su -c 中,在 Heredoc 中,馈入 2 层 ssh

引用命令中的反引号评估问题,在 su -c 中,在 Heredoc 中,馈入 2 层 ssh

我有以下间接链:

ssh -t root@host1 ssh host2 << EOF\nsu - user2 -c 'kill `cat ~/file_with_pid`'\nEOF

最后我需要的只是以 user2 的身份终止主机 2 上的一个进程(从文件中读取 pid)。除了单引号之间的部分外,我不能改变太多

'kill `cat ~/file_with_pid`'

因此我不能简单地

ssh user2@host2 'kill `cat ~/file_with_pid`'

我的问题是~文件路径中的 home 被扩展到错误的 home。这可能与反引号的求值时间有关(由于命令链很长,我不太确定这种情况何时发生)。

如何更改单引号中的部分以获得我想要的内容?

(注意:我无法对 home 进行硬编码,因为我可能会host2以 user 的身份在任意位置执行此操作user2,因此我希望user2每次都能确定 'home )。

答案1

-J正如 @pLumo 所建议的,您可以通过使用ssh 的 (“JumpHost”) 选项来摆脱一些引用地狱:

ssh -J root@host1 root@host2 "su user2 -c 'kill \"\$(cat ~/file_with_pid)\"'"

或者,使用此处文档:

ssh -J root@host1 -T root@host2 <<'EOT'
su user2 -c 'kill "$(cat ~/file_with_pid)"'
EOT

注意<<'EOT'代替<<EOT;引用结束标记可以防止变量、反引号等在此处文档中展开。

一般情况下,它-T会阻止 ssh 分配伪 tty,在这种情况下,它将阻止 ssh 警告您它尚未分配伪终端。如果出于某种原因你确实需要一个伪终端,请使用两个-t选项来强制 ssh 分配一个,即使当地的stdin 不是 tty。并exit在此处文档中添加一个:

ssh -J root@host1 -tt root@host2 <<'EOT'
su user2 -c 'kill "$(cat ~/file_with_pid)"'
exit
EOT

如果您需要连接到另一个端口而不是跳转主机上的 22,您应该使用以下-J user@host1:port形式;该-p选项适用于host2

ssh -J root@host1:port1 -p port2 root@host2 "su user2 -c 'kill \"\$(cat ~/file_with_pid)\"'"

我不知道有任何快捷方式选项可以让您为跳转主机使用不同的身份(如-i);看来您必须为此使用配置文件。


在您的示例中,EOF\nsu未加引号的只是EOFnsu, not EOF<newline>su(即使是,这也不起作用)。

但是重定向标准输入ssh(如此处<<文档所做的那样)将阻止第二台主机上的任何交互式身份验证,因此即使这样也无法修复您的示例。

相关内容