Démarrer un processus en arrière-plan sous Linux avec C

J’essaye de faire quelque chose d’un peu bizarre ici. Je dois démarrer un processus, logcat, à partir d’un démon qui fonctionnera en arrière-plan et imprimera sur le terminal sans prendre le contrôle de stdin. Il est idéal pour la connexion afin que logcat imprime les messages du journal tout en permettant à l’utilisateur d’entrer des commandes standard et d’initialiser les programmes à partir du shell. Voici le code du démon que j’ai à ce jour. Le programme, logcat, démarre et affiche les messages du journal, mais je ne peux pas entrer de commandes dans stdin car il semble que le programme ait pris le contrôle de stdin.

int main ( int argc, char** argv, char** env ) { int fd; if ((fd = open("/dev/console", O_RDWR)) < 0) { fd = open("/dev/null", O_RDWR); } printf("THIS IS A TEST\n"); dup2(1, fd); dup2(2, fd); pid_t childpid = fork(); if(childpid == -1) { perror("Failed to fork, logcat not starting"); return 1; } if(childpid == 0) { //this is the child, exec logcat setsid(); int execReturn = execl("/system/bin/logcat", "logcat", (char *) 0); } else { //this is the parent do nothing close(fd); return 0; } close(fd); return 0; } 

Merci

La commande ‘logcat’ semble être pour le développement Android – ce qui pourrait expliquer la mauvaise position de la commande.

L’opération clé que vous devez corriger est de vous assurer de fermer votre entrée standard actuelle (le terminal) et d’ouvrir /dev/null/ pour le périphérique d’entrée:

 close(0); if ((fd = open("/dev/null", O_RDONLY)) != 0) ...error - failed to open /dev/null! 

Cela signifie que votre processus enfant démonisé ne lit rien du terminal.


Ce que je pense que vous voulez faire c’est:

  1. Exécutez votre programme de lancement à partir d’une ligne de commande, qui aura une entrée standard, une sortie standard et une erreur standard connectée à «le terminal».
  2. A l’intérieur de votre programme, vous voulez remplacer l’entrée standard afin qu’elle vienne de /dev/null .
  3. Vous voulez laisser la sortie standard seule – vous voulez que logcat écrive dans la sortie standard actuelle.
  4. Vous voulez probablement laisser l’erreur standard seule aussi.

Au cours de la procédure, vous effectuez correctement votre démonisation (en empruntant le lien de la réponse de @bstpierre), en vous assurant que le terminal auquel vous êtes connecté ne correspond pas à votre terminal de contrôle. votre démon. La plomberie est plus simple que ce que vous avez configuré – vous devez gérer les entrées standard et laisser la sortie standard et l’erreur standard inchangées (au lieu de modifier les sorties et de laisser l’entrée inchangée).

Maintenant, vous voudrez peut-être que la sortie aille dans /dev/console ; Si c’est le cas, il est raisonnable de réviser le code pour ouvrir /dev/console . Cependant, il n’est pas raisonnable de se rabattre sur /dev/null si vous ne pouvez pas ouvrir /dev/console ; votre programme doit signaler une erreur et échouer (car il est inutile d’avoir écrit logcat dans /dev/null !). Assurez-vous d’ouvrir la console avec l’indicateur O_NOCTTY afin qu’il ne devienne pas le terminal de contrôle du démon.

Le dernier commentaire que je ferais est:

  • Êtes-vous sûr de vouloir que du texte aléatoire apparaisse sur votre terminal ou votre console lorsqu’il est utilisé pour d’autres choses?

Je ne l’aime pas beaucoup quand cela se produit.


Voir aussi: SO 958249

Comment démoniser sous Linux [lien mort]

Comment démoniser sous Linux [archive de la machine à revenir ci-dessus]

gist sur github – code tiré du lien ci-dessus

Résumé:

L’une des choses que je continue à utiliser sont les démons Linux qui ne se démodent pas correctement. Pour démoniser correctement, les étapes suivantes doivent être suivies.

  • L’appel fork () est utilisé pour créer un processus distinct.
  • L’appel setsid () est utilisé pour détacher le processus du parent (normalement un shell).
  • Le masque de fichier doit être réinitialisé.
  • Le répertoire actuel doit être modifié en quelque chose de bénin.
  • Les fichiers standard (stdin, stdout et stderr) doivent être rouverts.

Si vous ne suivez aucune de ces étapes, vous obtiendrez un processus démon qui risque de ne pas fonctionner correctement. Les symptômes typiques sont les suivants.

  • Le démarrage du démon et la déconnexion entraînent le blocage du terminal. Ceci est particulièrement désagréable avec ssh.
  • Le répertoire à partir duquel le démon a été lancé rest verrouillé.
  • Une sortie parasite apparaît dans le shell à partir duquel le démon a été démarré.

Il existe une fonction spéciale pour cela dans la glibc:

 #include  ... /* We are in the parent, yet */ daemon(0,0); /* Now we are in the child */ ... 

Plus de détails ici http://linux.die.net/man/3/daemon