2010-09-20 14 views
1

J'ai un crontab qui ressemble à:Comportement de crane insane. continue à faire bash défunte processus

SHELL=/bin/bash 
PATH=/sbin:/bin:/usr/sbin:/usr/bin 
MAILTO=root 
HOME=/ 

0-59 * * * * /var/www/html/private/fivemin/zdaemon.php >> /dev/null & 

simple que possible, non?

zdaemon.php que je suis essai juste avec est:

#!/usr/bin/php 
<? 


while(true){ 
     sleep(1); 
} 

?> 

Chaque fois qu'il exécute Se pose comme:

root  15532 0.0 0.1 57228 1076 ?  Ss 19:09 0:00 crond 
root  16681 0.0 0.1 72196 1428 ?  S 21:46 0:00 crond 
root  16682 0.0 0.0  0 0 ?  Zs 21:46 0:00 [bash] <defunct> 
root  16683 0.0 0.5 54800 5740 ?  S 21:46 0:00 /usr/bin/php /var/www/html/private/fivemin/zdaemon.php 
root  16687 0.0 0.1 72196 1428 ?  S 21:47 0:00 crond 
root  16688 0.0 0.0  0 0 ?  Zs 21:47 0:00 [bash] <defunct> 
root  16689 0.0 0.5 54800 5740 ?  S 21:47 0:00 /usr/bin/php /var/www/html/private/fivemin/zdaemon.php 

Je suis frappais mon cerveau contre un mur sur toute la journée. Quelqu'un a-t-il déjà vu cela avant? Des idées du tout?

C'est une référence à: Init.d script hanging

Répondre

7

A zombie Le processus n'est pas nécessairement une mauvaise chose en soi. Il indique que le processus enfant est mort et que le processus parent n'a pas encore atteint son statut (en utilisant wait() ou un appel système associé).

Ce qui se passe est la suivante - cron est intéressé par stderr du script, il commence (pour qu'il puisse l'envoyer par courriel à vous devez le script échec), donc il crée un tuyau qui attache stderr du script à écrire end (fichier descripteur 2). Puis cron se trouve en lecture sur l'extrémité de lecture du tuyau, en attendant que le script se termine et lise et (read() de zéro octet) - il récupère ensuite l'état de retour du script.

Dans votre exemple, le démon a donné naissance, hérite le descripteur de fichier stderr, et donc lorsque les sorties de coquille intermédiaires (et devient défunte), la conduite est maintenue ouverte par le démon. Par conséquent, cron ne lit jamais et et, par conséquent, ne récupère jamais l'état de retour.

La solution consiste à s'assurer que stderr de votre démon est fermé.Ceci peut être réalisé comme suit:

0-59 * * * * /var/www/html/private/fivemin/zdaemon.php >> /dev/null 2>&1 & 

qui rédigera deuxstdout et stderr-/dev/null

+0

C'est parfait !! C'était 100% stderr qui me baisait. J'ai changé la ligne pour: $ LDIR/$ EXEC &> $ LDIR/swapi.log & MYPID = $! dans mon script init.d (voir autre publication) et maintenant tout fonctionne comme il se doit. Merci merci merci!!! – ehiller

2

Je pense que votre problème principal est que le stderr va encore à la coquille, mais le processus de l'enfant (votre processus php) est en train de dormir, ce qui entraîne dans le processus de zombie. Essayez ceci:

0-59 * * * * /var/www/html/private/fivemin/zdaemon.php &> /dev/null & 

Si vous rencontrez toujours des problèmes avec un processus zombie, jetez un oeil à nohup.

+0

remarqué ceci est juste la bonne réponse aussi bien! – ehiller

0

La façon habituelle de créer un démon est de faire un travail en chaîne avec un processus fils, puis de quitter le processus parent avec un code d'erreur de 0. Je ne suis pas certain que ce soit votre problème. Je n'ai pas fait cela en PHP, mais vous pouvez utiliser pcntl_fork() pour imiter the usual c way

+0

Il est à noter que le démarrage d'un démon avec fork() n'est pas trivial, et vous devez d'habitude faire deux fois le fork pour le faire correctement. –

2

Il me semble étrange de mettre en contexte un processus dans un crontab. Essayez de supprimer le & à la fin de la ligne.