Как демонизировать Java-программу? - PullRequest
69 голосов
/ 11 февраля 2009

У меня есть Java-программа, которую я хотел бы демонизировать в системе Linux. Другими словами, я хочу запустить его в оболочке и продолжить работу после выхода из системы. Я также хочу иметь возможность аккуратно остановить программу.

Я нашел эту статью , которая использует комбинацию сценариев оболочки и Java-кода для решения этой задачи Это выглядит хорошо, но я бы хотел что-нибудь попроще, если это возможно.

Какой ваш предпочтительный способ демонизации Java-программы в системе Linux?

Ответы [ 11 ]

38 голосов
/ 11 февраля 2009

Apache Commons Daemon запустит вашу программу Java как демон Linux или службу WinNT.

32 голосов
/ 11 февраля 2009

Если вы не можете положиться на Java Service Wrapper процитировано в другом месте (например, если вы работаете в 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

Функция stop проверяет /var/run/$progname.pid, проверяет, является ли этот файл PID запущенного процесса, проверяет, является ли она виртуальной машиной Java (чтобы не уничтожать процесс, который просто повторно использовал PID). из мертвого экземпляра моего Java-демона), а затем убивает этот процесс.

При вызове метод main () запускается путем записи его PID в файл, определенный в System.getProperty ("pidfile").

Однако есть одно серьезное препятствие: в Java нет простого и стандартного способа получения PID процесса, в котором работает JVM.

Вот что я придумала:

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());
}
24 голосов
/ 11 февраля 2009

Я часто пишу сценарии или командные строки, которые по сути выглядят так, если я хочу:

  1. Запустить программу, неуязвимую для взломов
  2. Это полностью отсоединено от оболочки, которая его порождает, и
  3. Создает файл журнала из stderr и stdout, содержимое которого также отображается, но
  4. Позволяет мне прекратить просмотр журнала и выполнять другие действия, не прерывая процесс

Наслаждайтесь.

nohup java com.me.MyProgram </dev/null 2>&1 | tee logfile.log &
14 голосов
/ 11 февраля 2009

Я предпочитаю команду nohup . В сообщении блога говорится, что есть лучшие способы, но я не думаю, что они достаточно лучше.

5 голосов
/ 11 февраля 2009

Вы можете попробовать Java Service Wrapper , версия для сообщества бесплатна и соответствует вашим потребностям.

4 голосов
/ 16 мая 2012

Мой предпочтительный способ в Ubuntu - использовать утилиту libslack 'daemon'. Это то, что Дженкинс использует в Ubuntu (именно там у меня появилась идея). Я использовал его для своих серверных приложений на базе Jetty, и он хорошо работает.

Когда вы останавливаете процесс демона, он сигнализирует JVM о завершении работы. Вы можете выполнить код выключения / очистки на этом этапе, зарегистрировав перехват выключения с помощью Runtime.addShutdownHook ().

4 голосов
/ 11 февраля 2009

Это зависит. Если это всего лишь разовая вещь, я хочу ее демонизировать и затем вернуться домой, но обычно я жду результатов, я мог бы сделать:

nohup java com.me.MyProgram &

в командной строке. Чтобы убить это чисто, у вас есть много вариантов. У вас может быть прослушиватель SIGKILL, или прослушивание порта и завершение работы при установлении соединения, периодически проверяйте файл. Различия в подходах имеют разные недостатки. Если бы он использовался в работе, я бы подумал об этом и, вероятно, бросил бы скрипт в /etc/init.d, который его не поддерживал, и сделал бы более сложное завершение работы, например, то, что имеет tomcat.

2 голосов
/ 23 февраля 2016

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
  1. Создайте новый скрипт с именем , запустите в папке / service / vm / и добавьте следующие строки.
#!/bin/bash    
echo starting VM 
exec java -jar
/root/learning-/daemon-java/vm.jar

Примечание: замените Jar своим собственным файлом Jar. или любой файл класса Java.

  1. Перезагрузка системы

  2. svstat / service / vm должен быть запущен и работает!

  3. svc -d / service / vm должен отключить vm!
  4. svc -u / service / vm должен запустить vm сейчас!.
2 голосов
/ 11 февраля 2009

Этот вопрос касается демонизации произвольной программы (не относящейся к java), поэтому некоторые ответы могут относиться к вашему случаю:

0 голосов
/ 14 августа 2018
nohup java -jar {{your-jar.jar}} > /dev/null &

Это может помочь.

...