用于处理 SSH 连接断开/终止的 Linux 陷阱信号

not*_*ain 6 linux ssh bash

我在 npm 脚本中有一个命令,它通过 SSH 连接到远程构建服务器并运行 Bash 脚本。该脚本设置一个锁文件,并trap在脚本退出时调用以删除该锁文件。

在这两种情况下,我都用ctrl+取消操作C

LOCKFILEPATH="/tmp/env_app.lock"
# cleanup function just deletes $LOCKFILEPATH
function mutex() {
  if [ -f "$LOCKFILEPATH" ]; then
    echo -e "\n\n${redtext}Build already in progress! Exiting.${resettext}\n\n";
    exit 1;
  else
    touch $LOCKFILEPATH;
    trap cleanup EXIT;
  fi
}
Run Code Online (Sandbox Code Playgroud)

当您第一次通过 SSH 进入主机以运行它时,这可以正常工作,但是当您通过 SSH 发送命令时,陷阱不起作用

ssh hostname command
Run Code Online (Sandbox Code Playgroud)

我尝试添加到 trap 命令以运行更多信号,但这些似乎也不起作用:

 trap cleanup EXIT SIGHUP SIGKILL SIGTERM SIGINT
Run Code Online (Sandbox Code Playgroud)

我应该在这里做什么?

我还设置了一个更简单的脚本,当通过 SSH 手动执行它时,它似乎工作正常。也许当我使用 npm 脚本运行它时添加了层?npm 脚本是:

"deploy": "ssh HOSTNAME ''deploy-script $(git rev-parse --abbrev-ref HEAD) stage $npm_package_config_deploy_target yes''",
Run Code Online (Sandbox Code Playgroud)

它只检查当前分支名称并使用它在构建主机上进行部署。与...一样

"deploy": "ssh HOSTNAME ''deploy-script CURRENTBRANCH stage APPNAME''",
Run Code Online (Sandbox Code Playgroud)

更新:向-tnpm 脚本添加 force tty似乎已修复它。令人困惑,因为对于简单的脚本案例我不需要它。也许我在大脚本中生成了太多子进程(太多了,无法在没有编辑的情况下粘贴在这里)所以它需要一个 tty 来触发清理陷阱。

"deploy": "ssh -t HOSTNAME ''deploy-script CURRENTBRANCH stage APPNAME''",
Run Code Online (Sandbox Code Playgroud)

Kam*_*ski 3

当你这样做时

\n\n
ssh hostname command\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后Ctrl+ C,您终止本地ssh. command仍然在远程端运行,它永远不会收到您的击键。这与 不同-t。看这个答案以获取解释。相关片段:

\n\n
\n

在客户端,ssh将尝试将 stdin 使用的 tty 设置为“原始”模式,并且sshd在远程主机上将分配一个伪 tty [\xe2\x80\xa6] 如果您输入Ctrl+ C,它将被发送到远程主机,命令可能会收到SIGINT[\xe2\x80\xa6]。然后遥控器sshd关闭连接,并ssh报告Connection to remotehost closed

\n
\n\n

因此使用:

\n\n
ssh -t hostname command\n
Run Code Online (Sandbox Code Playgroud)\n\n

当您按+时,您的command(不是本地的ssh)将会得到SIGINTCtrlC

\n\n
\n\n

这可能会变得更有趣。比较ssh + 这里文档 \xe2\x80\x93 Ctrl+C 是否到达远程端?

\n