web-dev-qa-db-fra.com

Comment démoniser un programme Java?

J'ai un programme Java que je voudrais démoniser sur un système Linux. En d'autres termes, je veux commencer à l'exécuter dans un shell et le poursuivre après ma déconnexion. Je veux aussi pouvoir arrêter le programme proprement.

J'ai trouvé cet article qui utilise une combinaison de scripts Shell et de code Java pour faire l'affaire. Cela a l'air bien, mais j'aimerais quelque chose de plus simple, si possible.

Quelle est votre méthode préférée pour démoniser un programme Java sur un système Linux?

69
Rich Apodaca

Apache Commons Daemon exécutera votre programme Java en tant que démon Linux ou service WinNT.

37
Bahaa Zaid

Si vous ne pouvez pas compter sur Java Service Wrapper cité ailleurs (par exemple, si vous utilisez Ubuntu, qui ne possède pas de version logicielle de SW), vous voudrez probablement le faire à l'ancienne: Demandez à votre programme d'écrire son PID dans /var/run/$progname.pid et écrivez un script d'initialisation SysV standard (utilisez par exemple celui de ntpd comme exemple, c'est simple). De préférence, rendez-le compatible LSB également.

Essentiellement, la fonction de démarrage teste si le programme est déjà en cours d'exécution (en vérifiant si /var/run/$progname.pid existe et si le contenu de ce fichier est le PID d'un processus en cours d'exécution), et s'il n'est pas exécuté

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

La fonction stop vérifie sur /var/run/$progname.pid, vérifie si ce fichier est le PID d'un processus en cours d'exécution, vérifie qu'il s'agit d'un fichier Java VM (afin de ne pas interrompre un processus ayant simplement réutilisé le fichier). PID d’une instance morte de mon démon Java) puis tue ce processus. 

Quand elle est appelée, ma méthode main () commence par écrire son PID dans le fichier défini dans System.getProperty ("pidfile").

Un obstacle majeur cependant: en Java, il n’existe aucun moyen simple et standard d’obtenir le PID du processus dans lequel la JVM est exécutée.

Voici ce que je suis venu avec:

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());
}
32
Varkhan

Je me trouve souvent en train d'écrire des scripts ou des lignes de commande qui ressemblent essentiellement à ceci, si je veux:

  1. Exécuter un programme qui est immunisé contre les sighups 
  2. C'est complètement déconnecté de la coquille qui l'engendre, et 
  3. Produit un fichier journal à partir de stderr et stdout dont le contenu est également affiché, mais
  4. Me permet d’arrêter de consulter le journal en cours et d’effectuer d’autres tâches sans interrompre le processus en cours.

Prendre plaisir.

Nohup Java com.me.MyProgram </dev/null 2>&1 | tee logfile.log &
23
Ben Hardy

Je préfère le Nohup commande. Le billet de blog dit qu'il existe de meilleures méthodes, mais je ne pense pas qu'elles soient suffisamment meilleures.

14
S.Lott

Vous pouvez essayer Java Service Wrapper , l'édition de la communauté est gratuite et répond à vos besoins.

5
John T

Mon moyen préféré sur Ubuntu est d'utiliser l'utilitaire 'daemon' de libslack. C'est ce que Jenkins utilise sur Ubuntu (c'est là que j'ai eu l'idée.) Je l'ai utilisé pour mes applications serveur basées sur Jetty et cela fonctionne bien.

Lorsque vous arrêtez le processus démon, il indique à la JVM de s’arrêter. Vous pouvez exécuter le code d'arrêt/nettoyage à ce stade en enregistrant un hook d'arrêt avec Runtime.addShutdownHook ().

4
colini

Ça dépend. Si c'est juste une fois, je veux le démoniser et ensuite rentrer chez moi, mais d'habitude j'attends les résultats, je pourrais faire:

Nohup Java com.me.MyProgram &

à la ligne de commande. Pour le tuer proprement, vous avez beaucoup d'options. Vous pouvez avoir un écouteur pour SIGKILL, ou écouter sur un port et arrêter quand une connexion est établie, vérifier périodiquement un fichier. Les approches différentielles ont des faiblesses différentes. Si c'est pour une utilisation en production, j'y réfléchirais davantage et jetterais probablement un script dans /etc/init.d qui ne le ferait pas et un arrêt plus sophistiqué, comme celui de Tomcat.

4
Don Branson

Cette question concerne la démonisation d'un programme arbitraire (non spécifique à Java), de sorte que certaines des réponses peuvent s'appliquer à votre cas:

2
dreeves

DaemonTools: - Un moyen plus propre de gérer les services sous UNIX https://cr.yp.to/daemontools.html

  1. Installez les outils de démon à partir de l’URL https://cr.yp.to/daemontools/install.html Suivez les instructions qui y sont mentionnées. Pour tout problème, veuillez essayer les instructions https: //Gist.github. com/rizkyabdilah/8516303

  2. Créez un fichier dans /etc/init/svscan.conf et ajoutez les lignes ci-dessous (requis uniquement pour cent-os-6.7).

 start on runlevel [12345]
 stop on runlevel [^12345]
 respawn
 exec /command/svscanboot
  1. Créez un nouveau script nommé run dans/folder/service/vm/et ajoutez les lignes ci-dessous.
#!/bin/bash    
echo starting VM 
exec Java -jar
/root/learning-/daemon-Java/vm.jar

Remarque: remplacez le Jar par votre propre fichier Jar. ou n'importe quel fichier de classe Java.

  1. Redémarrez le système

  2. svstat/service/vm devrait être opérationnel maintenant!.

  3. svc -d/service/vm devrait faire tomber vm maintenant!.
  4. svc -u/service/vm devrait mettre vm maintenant!.
2
Velu

Jetez un coup d'oeil ici:

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

pour un exemple de code basé sur JNI. Dans ce cas, vous démonalisez le code qui a été démarré en tant que Java et la boucle principale est exécutée en C. Mais il est également possible de mettre la boucle de service principale du démon dans Java.

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

Amusez-vous avec JNI!

0
Oo.oO
Nohup Java -jar {{your-jar.jar}} > /dev/null &

Cela peut faire l'affaire.

0
fifman