Unix/Java 進程移至後台時停止執行

Unix/Java 進程移至後台時停止執行

我們有一個使用 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

看來後台作業正在等待輸入被停止在大多數環境中。

來自有關 Unix 作業控制的維基百科頁面:

嘗試讀取或寫入其控制終端的後台程序會收到 SIGTTIN(用於輸入)或 SIGTTOU(用於輸出)訊號。這些訊號預設停止進程,但也可以透過其他方式處理。

並從一個Rutgers 關於 Unix 中級使用的頁面:

如果需要輸入,後台運行的作業將停止。無法將輸入提供給背景作業,因此請確保所有必要的輸入都可供其使用。

作為解決方案我們只是更新了 Java 進程以接受一個可選參數,該參數將導致主執行緒無限期地休眠,而不是等待輸入。我們有一個關閉鉤子可以SIGTERM/SIGINT適當地處理訊號:

        if (args.length >= 0 && StringUtils.equals(args[0], "daemon")) {
            while (true) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

相關內容