2009-02-10 113 views
67

我有一個Java程序,我想在Linux系統上守護進程。換句話說,我想開始在shell中運行它,並在退出後繼續運行它。我也希望能夠乾淨地停止程序。如何守護Java程序?

我發現this article它使用shell腳本和Java代碼的組合來完成這個技巧。它看起來不錯,但如果可能的話,我希望更簡單一些。

在Linux系統上守護Java程序的首選方法是什麼?

+0

請參閱http://stackoverflow.com/questions/407016/how-to-convert-an-existing-java-application-to-a-sys-v-service-daemon – 2009-02-10 23:15:44

+6

嘗試`nohup java prog&` 。 – ceving 2012-07-09 14:47:21

+0

在UNIX上管理服務的更簡潔的方法https://cr.yp.to/daemontools.html – Velu 2016-02-23 04:47:40

回答

5

你可以試試Java Service Wrapper,社區版是免費的,可以滿足你的需求。

+1

你怎麼知道它滿足他的需求? Java Service Wrapper根據其許可證不能免費用於商業用途:http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html – Jared 2014-05-21 14:31:57

14

我更喜歡nohup命令。博客文章說有更好的方法,但我認爲它們不夠好。

+0

它不完全是守護進程。如果操作系統重新啓動,該怎麼辦?。這裏是清潔解決方案與守護進程http://stackoverflow.com/a/35569052/1840774 – Velu 2016-04-15 02:16:48

+1

這將不會提供服務,一旦系統出現故障或重新啓動! – Velu 2016-04-15 02:17:36

3

這取決於。如果它只是一個一次性的事情,我想守護進程,然後回家,但通常我等待結果,我可能會做:

nohup java com.me.MyProgram & 

在命令行。要乾淨地殺死它,你有很多選擇。您可能擁有SIGKILL的偵聽器,或者在端口上偵聽並在建立連接時關閉,並定期檢查文件。差異方法有不同的弱點。如果它用於生產中,我會考慮更多,並且可能會在/etc/init.d中引入一個腳本,使腳本不被竊取,並且具有更復雜的關閉,比如tomcat的功能。

23

我經常發現自己寫腳本或命令行基本上是這樣的,如果我想:

  1. 運行一個程序,它是免疫sighups
  2. 這是其殼產卵完全斷開它和
  3. 可生產從標準錯誤日誌文件和標準輸出,其中顯示以及內容,但
  4. 讓我停止觀看日誌中的進度和做其他的東西而不會中斷正在運行的進程

享受。

nohup java com.me.MyProgram </dev/null 2>&1 | tee logfile.log &
30

如果你不能依靠Java Service Wrapperelsewhere(例如,如果你在Ubuntu,其中有SW的無包裝的版本上運行),你可能想這樣做的老式方法:讓你的程序把它的PID寫在/var/run/$progname.pid中,然後在它周圍寫一個標準的SysV初始化腳本(例如用於ntpd的例子,這很簡單)。優選地,也使其符合LSB。

本質上,啓動函數測試程序是否已在運行(通過測試/var/run/$progname.pid是否存在,並且該文件的內容是正在運行的進程的PID),如果未運行

logfile=/var/log/$progname.log 
pidfile=/var/run/$progname.pid 
nohup java -Dpidfile=$pidfile $jopts $mainClass </dev/null > $logfile 2>&1 

上/var/run/$progname.pid停止功能檢查,測試,如果該文件是一個正在運行的進程的PID,驗證它是一個Java虛擬機(以便不殺一個過程,只需從Java守護進程的死實例中重用PID),然後殺死該進程。

當被調用時,我的main()方法將通過在System.getProperty(「pidfile」)中定義的文件中寫入其PID來啓動。

的一個主要障礙,雖然:在Java中,沒有簡單和標準的方式來獲得JVM上運行的進程的PID

以下是我想出了:

private static String getPid() { 
    File proc_self = new File("/proc/self"); 
    if(proc_self.exists()) try { 
     return proc_self.getCanonicalFile().getName(); 
    } 
    catch(Exception e) { 
     /// Continue on fall-back 
    } 
    File bash = new File("/bin/bash"); 
    if(bash.exists()) { 
     ProcessBuilder pb = new ProcessBuilder("/bin/bash","-c","echo $PPID"); 
     try { 
      Process p = pb.start(); 
      BufferedReader rd = new BufferedReader(new InputStreamReader(p.getInputStream())); 
      return rd.readLine(); 
     } 
     catch(IOException e) { 
      return String.valueOf(Thread.currentThread().getId()); 
     } 
    } 
    // This is a cop-out to return something when we don't have BASH 
    return String.valueOf(Thread.currentThread().getId()); 
} 
2

This問題是關於daemonizing任意程序(不針對Java)這樣一些問題的答案可能適用於您的情況:

4

我在Ubuntu上的首選方式是使用libslack'守護進程'實用程序。這就是Jenkins在Ubuntu上使用的(這是我的想法)。我已經將它用於基於Jetty的服務器應用程序,並且它運行良好。

當你停止守護進程時,它會發出關閉JVM的信號。您可以通過使用Runtime.addShutdownHook()註冊一個關閉鉤子來執行關閉/清除代碼。

2

的Daemontools: - 在UNIX https://cr.yp.to/daemontools.html管理服務

  1. 從URL https://cr.yp.to/daemontools/install.html 跟隨指令提到的還有,對於任何問題,請嘗試說明https://gist.github.com/rizkyabdilah/8516303

  2. 安裝守護程序工具,更清潔的方式創建一個文件在/etc/init/svscan.conf並添加下面的行(只需要cent-os-6.7)

start on runlevel [12345] 
stop on runlevel [^12345] 
respawn 
exec /command/svscanboot 
  • 創建名爲運行內部/服務/ VM /文件夾的新腳本,並添加以下行。
  • #!/bin/bash  
    echo starting VM 
    exec java -jar 
    /root/learning-/daemon-java/vm.jar 
    

    注: 用自己的Jar文件替換JAR。或任何Java類文件。

  • 重新引導系統

  • svstat /服務/ VM應達和現在正在運行!。

  • svc -d/service/vm應該讓vm下來吧!
  • svc -u/service/vm現在應該啓動虛擬機了!