使用Shell脚本启动远程(SSH)Java应用程序不会返回本地提示

时间:2018-06-27 15:09:35

标签: java bash ssh

我见过类似的问题,所有解决的问题都已经解决/不适用。

我在启动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"

但是没有本地提示。我尝试对nohupdisown运行相同的命令,结果相同。如图所示,该命令的末尾有&。仅注释掉远程脚本中的那行是没有问题的(并且没有任何用处),因此我认为这与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"

1 个答案:

答案 0 :(得分:2)

您可以重定向Java进程的标准输入,输出和错误,以便其标准输入,输出和错误不会连接到远程SSH服务器:

java ... < /dev/null > /dev/null 2>&1 &

这应该允许远程服务器立即终止SSH会话。

当您要求远程SSH服务器调用命令,而您不要求该命令的TTY时,服务器将为子进程的标准输入,输出和错误创建一组管道。当退出远程命令时,OpenSSH服务器的当前行为似乎不是关闭会话。相反,服务器在检测到远程处理的标准输出管道上的文件结束条件时关闭会话。

您的远程命令启动的Java进程正在将管道继承到SSH服务器作为其标准输入等。SSH服务器在这些管道上没有得到EOF指示,因为仍然有一个可以访问管道的进程。 / p>

您可以通过运行类似以下的命令来对此进行测试:

ssh localhost 'sleep 10 < /dev/null > /dev/null &'

如果ssh立即退出而没有等待sleep完成,则意味着您已使远程SSH服务器不等待睡眠。

我自己的测试建议SSH服务器正在查看从子进程接收标准输出的管道,因此您只需重定向即可。但是,您应该考虑重定向所有三个管道(标准输入,输出和错误),以防SSH服务器的行为将来发生变化。