2010-06-26 5 views
1

J'essaie d'empêcher mon script cron de lui permettre de fonctionner en parallèle. J'en ai besoin pour que, s'il n'y a pas d'exécution en cours, le script soit autorisé à s'exécuter jusqu'à ce qu'il soit terminé, l'expiration du script ou une exception se produit.Arrêt de l'exécution parallèle du script PHP

J'ai essayé d'utiliser la fonction flock de PHP pour engager un verrou de fichier, exécutez le script, puis relâchez le verrou. Cependant, il semble toujours que je puisse exécuter le script plusieurs fois en parallèle. Est-ce que je manque quelque chose? Btw, je développe sur Mac OS X avec le système de fichiers Mac, peut-être est-ce la raison pour laquelle les verrous de fichiers sont ignorés? Bien que la documentation de PHP regarde seulement au sujet des systèmes de fichiers NTFS?

 // Construct cron lock file path 
    $cronLockFilePath = realpath(APPLICATION_PATH . '/locks/cron'); 

    // Get cron lock file 
    $cronLockFile = fopen($cronLockFilePath, 'r'); 

    // Lock cron lock file 
    if (flock($cronLockFile, LOCK_EX)) { 

echo 'lock'; 
sleep(10); 

    } else { 

echo 'no lock'; 
    } 

Répondre

3

Votre idée est fondamentalement correcte, mais bricoler avec des verrous de fichiers conduit généralement à un comportement étrange.

Il suffit de créer un fichier au démarrage du script et de le supprimer à la fin. La présence du fichier indiquera si le cron est déjà en cours d'exécution. Assurez-vous absolument, que le fichier est supprimé à la fin, même si le cron se heurte à une erreur à mi-chemin.

+0

erreurs de gestion ne devrait pas être un problème, je vais juste attraper toutes les exceptions et puis dissocier le fichier créé ... mais j'imagine que la gestion des terminaisons de script n'est pas possible, par exemple redémarre le serveur, redémarre Apache, ou timeout de script. Comme c'est un fichier cron, je pourrais juste faire fonctionner le script sans timeout. – cappuccino

+0

Vous pouvez essayer d'avoir deux scripts: Le premier crée le fichier "lock", exécute votre script cron en cours, puis supprime le fichier "lock". Donc, même si votre script cron actuel explose, le premier script supprimera toujours le verrou. Autre chose que j'ai déjà faite: si votre script détecte que le fichier "lock" est là, mais que le filectime est plus ancien qu'une heure, vous le supprimez quand même, car il est très probable que quelque chose s'est mal passé. – FlorianH

0

Je pense que ce que vous pouvez faire est d'écrire un fichier normal quelque part (lock.txt ou quelque chose) quand le script commence à exécuter, sans troupeaux, et enlever arrêt du script en cours d'exécution. Et puis vérifiez toujours à l'initialisation si ce fichier existe déjà - une autre instance en cours d'exécution.

+0

La vérification de l'existence d'un fichier et de la création d'un fichier de verrouillage est au moins deux commandes, ce qui signifie qu'il est toujours possible d'avoir des conditions de concurrence. 'flock' n'existe pas sans raison. – cweiske

1

De la documentation:

Avertissement

Sur certains troupeau de systèmes d'exploitation() est mis en œuvre au niveau du processus. Lorsque en utilisant une API serveur multithread comme ISAPI vous ne pouvez pas être en mesure de compter sur flock() pour protéger les fichiers contre d'autres scripts PHP exécutant en parallèle threads de la même instance de serveur!

Vous pouvez essayer de créer et supprimer un fichier, ou écrire quelque chose dedans.

+0

Je vois, je vois, j'ai vu d'autres méthodes qui reposent sur la création d'un fichier, puis la suppression une fois terminé. cependant, ceci ne sera pas capable de gérer les timeouts et les exceptions de script où le script est terminé avant l'exécution de la fonction unlink. En tant que tel, même si un script a peut-être été arrêté, le script ne pourra plus s'exécuter car le fichier créé n'a pas été supprimé. Y a-t-il une méthode pour faire face à cette situation? – cappuccino

+0

D'abord, peut-être que vous pouvez essayer d'ouvrir le socket et lorsque d'autres threads tentent d'ouvrir le même socket sur le même port, ils échouent. – codez