Problème
J'ai un formulaire qui, une fois soumis, exécutera un code de base pour traiter les informations soumises et l'insérer dans une base de données pour l'afficher sur un site Web de notification. De plus, j'ai une liste de personnes qui se sont inscrites pour recevoir ces notifications par e-mail et SMS. Cette liste est triviale pour le moment (seulement environ 150), mais elle suffit pour que cela prenne plus d'une minute pour parcourir toute la table des abonnés et envoyer plus de 150 e-mails. (Les e-mails sont envoyés individuellement à la demande des administrateurs système de notre serveur de messagerie en raison des politiques de messagerie de masse.)
Pendant ce temps, l'individu qui a publié l'alerte restera assis sur la dernière page du formulaire pendant près d'une minute sans aucune confirmation positive que sa notification est affichée. Cela conduit à d'autres problèmes potentiels, tout ce qui a des solutions possibles que je trouve loin d'être idéales.
Tout d'abord, l'affiche peut penser que le serveur est à la traîne et cliquer à nouveau sur le bouton «Soumettre», provoquant le redémarrage ou l'exécution du script deux fois. Je pourrais résoudre ce problème en utilisant JavaScript pour désactiver le bouton et remplacer le texte pour dire quelque chose comme «Traitement ...», mais ce n'est pas idéal car l'utilisateur sera toujours bloqué sur la page pendant toute la durée de l'exécution du script. (De plus, si JavaScript est désactivé, ce problème existe toujours.)
Deuxièmement, l'affiche peut fermer l'onglet ou le navigateur prématurément après avoir soumis le formulaire. Le script continuera à s'exécuter sur le serveur jusqu'à ce qu'il essaie de réécrire dans le navigateur, mais si l'utilisateur navigue ensuite sur une page de notre domaine (pendant que le script est toujours en cours d'exécution), le navigateur suspend le chargement de la page jusqu'à ce que le script soit terminé . (Cela ne se produit que lorsqu'un onglet ou une fenêtre du navigateur est fermé et non pas l'ensemble de l'application du navigateur.) Pourtant, c'est loin d'être idéal.
(Possible) Solution
J'ai décidé de séparer la partie "e-mail" du script dans un fichier séparé que je pourrai appeler une fois la notification publiée. J'ai initialement pensé à le mettre sur la page de confirmation une fois la notification publiée avec succès. Cependant, l'utilisateur ne saura pas que ce script est en cours d'exécution et aucune anomalie ne lui sera apparente; Ce script ne peut pas échouer.
Mais que se passe-t-il si je peux exécuter ce script en tant que processus d'arrière-plan? Donc, ma question est la suivante: comment puis-je exécuter un script PHP pour se déclencher en tant que service d'arrière-plan et s'exécuter complètement indépendamment de ce que l'utilisateur a fait au niveau du formulaire?
EDIT: Cela ne peut pas être cron'ed. Il doit s'exécuter au moment où le formulaire est soumis. Ce sont des notifications hautement prioritaires. De plus, les administrateurs système exécutant nos serveurs interdisent aux crons de s'exécuter plus de 5 minutes.
la source
exec()
mais je n'ai jamais essayé cela.ajax
et j'insèresleep()
avec un intervalle de temps dans la boucle (j'utilise foreach dans mon cas) pour exécuter le processus en arrière-plan. Cela fonctionne parfaitement sur mon serveur. Pas sûr des autres. J'ajoute égalementignore_user_abort()
etset_time_limit()
(avec l'heure de fin calculée) avant la boucle pour m'assurer que le script ne sera pas arrêté par le serveur que j'utilise, même selon mon test, le script complétant la tâche sansignore_user_abort()
etset_time_limit()
.gearman
avec php pour gérer les tâches en arrière-plan. Il est parfait pour évoluer si vous rencontrez un traitement fastidieux et des charges lourdes. Vous devriez y jeter un œil.Réponses:
Faire quelques expérimentations avec
exec
etshell_exec
j'ai découvert une solution qui fonctionnait parfaitement! Je choisis d'utilisershell_exec
afin de pouvoir enregistrer chaque processus de notification qui se produit (ou non). (shell_exec
retourne sous forme de chaîne et c'était plus facile que d'utiliserexec
, d'assigner la sortie à une variable puis d'ouvrir un fichier dans lequel écrire.)J'utilise la ligne suivante pour appeler le script d'e-mail:
Il est important de noter le
&
à la fin de la commande (comme indiqué par @netcoder). Cette commande UNIX exécute un processus en arrière-plan.Les variables supplémentaires entourées de guillemets simples après le chemin du script sont définies comme des
$_SERVER['argv']
variables que je peux appeler dans mon script.Le script de courrier électronique sort ensuite dans mon fichier journal à l'aide de
>>
et produira quelque chose comme ceci:la source
$post_id
après le chemin du script php?$post_id
; Je préférerais jeter directement à un numéro:(int) $post_id
. (Appel à votre attention pour décider ce qui est le mieux.)Sur les serveurs Linux / Unix, vous pouvez exécuter un travail en arrière-plan en utilisant proc_open :
L'
&
être le plus important ici. Le script continuera même si le script d'origine est terminé.la source
proc_close
lorsque la tâche est terminée.proc_close
fait que le script se bloque environ 15 à 25 secondes. J'aurais besoin de garder un journal en utilisant les informations de pipe, donc je dois ouvrir un fichier sur lequel écrire, le fermer, puis fermer la connexion proc. Donc, malheureusement, cette solution ne fonctionne pas pour moi.proc_close
, c'est le point! Et oui, vous pouvez rediriger vers un fichier avecproc_open
. Voir la réponse mise à jour.De toutes les réponses, aucune n'a considéré la fonction ridiculement facile fastcgi_finish_request , qui, lorsqu'elle est appelée, vide toute la sortie restante vers le navigateur et ferme la session Fastcgi et la connexion HTTP, tout en laissant le script s'exécuter en arrière-plan.
Un exemple:
la source
PHP
exec("php script.php")
peut le faire.À partir du manuel :
Donc, si vous redirigez la sortie vers un fichier journal (ce qui est une bonne idée de toute façon), votre script d'appel ne se bloquera pas et votre script de courrier électronique s'exécutera dans bg.
la source
Et pourquoi ne pas faire une requête HTTP sur le script et ignorer la réponse?
http://php.net/manual/en/function.httprequest-send.php
Si vous faites votre demande sur le script, vous devez appeler votre serveur Web qui l'exécutera en arrière-plan et vous pourrez (dans votre script principal) afficher un message indiquant à l'utilisateur que le script est en cours d'exécution.
la source
Que dis-tu de ça?
Ce second script PHP doit être configuré pour s'exécuter en tant que cron.
la source
Comme je sais que vous ne pouvez pas le faire de manière simple (voir fork exec, etc. (ne fonctionne pas sous Windows)), vous pouvez peut-être inverser l'approche, utiliser l'arrière-plan du navigateur en postant le formulaire en ajax, donc si le message est toujours travail, vous n'avez pas de temps d'attente.
Cela peut aider même si vous devez faire une longue élaboration.
À propos de l'envoi de courrier, il est toujours suggéré d'utiliser un spouleur, peut être un serveur smtp local et rapide qui accepte vos demandes et les spoule vers le vrai MTA ou les met tout dans une base de données, plutôt que d'utiliser un cron qui spoule la file d'attente.
Le cron peut être sur une autre machine appelant le spouleur en tant qu'URL externe:
la source
Le travail cron en arrière-plan semble être une bonne idée pour cela.
Vous aurez besoin d'un accès ssh à la machine pour exécuter le script en tant que cron.
$ php scriptname.php
pour l'exécuter.la source
Si vous pouvez accéder au serveur via ssh et exécuter vos propres scripts, vous pouvez créer un simple serveur fifo en utilisant php (bien que vous devrez recompiler php avec le
posix
support defork
).Le serveur peut vraiment être écrit dans n'importe quoi, vous pouvez probablement le faire facilement en python.
Ou la solution la plus simple serait d'envoyer une HttpRequest et de ne pas lire les données de retour, mais le serveur pourrait détruire le script avant la fin du traitement.
Exemple de serveur:
Exemple de client:
la source
Le moyen le plus simple d'exécuter un script PHP en arrière-plan est
Le script s'exécutera en arrière-plan et la page atteindra également la page d'action plus rapidement.
la source
En supposant que vous exécutez sur une plate-forme * nix, utilisez
cron
et l'php
exécutable.ÉDITER:
Il y a déjà un certain nombre de questions demandant "exécuter php sans cron" sur SO. En voici une:
Planifier des scripts sans utiliser CRON
Cela dit, la réponse exec () ci-dessus semble très prometteuse :)
la source
Si vous êtes sous Windows, recherchez
proc_open
oupopen
...Mais si nous sommes sur le même serveur "Linux" exécutant cpanel, alors c'est la bonne approche:
N'utilisez pas
fork()
oucurl
si vous doutez de pouvoir les gérer, c'est comme abuser de votre serveurEnfin, sur le
script.php
fichier qui est appelé ci-dessus, prenez note de ceci assurez-vous d'avoir écrit:la source
pour le travailleur d'arrière-plan, je pense que vous devriez essayer cette technique, cela vous aidera à appeler autant de pages que vous aimez toutes les pages fonctionneront à la fois indépendamment sans attendre que chaque page de réponse soit asynchrone.
form_action_page.php
testpage.php
PS: si vous souhaitez envoyer des paramètres d'url en boucle, suivez cette réponse: https://stackoverflow.com/a/41225209/6295712
la source
Dans mon cas, j'ai 3 paramètres, l'un d'eux est string (mensaje):
Dans mon Process.php j'ai ce code:
la source
Cela fonctionne pour moi. tyr ceci
la source
serialize()
function. par exemple, j'aiindex.php
avec formulaire et j'envoie une valeur via ajax à index2.php Je veux effectuer l'envoi de données dans index2.php en arrière-plan que suggérez-vous? merciUtilisez Amphp pour exécuter des travaux en parallèle et de manière asynchrone.
Installez la bibliothèque
Exemple de code
Pour votre cas d'utilisation, vous pouvez faire quelque chose comme ci-dessous
la source