5
votes

Pourquoi les fichiers "lock" sont-ils utilisés en PHP au lieu de simplement compter les processus?

J'ai vu beaucoup d'exemples où un fichier "verrouillé" est utilisé pour savoir si un script PHP est en cours d'exécution.

Exemple:

  1. démarrage du script
  2. vérifie si "/ tmp / lockfile" est actuellement verrouillé
  3. S'il est verrouillé, quittez. Sinon, verrouillez le fichier et continuez

De cette façon, si un script de longue durée est lancé deux fois, seule la première instance sera exécutée. Ce qui est génial.

Cependant, il semble que ce ne soit pas la bonne façon de le contourner. Pourquoi ne vérifions-nous pas simplement si le processus fonctionne déjà comme ça?

if(exec("ps -C " . basename(__FILE__) . " --no-headers | wc -l") > 1){
  echo "Already running.";
  exit;
}

Y a-t-il des pièges potentiels à cette méthode? Pourquoi est-ce que je vois si souvent la solution de contournement du fichier «verrouillé»? Il semble certainement plus précis de compter les processus avec le nom que nous recherchons ....


7 commentaires

Probablement parce que la vérification du fichier de verrouillage peut se faire en PHP pur sans connaissance de Bash etc ...


selon votre hébergement, vous n'aurez peut-être pas la possibilité d'exécuter exec


Je pense que vous pourriez envisager de modifier votre question ... cela s'applique certainement à la pratique générale qui est plus large que PHP.


@Brad - Bon point. Cela pourrait également s'appliquer à d'autres contextes. Cependant, je me demandais en partie s'il y avait des pièges à cette méthode qui étaient spécifiques à PHP.


car ps ne fonctionne que sous linux, flock fonctionne également sous Windows


Oui, Bash n'est pas pris en charge sur de nombreux serveurs Windows


La meilleure façon d'implémenter quelque chose comme ça, est de créer votre propre système de verrouillage basé sur un script si vous voulez une compatibilité croisée à 100% car l'implémentation php (s) de flock n'est pas garantie de fonctionner sur tous les systèmes d'exploitation (serveurs multi-threads). .. c'est ce qui me rend parfois méfiant à propos de php, je veux dire qu'il a quelque chose comme 6000 fonctions de base, mais il a encore des problèmes majeurs pour contrôler les appels d'accès simples au niveau du système ...


3 Réponses :


0
votes

Premièrement, la commande n'est pas correcte. Quand j'exécute php test.php et que la commande

$count = exec("ps -aux|grep 'php test.php' -c");

if($count > 3){
  echo "Already running.".$count;
  exit;
}

while(1){
    sleep(20);
}

n'obtient rien. Vous pouvez utiliser ps -aux | grep 'test.php' -c pour obtenir le numéro de processus.Mais exec ("ps -aux | grep 'php test.php' -c"); le numéro de retour doit moins 2 est le numéro de processus réel

La raison d'utiliser le fichier de verrouillage la plupart du temps est exec ou une autre fonction de commande nécessite une autorisation spéciale, et est disable_functions dans la configuration par défaut de php.ini.

Tester un script comme celui-ci:

 ps -C test.php


1 commentaires

Hmmm, vous avez peut-être un problème avec votre ps ? Selon le manuel , -C signifie "Sélectionner par nom de commande . " Pour moi, la commande bash dans mon code renvoie "1" pendant que le processus est en cours d'exécution. De plus, -C nécessite une correspondance exacte, votre grep obtiendra également des correspondances partielles, ce qui pourrait tout gâcher.



0
votes

La principale raison pour laquelle les "fichiers verrouillés" sont utilisés est simplement parce qu'ils peuvent être censés fonctionner dans n'importe quel environnement hôte. Si vous pouvez "créer un fichier" et si vous pouvez le "verrouiller", ce code fonctionnera ... n'importe où.

Aussi - "il n'y a rien à gagner à être" intelligent "." Cette stratégie bien connue est connue pour bien fonctionner - donc, "courez avec."


3 commentaires

La méthode de fichier "lock" fonctionnait très bien pour moi - jusqu'à ce que je commence à l'utiliser dans plus de 200 emplacements sur quelques scripts. J'ai commencé à remarquer des choses étranges qui se produisaient (comme des scripts non liés (rarement) "voler" le verrou du fichier, l'empêchant de fonctionner correctement. Peut-être un problème de système d'exploitation avec les verrous de fichiers?) Quoi qu'il en soit, mes scripts ne fonctionnent que sur Linux (et cela a gagné '' t changer). Donc, dans mon cas, une solution qui fonctionne absolument indépendamment des états de verrouillage de fichier est meilleure qu'une solution qui fonctionne dans n'importe quel environnement hôte.


