我们有一个使用 Appassembler 创建的 Java 进程。只要启动并在前台运行,它就可以正常运行:
[ec2-user@ip-xxx ourapp-0.0.1-SNAPSHOT]$ bin/ourapp
Starting in APP_HOME=/home/ec2-user/app_home
Press Q to quit
然后,我们可以成功访问和测试该应用程序。但是,如果我们在后台启动它,它不仅会停止运行,而且我们似乎无法在没有将其带到前台:
[ec2-user@ip-xxx ourapp-0.0.1-SNAPSHOT]$ bin/ourapp &
[1] 11661
Starting in APP_HOME=/home/ec2-user/app_home
Press Q to quit
## Not accessible!
[ec2-user@ip-xxx ourapp-0.0.1-SNAPSHOT]$ jobs
[1]+ Stopped bin/ourapp
[ec2-user@ip-xxx ourapp-0.0.1-SNAPSHOT]$ bg %1
[1]+ bin/ourapp & ## Still not accessible!
[ec2-user@ip-xxx ourapp-0.0.1-SNAPSHOT]$ jobs
[1]+ Stopped bin/ourapp
[ec2-user@ip-xxx ourapp-0.0.1-SNAPSHOT]$ fg %1
bin/ourapp ## Now, it's accessible.
我是不是启动不当?有没有办法让作业继续运行,即使它在后台?我需要将其作为守护进程启动,nohup
然后注销,但除非它仍然是前台进程,否则我似乎无法让它成功运行,但这是不可行的。
答案1
似乎正在等待输入的后台作业被停止在大多数环境中。
尝试读取或写入控制终端的后台进程将收到 SIGTTIN(用于输入)或 SIGTTOU(用于输出)信号。这些信号默认会停止进程,但也可以采用其他方式处理。
并且来自罗格斯大学关于 Unix 中级使用的页面:
如果需要输入,后台运行的作业将停止。无法为后台作业提供输入,因此请确保所有必要的输入都可供其使用。
解决方案我们只是更新了 Java 进程以接受一个可选参数,这将导致主线程无限期休眠,而不是等待输入。我们有一个关闭钩子可以SIGTERM/SIGINT
适当地处理信号:
if (args.length >= 0 && StringUtils.equals(args[0], "daemon")) {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}