Как демонировать программу Java?

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

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

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

Ответ 1

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

Ответ 2

Если вы не можете положиться на Java Service Wrapper, ссылка в другом месте ( например, если вы работаете на Ubuntu, у которого нет пакетной версии SW), вы, вероятно, захотите сделать это старомодно: попросите свою программу записать свой PID в /var/run/ $progname.pid и напишите стандартный SysV init script (используйте, например, пример для ntpd, это просто) вокруг него. Желательно также сделать его совместимым с LSB.

По сути, функция start проверяет, запущена ли программа (путем тестирования, существует ли /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 (чтобы не убивать процесс, который просто повторно использовал 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());
}

Ответ 3

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

  • Запустите программу, которая невосприимчива к sighups
  • Это полностью отключено от оболочки, которая его порождает, и
  • Производит файл журнала из stderr и stdout, содержимое которых также отображается, но
  • Позволяет мне остановить просмотр журнала и выполнить другие действия, не нарушая выполняемый процесс.

Enjoy.

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

Ответ 4

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

Ответ 5

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

Ответ 6

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

nohup java com.me.MyProgram &

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

Ответ 7

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

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

Ответ 9

DaemonTools: - более чистый способ управления службами в UNIX https://cr.yp.to/daemontools.html

  • Установить инструменты демона из URL https://cr.yp.to/daemontools/install.html следуйте инструкциям, указанным там, по любым вопросам, пожалуйста, попробуйте инструкции https://gist.github.com/rizkyabdilah/8516303

  • Создайте файл с /etc/init/svscan.conf и добавьте следующие строки. (требуется только для cent-os-6.7)

 start on runlevel [12345]
 stop on runlevel [^12345]
 respawn
 exec /command/svscanboot
  1. Создайте новую script с именем запустите внутреннюю/служебную/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 сейчас!

Ответ 10

Если вам нравятся новые вещи, вы можете попробовать Akuma. Для (немного) информации см. Также Блог Kohsuke Kawaguchi.

Ответ 11

Взгляните сюда:

http://jnicookbook.owsiak.org/recipe-no-022/

для примера кода, основанного на JNI. В этом случае вы демонизируете код, который был запущен как Java, а основной цикл выполняется в C. Но также можно поместить основной цикл daemon в Java.

https://github.com/mkowsiak/jnicookbook/tree/master/recipeNo029

Получайте удовольствие от JNI!

Ответ 12

nohup java -jar {{your-jar.jar}} > /dev/null &

Это может сделать трюк.