Un problème critique avec les "fichiers de verrouillage" dans certains systèmes d'exploitation, par exemple Unix / Linux est que les verrous sont considérés comme consultatifs. Par conséquent, la présence du fichier est souvent utilisée comme une indication de la mise en place d'un verrou.


J'ai déjà vu une implémentation "présence de fichier". Mon seul souci avec celui-là (et corrigez-moi si je me trompe) est que si le processus subit un crash "dur", le fichier sera laissé derrière nous et le script ne pourra plus s'auto-récupérer (car il pense qu'il est toujours en cours d'exécution)



2
votes

Sur la base des commentaires ici et de mes propres observations, j'ai composé une liste des avantages et des inconvénients des deux approches: méthode

flock :

avantages: p>

  • Plus compatible avec les systèmes d'exploitation
  • Aucune connaissance de bash requise
  • Approche plus courante, de nombreux exemples
  • Fonctionne même avec exec () désactivé
  • Peut utiliser plusieurs verrous dans un seul fichier pour autoriser différents "modes" d'exécution du même fichier en même temps

cons:

  • Ce n'est pas définitif. Si votre fichier de verrouillage est supprimé par un processus / utilisateur externe, vous pourriez vous retrouver avec plusieurs processus. Si vous enregistrez le fichier de verrouillage dans le répertoire / tmp , c'est une possibilité valable, car tout ce qui se trouve dans ce répertoire est censé être "temporaire"
  • Dans certaines circonstances, lorsqu'un processus meurt de manière inattendue, le verrou de fichier peut être transféré vers un processus indépendant (je ne le croyais pas au début, mais j'ai trouvé des exemples de cela se produisant (bien que rarement) sur plus de 200 systèmes basés sur unix , dans 3 systèmes d'exploitation différents)

exec ("ps -C ...") méthode

avantages:

  • Puisque vous comptez réellement les processus , cela fonctionnera à chaque fois, quel que soit l'état des verrous de fichiers, etc.

cons:

  • Fonctionne uniquement sous Linux
  • nécessite que "exec" soit activé
  • Si vous modifiez le nom de votre script, cela pourrait entraîner des doubles processus (et assurez-vous que le nom de votre script n'est pas codé en dur dans le code)
  • Suppose que votre script n'a qu'un seul "mode" en cours d'exécution

EDIT: J'ai fini par utiliser ceci:

if (exec("pgrep -x " . $scriptName . " -u ". $currentUser . " | wc -l") > 1)
{
  echo $scriptName . " is already running.\n";
  exit;
}

... parce que ps ne vous permet pas pour filtrer sur le propriétaire du processus en plus du nom du processus, et je voulais autoriser ce script à s'exécuter plusieurs fois si un autre utilisateur l'exécutait.


EDIT 2: p >

... Donc, après avoir fonctionné pendant quelques jours, ce n'est pas parfait non plus. D'une manière ou d'une autre, le processus a démarré plusieurs fois sur la même machine sous le même utilisateur. Ma seule hypothèse est qu'il y a eu un problème (manque de mémoire, etc.) qui a fait que pgrep ne renvoie rien, alors qu'il aurait dû renvoyer quelque chose.

Cela signifie donc que NI la méthode flock et les méthodes du processus de comptage ne sont fiables à 100%. Vous devrez déterminer quelle approche fonctionnera le mieux pour votre projet.

En fin de compte, j'utilise une autre solution qui stocke le PID de la tâche en cours dans un fichier "verrouillé", qui n'est pas réellement verrouillé avec troupeau. Ensuite, lorsque le script démarre, vérifie si le fichier de verrouillage existe, et si c'est le cas, récupère le contenu (PID du dernier démarrage du script) Ensuite, il vérifie s'il est toujours en cours d'exécution, en comparant le / proc / # PID # / cmdline contenu avec le nom du script en cours d'exécution.


1 commentaires

con de cette méthode exec: elle suppose que le script n'est utilisé que pour cette fonction. Si votre script a deux ou plusieurs fonctions, il peut en être une autre en cours d'exécution. On peut bien sûr affirmer que chaque fonction doit être dans son propre fichier.