java - 使用 shell 脚本启动远程 (SSH) Java 应用程序不会返回本地提示
问题描述
我见过类似的问题,所有已解决的问题都已解决/不适用。
我在远程机器上有一个启动 Java 应用程序的 bash 脚本。相关行将是:
#!/usr/bin/env bash
...
java -cp /full/path/to/my.jar com.whatever.hi.wassup.MainClassThing \
--arg-1 /full/path/to/relevant_dir --arg-2 /full/path/to/another_dir &
...
echo started my app
exit 0
我用小脚本做了一堆测试,没有任何问题。我使用相同的方法来启动另一个 Java 应用程序,但没有问题(--daemon
如果重要,它是一个带有参数的服务器应用程序)。
在本地机器上,我尝试在本地 bash 脚本中调用远程脚本,如下所示:
#!/usr/bin/env bash
...
ssh remote_host myRemoteScript
我的所有测试和其他 Java 应用程序都返回本地提示。问题是,这个确实启动了远程 Java 应用程序并一直到最后一行,输出“启动我的应用程序”但脚本停在那里,除非我没有本地提示Ctrl+C
。
在工作的Java应用程序上使用ssh -v
我得到这个:
debug1: channel 0: free: client-session, nchannels 1
Transferred: sent 2992, received 7060 bytes, in 24.4 seconds
Bytes per second: sent 122.6, received 289.2
debug1: Exit status 0
然而,在非工作应用程序上,我得到了这个:
debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
debug1: client_input_channel_req: channel 0 rtype eow@openssh.com reply 0
"started my app"
但没有本地提示。我尝试使用nohup
and运行相同的命令disown
,结果相同。正如所见,命令&
在最后。仅在远程脚本中注释掉该行没有问题(并且没有任何用处),所以我认为这与 Java 应用程序本身有关——但进程控制不是由 shell 控制的吗?在远程机器上运行 myRemoteScript 也可以正常工作。
这是一个无密码登录。两台机器都是 RHEL 7.2。
编辑
也试过:
ssh remote_host "myRemoteScript"
ssh -T remote_host myRemoteScript
ssh remote_host "bash -c myRemoteScript"
ssh remote_host "myRemoteScript; exit"
解决方案
您可以重定向 java 进程的标准输入、输出和错误,使其标准输入、输出和错误不连接到远程 SSH 服务器:
java ... < /dev/null > /dev/null 2>&1 &
这应该允许远程服务器立即终止 SSH 会话。
当您要求远程 SSH 服务器调用命令,而您没有为该命令请求 TTY 时,服务器将为子进程的标准输入、输出和错误创建一组管道。OpenSSH 服务器的当前行为似乎不是在远程命令退出时关闭会话。相反,当服务器在处理来自远程进程的标准输出的管道上检测到文件结束条件时,它会关闭会话。
您的远程命令启动的 java 进程正在继承 SSH 服务器的管道作为其标准输入等。SSH 服务器没有在这些管道上获得 EOF 指示,因为仍有一个进程可以访问管道。
您可以通过运行如下命令来测试它:
ssh localhost 'sleep 10 < /dev/null > /dev/null &'
如果 ssh 没有等待sleep
完成就立即退出,这意味着您已经让远程 SSH 服务器不等待睡眠。
我自己的测试表明 SSH 服务器正在查看从子进程接收标准输出的管道,所以这就是您必须重定向的全部内容。但是您应该考虑重定向所有三个管道——标准输入、输出和错误——以防 SSH 服务器的行为在未来发生变化。
推荐阅读
- java - 如何使 jTable 数据依赖于 Java GUI 中的组合框?
- xml - SonarLint 不显示来自本地 SonarQube 服务器的自定义规则
- c# - 如何使用 c# 将 JSON 反序列化为派生类
- r - ggplot2:添加辅助 x 标签(年份低于月份)
- outlook - 如何在 Outlook 的已删除邮件文件夹中创建 EWS 项目(日历事件或联系人)?
- android - WebView 在显示 about:blank 后不加载 html 文件
- java - 从 api 获取数据适用于 https api,但不适用于 http api
- node.js - 如何让我的前端应用程序访问我的节点服务器 API
- bash - awk:处理 if 语句中的变量
- vim - vimscript 获取要执行的命令