Travail en cours d'exécution en arrière-plan à partir de Perl SANS attendre de retour
L'Avertissement
Tout d'abord, je sais que cette question (ou des variantes) a été demandé un millier de fois. J'ai vraiment passé quelques heures à la recherche de l'évidence et qui n'est pas si évident endroits, mais il y a peut être quelque chose de petit, je suis absent.
Le Contexte
Permettez-moi de définir le problème plus clairement: je suis la rédaction d'un bulletin application dans laquelle je veux le réel de l'envoi de processus asynchrone. Comme dans, l'utilisateur clique sur "envoyer", la requête renvoie immédiatement et puis, ils peuvent vérifier l'état d'avancement dans une page spécifique (via AJAX, par exemple). Il est écrit dans votre traditionnelle de LAMPE de la pile.
Dans l'hôte particulier, je suis à l'aide, PHP exec() et system() sont désactivées pour des raisons de sécurité, mais en Perl fonctions du système (exec, le système et les backticks) ne le sont pas. Donc, mon solution la solution a été de créer un "déclencheur" de script en Perl qui appelle l'expéditeur réel via la CLI PHP, et redirige vers la page en cours.
Où je suis Coincé
La très la ligne les appels de l'expéditeur est, dès maintenant:
system("php -q sender.php &");
Problème, c'est de ne pas retourner immédiatement, mais l'attente pour le script à la fin. Je voulez qu'il fonctionne dans le fond et que l'appel système lui-même de retour tout de suite. J'ai aussi essayé de lancer un script similaire dans mon terminal Linux, et, en fait, l'invite n'apparaît pas jusqu'à ce que, une fois le script terminé, même si mon test de sortie ne fonctionne pas, indiquant qu'il est vraiment en cours d'exécution en arrière-plan.
Ce que j'ai déjà essayé
- Perl fonction exec () - même résultat de system().
- La modification de la commande: "php -q sender.php | à maintenant"), en espérant que le "au" démon allait revenir et que le processus PHP lui-même ne pas être attaché à Perl.
- De l'exécution de la commande "indirectement": "/bin/sh-c 'php -q sender.php & "" - attend encore jusqu'à ce que sender.php est la fin de l'envoi.
- fork()'ing le processus et de l'exécution de l'appel système à l'enfant (espérons-le processus détaché) - le même résultat que ci-dessus
Mon environnement de test
Juste pour être sûr que je ne suis pas manque rien d'évident, j'ai créé un sleeper.php script qui dort juste cinq secondes avant de sortir. Et un test.script cgi qui est comme ça, mot à mot:
#!/usr/local/bin/perl
system("php sleeper.php &");
print "Content-type: text/html\n\ndone";
Que dois-je essayer maintenant?
OriginalL'auteur Rafael Almeida | 2010-04-15
Vous devez vous connecter pour publier un commentaire.
Essentiellement, vous avez besoin de 'daemonize' un processus -- fourche d'un enfant, puis entièrement le débrancher de la mère, de sorte que le parent peut résilier en toute sécurité sans affecter l'enfant.
Vous pouvez le faire facilement avec le module CPAN Proc::Daemon:
OriginalL'auteur Ether
Parfois STDERR et STDOUT pouvez également verrouiller le système... De faire les deux, j'utilise (pour la plupart des environnement shell (bash, csh, etc) que j'utilise...):
OriginalL'auteur SirGCal
Utilisation
fork()
et ensuite appelersystem
dans le processus de l'enfant.Essayé aujourd'hui, mais le script principal, ne pas quitter jusqu'à ce que après l'appelé est résilié.
juste pour l'achèvement souci: ajouter
close STDIN;close STDOUT;
avant d'appelersystem($command);
et la async processus ne sera pas keep-alive le lien de la page webOriginalL'auteur mob
Une autre option serait de créer un gearman serveur et un processus de travail (ou de processus) que faire de l'emailing. De cette façon, vous contrôlez la façon dont beaucoup d'emailing est en cours simultanément, et pas de bifurcation est nécessaire. Le client (votre programme) peut ajouter une tâche à la gearman serveur (en arrière-plan sans attendre le résultat si vous le souhaitez), et les travaux sont mis en file d'attente jusqu'à ce que le serveur transmet le travail à un travailleur. Il y a perl et php Api pour gearman, de sorte qu'il est très pratique.
OriginalL'auteur runrig
Réussi à résoudre le problème. Apparemment, ce qui est de l'empêcher de revenir était que l'appel à l'expéditeur de cette façon, ne pas déconnecter la sortie standard (stdout). Donc, la solution était tout simplement de changer le système d'appel à l':
Merci à tous pour l'aide. En fait, c'était lors de la lecture de l'ensemble de l'histoire de la "daemonizing" un processus que j'ai eu l'idée de débrancher la sortie standard (stdout).
fork
etexec
est une bien meilleure solution, à mon humble avis.Je comprends. Mais dans ce cas, la simplicité est de loin la principale contrainte. Je sais que le fork/exec méthode devrait fonctionner tout de suite (et je l'ai "pris note" pour une utilisation future), mais à partir de maintenant, je vais avec la première solution la plus simple qui fonctionne =)
OriginalL'auteur Rafael Almeida