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?
Apache Commons Daemon exécutera votre programme Java en tant que démon Linux ou service WinNT.
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());
}
Je me trouve souvent en train d'écrire des scripts ou des lignes de commande qui ressemblent essentiellement à ceci, si je veux:
Prendre plaisir.
Nohup Java com.me.MyProgram </dev/null 2>&1 | tee logfile.log &
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.
Vous pouvez essayer Java Service Wrapper , l'édition de la communauté est gratuite et répond à vos besoins.
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 ().
Ç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.
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:
DaemonTools: - Un moyen plus propre de gérer les services sous UNIX https://cr.yp.to/daemontools.html
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
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
#!/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.
Redémarrez le système
svstat/service/vm devrait être opérationnel maintenant!.
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!
Nohup Java -jar {{your-jar.jar}} > /dev/null &
Cela peut faire l'affaire.