我有一系列bash命令,其中一些带有交互式提示,我需要在远程计算机上运行。我必须按照特定顺序调用它们以用于不同的场景,所以我一直在尝试制作一个bash脚本来为我自动化该过程。但是,似乎使用bash脚本启动ssh
会话的每种方式都会导致stdin
重定向到首先用于启动脚本的任何字符串或文件。
有没有办法可以指定在远程计算机上执行某个脚本,还可以将stdin
通过ssh
转发到本地计算机以使用户能够与任何提示交互?< / p>
以下列出了我要澄清我要做的事情的要求。
git commit
会显示vim
。
git commit
并且显示vim
,则该用户应该能够与vim
进行交互,就像它在本地计算机上运行一样。[y/n]
响应,则用户应该能够输入他们的答案。vim
或按提示返回 - 脚本应继续正常运行。我一直在测试各种不同的方法,我想在远程机器上运行以下脚本。
#!/bin/bash
echo hello
vim
echo goodbye
exit
用户能够使用vim
至关重要,然后,当用户完成时,应该将“再见”打印到屏幕上并终止远程会话。
我已尝试将临时脚本上传到远程计算机,然后运行ssh user@host bash /tmp/myScript
,但这似乎也完全接管了stdin
,导致无法让用户响应用户的提示输入。我尝试添加-t
和-T
选项(我不确定它们是否不同),但我仍然得到相同的结果。
一位评论者提到使用expect
,spawn
和interact
,但我不确定如何将这些工具结合使用以获得我想要的行为。似乎interact
会导致用户获得对stdin
的控制权,但是一旦用户退出vim
以便让我的脚本继续执行,就无法放弃它。< / p>
我想要的行为甚至可能吗?
答案 0 :(得分:2)
好的,我想我发现了我的问题。我正在为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
一旦我更改了包装脚本,问题中描述的测试脚本就可以了!我能够打印&#34;你好&#34;在屏幕上,vim
出现了,我能够像平常一样使用它,然后一旦我退出vim
&#34;再见&#34;已打印,ssh
客户已关闭。
这个问题的评论者一直指着我正确的方向。对不起我只告诉了我的部分故事。
答案 1 :(得分:0)
过去,我已经多次寻求解决此问题的方法,但是从未找到完全令人满意的方法。用ssh管道传输会失去交互性。两个连接(scp / ssh)速度较慢,并且可能会留下您的临时文件。而且,命令行上的整个脚本通常以逃脱地狱而告终。
最近,我遇到命令行缓冲区大小通常很大的情况(在我看来,{getconf ARG_MAX
> 2MB)。这让我开始思考如何使用它并缓解转义问题。
结果是:
ssh -t <host> /bin/bash "<(echo "$(cat my_script | base64 | tr -d "\n")" | base64 --decode)" <arg1> ...
或使用此处文档和cat
:
ssh -t <host> /bin/bash $'<(cat<<_ | base64 --decode\n'$(cat my_script | base64)$'\n_\n)' <arg1> ...
我已经扩展了这个想法,以产生一个可以正常运行的BASH示例脚本sshx
,该脚本可以运行任意脚本(不仅仅是BASH),其中参数也可以通过ssh成为本地输入文件。参见here。