【问题标题】:How to figure out why ssh session does not exit sometimes?如何弄清楚为什么 ssh 会话有时不退出?
【发布时间】:2011-06-09 17:35:46
【问题描述】:

我有一个 C++ 应用程序,它使用 ssh 来建立与服务器的连接。我发现有时 ssh 会话在调用服务器的命令退出后很长时间仍然存在。查看 ssh 的 Centos4 手册页,我看到以下内容:

 The session terminates when the command or shell on the remote machine
 exits and all X11 and TCP/IP connections have been closed.  The exit
 status of the remote program is returned as the exit status of ssh.

我看到命令已经退出,所以我想不是所有的 X11 和 TCP/IP 连接都已关闭。我如何才能确定哪些 ssh 正在等待,以便我可以修复我的召唤命令的 C++ 应用程序,以清理留下的任何东西,使 ssh 保持打开状态。

我想知道为什么这种失败只在某些时候发生,而不是在每次调用时发生?它似乎发生在大约 50% 的时间里。我的 C++ 应用程序会留下什么来触发这个?

更多背景:服务器是一个守护进程,当启动时,它分叉并且父进程退出,让子进程继续运行。客户端召唤方式:

popen("ssh -n -o ConnectTimeout=300 user@host \"sererApp argsHere\""
      " 2>&1 < /dev/null", "r")

【问题讨论】:

    标签: c++ ssh tcp centos


    【解决方案1】:

    @sienkiew:如果你真的想通过ssh 执行命令或脚本并退出,看看libslack 包的daemontool。 (可以将命令从其标准流中分离出来的类似工具是screentmuxdetach。)

    要在命令行上检查通过ssh 执行的命令的标准输入、标准输出和标准错误,例如,您可以使用lsof

    # sample code to figure out why ssh session does not exit
    # sleep keeps its stdout open, so sshd only sees EOF after command completion
    ssh localhost 'sleep 10 &'        # blocks
    ssh localhost 'sleep 10 1>&- &'   # does not block
    
    ssh localhost 'sleep 10 & lsof -p ${!}'
    ssh localhost 'sleep 10 1>&- & lsof -p ${!}'
    ssh localhost 'sleep 10 1>/dev/null & lsof -p ${!}'
    ssh localhost 'sleep 10 1>/dev/null 2>&1 & lsof -p ${!}'
    

    【讨论】:

      【解决方案2】:

      使用libsshlibssh2,而不是仅从C 调用popen(3) 来调用本身是另一个C 程序的ssh(1)。如果你想要我的个人经验,我会说试试libssh2 - 我已经在 C++ 程序中使用过它,它可以工作。

      【讨论】:

      • 现在,我已经在 fork() 的子进程退出之前完成了 fclose(stderr),现在 ssh 不再被困。
      【解决方案3】:

      我在这里找到了一些提示:

      http://www.snailbook.com/faq/background-jobs.auto.html

      这个问题通常是由 OpenSSH 服务器的一个特性引起的。在编写 SSH 服务器时,您必须回答“服务器何时应关闭 SSH 连接?”这个问题。显而易见的答案似乎是:当客户端请求(shell 或远程命令)启动的服务器端用户程序退出时关闭它。然而,它实际上有点复杂。这种简单的策略允许出现可能导致数据丢失的竞争条件(请参阅下面的说明)。 为避免此问题,sshd 改为等待,直到在连接到用户程序的 stdout 和 stderr 的管道上遇到文件结束 (eof)。

      【讨论】:

      • 这是我系统上发生的事情。手册页不正确 - 进程退出时它不会退出,您可以使用“ssh host 'sleep 20 &'”进行测试。当然,问题是当您的脚本没有做那么明显的事情时,可能会留下一个进程(即使在后台)。我还没有找到解决该案例的方法。
      猜你喜欢
      • 1970-01-01
      • 2015-06-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-11
      • 1970-01-01
      相关资源
      最近更新 更多