【问题标题】:Running SSH from a background script从后台脚本运行 SSH
【发布时间】:2017-11-24 14:40:07
【问题描述】:

我在 Linux 上从一个调用脚本运行 SSH,该脚本在执行时被移到后台。

SSH命令在远程win 10服务器上执行批处理命令。
调用脚本中的语法为:chkval=$(SSH domain\remotehost cmd arg2 arg2)

只要我在前台运行脚本,这可以从命令行或调用脚本工作,但只要我将脚本置于后台或将其交给“at”以进行预定的 exec,SSH 命令失败并出现“更多令牌预期”错误。

脚本不会死,SSH 调用也不会死,但它永远不会执行远程命令。

【问题讨论】:

  • 您是否尝试过-t 选项,即使在非交互式会话中也能获取 tty?
  • 是的,SSH 进程只是挂起,从不执行远程命令。我可以做一个 ps -ef |grep ssh 看看。
  • 更重要的是,当我杀死调用进程时,它并没有杀死相关的ssh命令,我必须单独杀死它。
  • 是的,那是因为信号不是通过 SSH 协议传输的。只有标准输入、标准输出和标准错误。给本地客户端的信号可能会杀死客户端,但不会将信号中继到远程主机上的服务器进程,因此服务器会继续运行并且不会向其子进程发出任何信号。
  • 顺便说一下,感谢您的快速回复和建议。

标签: linux windows bash shell ssh


【解决方案1】:

你可以使用 -N -f 标志来做到这一点。 来自 man ssh

-f: 在命令执行之前请求 ssh 进入后台。如果 ssh 将要求输入密码或密码,但用户希望它在后台使用,这很有用。这意味着-n。在远程站点启动 X11 程序的推荐方法是使用 ssh -f host xterm 之类的方法。 如果 ExitOnForwardFailure 配置选项设置为“yes”,则以 -f 启动的客户端将等待所有远程端口转发成功建立,然后将其置于后台。

-N: 不要执行远程命令。这对于仅转发端口很有用(仅限协议版本 2)。

Y 留下一个示例脚本。您首先需要客户端/服务器身份验证是基于密钥的,因为您不需要输入用户/密码

#!/bin/bash
dst_machine_ip="192.168.0.100"
ssh  -Nf $dst_machine_ip

# Here goes your remote commands
ls
date
# Exit
ssh -O exit $dst_machine_ip

你可以直接在后台执行这个脚本

nohup ./script.sh &

【讨论】:

  • 感谢您的回复!我不想在 bg 中运行 ssh 命令本身,而是在调用进程中运行。脚本调用 ssh 命令并等待远程命令完成。然后清理并退出。如果我在 ssh 命令上使用 -f,它将进入后台并在远程进程完成之前将控制权返回给脚本,这是我不想要的。
  • 如果我在 fg 中运行调用脚本,一切都很好,但这不是一个可行的解决方案。很抱歉造成误解,我知道我说在 bg 中运行 SSH 是问题所在,但这并不完全准确。
  • 下面是调用SSH命令的脚本我把这个脚本叫做pmcmdx。我有另一个使用两个参数调用 pmcmdx 的脚本,我称该脚本为“metaljpr”。 metaljpr 由另一个主脚本控制,它是在运行时放入 bg 的脚本,我称之为 metal。因此,A Menu 调用并将 metal 发送到 bg,该 bg 运行 >metaljpr >pmcmdx
  • fl=$1 wf=$2 echo -e "\n在 date 调用" echo -e "\n尝试 SSH 连接到远程集成服务:[PWIS01_SDW_DEV]" jstat=$(ssh NJ\\ NJDSSINFADM@dc01nj2dwifdv02.nj.core.him pmcmds $fl $wf) let jstat=echo $jstat|sed -e 's/[^0-9]//g' if [ $jstat -eq 0 ];然后 echo -e "INFO: Workflow [${2}]: 执行成功。" else echo -e "ERROR: Workflow [${wf}]: 执行失败。" echo -e "断开远程集成服务" fi
  • 这是我正在运行的 ssh 命令code /usr/bin/ssh NJ\\NJDSSINFADM@dc01nj2dwifdv02.nj.core.him pmcmds DFD_ETIME wf_TEST