我有一系列 bash 命令,其中一些带有交互式提示,需要在远程计算机上运行。我必须针对不同的场景按一定的顺序调用它们,所以我一直在尝试制作一个 bash 脚本来为我自动化该过程。然而,似乎使用 bash 脚本启动 ssh session 的所有方法都会导致将 stdin 重定向到用于启动脚本的任何字符串或文件。第一名。
有没有一种方法可以指定在远程计算机上执行某个脚本,同时还可以通过 ssh
将 stdin
转发到本地计算机,以便用户能够与任何提示进行交互吗?
这是我必须澄清我想要做什么的要求列表。
- 在远程计算机上运行脚本。
- 在远程脚本中间的某个位置是提示输入的命令。示例:
git commit
将调出vim
。- 如果该命令是
git commit
并且它启动了vim
,则用户应该能够与vim
进行交互,就好像它正在运行一样在他们的本地机器上。 - 如果该命令提示输入
[y/n]
响应,用户应该能够输入他们的答案。
- 如果该命令是
- 用户输入必要的信息后(通过退出
vim
或在提示符下按回车键),脚本应继续像正常一样运行。 - 然后我的脚本将终止 ssh session 。最终产品是为用户执行命令,而他们不需要知道它是通过远程连接执行的。
我一直在使用我想在远程计算机上运行的以下脚本测试各种不同的方法。
#!/bin/bash
echo hello
vim
echo goodbye
exit
用户能够使用 vim
至关重要,然后,当用户完成后,“再见”应该打印到屏幕上,并且远程 session 应该终止。
我尝试将临时脚本上传到远程计算机,然后运行 ssh user@host bash/tmp/myScript
,但这似乎也接管了 stdin
完全无法让用户响应用户输入的提示。我尝试添加 -t
和 -T
选项(我不确定它们是否不同),但我仍然得到相同的结果。
一位评论者提到使用 expect
、spawn
和 interact
,但我不确定如何一起使用这些工具来获得我的期望的行为。看起来 interact
会导致用户获得对 stdin
的控制权,但是一旦用户退出 vim
就无法放弃它为了让我的脚本继续执行。
我想要的行为可能吗?
最佳答案
好的,我想我已经找到我的问题了。我正在为 ssh 创建一个包装脚本,如下所示:
#!/bin/bash
tempScript="/tmp/myScript"
remote=user@host
commands=$(</dev/stdin)
cat <(echo "$commands") | ssh $remote "cat > $tempScript && chmod +x $tempScript" &&
ssh -t $remote $tempScript
errorCode=$?
ssh $remote << RM
if [[ -f $tempScript ]]; then
rm $tmpScript
fi
RM
exit $errorCode
我在那里重定向了stdin
,而不是ssh
。当我提出问题时我应该提到这一点。我一遍又一遍地阅读该脚本,但我想我只是忽略了这一行。删除该行完全解决了我的问题。
只是为了澄清,将我的脚本更改为以下内容完全解决了我的问题。
#!/bin/bash
tempScript="/tmp/myScript"
remote=user@host
commands="$@"
cat <(echo "$commands") | ssh $remote "cat > $tempScript && chmod +x $tempScript" &&
ssh -t $remote $tempScript
errorCode=$?
ssh $remote << RM
if [[ -f $tempScript ]]; then
rm $tmpScript
fi
RM
exit $errorCode
一旦我更改了包装脚本,问题中描述的测试脚本就起作用了!我能够在屏幕上打印“hello”,vim
出现并且我能够像平常一样使用它,然后一旦我退出vim
“goodbye”就被打印出来并ssh
客户端已关闭。
这个问题的评论者一直在为我指明正确的方向。很抱歉我只讲述了部分故事。
关于bash - 如何使用脚本启动 ssh session 而不重定向 stdin?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37044129/