如何在不重定向标准输入的情况下使用脚本启动ssh会话?

时间:2016-05-05 06:43:59

标签: bash unix vim ssh expect

我有一系列bash命令,其中一些带有交互式提示,我需要在远程计算机上运行。我必须按照特定顺序调用它们以用于不同的场景,所以我一直在尝试制作一个bash脚本来为我自动化该过程。但是,似乎使用bash脚本启动ssh会话的每种方式都会导致stdin重定向到首先用于启动脚本的任何字符串或文件。

有没有办法可以指定在远程计算机上执行某个脚本,还可以将stdin通过ssh转发到本地计算机以使用户能够与任何提示交互?< / p>

以下列出了我要澄清我要做的事情的要求。

  1. 在远程计算机上运行脚本。
  2. 该远程脚本中间的某个位置是提示输入的命令。示例:git commit会显示vim
    • 如果该命令为git commit并且显示vim,则该用户应该能够与vim进行交互,就像它在本地计算机上运行一样。
    • 如果该命令提示[y/n]响应,则用户应该能够输入他们的答案。
  3. 用户输入必要信息后 - 退出vim或按提示返回 - 脚本应继续正常运行。
  4. 我的脚本将终止ssh会话。最终产品是为用户执行命令而不需要知道它是通过远程连接。
  5. 我一直在测试各种不同的方法,我想在远程机器上运行以下脚本。

    #!/bin/bash
    echo hello
    vim
    echo goodbye
    exit
    

    用户能够使用vim至关重要,然后,当用户完成时,应该将“再见”打印到屏幕上并终止远程会话。

    我已尝试将临时脚本上传到远程计算机,然后运行ssh user@host bash /tmp/myScript,但这似乎也完全接管了stdin,导致无法让用户响应用户的提示输入。我尝试添加-t-T选项(我不确定它们是否不同),但我仍然得到相同的结果。

    一位评论者提到使用expectspawninteract,但我不确定如何将这些工具结合使用以获得我想要的行为。似乎interact会导致用户获得对stdin的控制权,但是一旦用户退出vim以便让我的脚本继续执行,就无法放弃它。< / p>

    我想要的行为甚至可能吗?

2 个答案:

答案 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