SELFHTML/Aides à la navigation CGI/Perl Fonctions Perl |
Fonctions pour les appels du système d'exploitation |
|
Généralités sur ces fonctions |
|
Sous les "appels du système d'exploitation" sont rassemblées ici des fonctions qui s'orientent avant tout de très près au concept du système d'exploitation Unix. Quelques unes de ces fonctions seulement peuvent servir sur d'autres plates-formes.
Les systèmes Unix gèrent les "programmes" en activité dans ce qu'on appelle des processus. Chaque processus a un numéro de processus (PID). Par ailleurs, il y a des groupes de processus. Chaque processus fait partie d'un groupe de processus. Les groupes de processus ont également des numéros. Même votre script Perl représente, lorsqu'il est exécuté, un tel processus qui fait partie d'un groupe de processus. Pour beaucoup des fonctions décrites ici, vous pouvez adresser le processus actuel, donc celui de votre script Perl par le numéro de processus "virtuel" 0
. Vous pouvez cependant aussi trouver et utiliser le numéro de processus effectif par les variables prédéfinies. Le script suivant expose la mise en œuvre des variables correspondantes:
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Sortie du test</title>\n"; print "</head><body>\n"; print "numéro de processus (PID): <b>$$</b><br>\n"; print "groupe d'utilisateurs réel (GID) du processus: <b>$(</b><br>\n"; print "groupe d'utilisateurs effectif (GID) du processus: <b>$)</b>\n"; print "</body></html>\n"; |
Avec $$
vous adressez le numéro du processus actuel. Le processus tourne sous un certain numéro d'utilisateur qui fait lui-même partie de un ou plusieurs groupes. Si par exemple le script a été lancé avec setgid
, le group-ID réel contient le(s) groupe(s) à partir duquel il a été lancé, le group-ID effectif contient le(s) groupe(s) dans lequel on est passé (le groupe actuel donc). Le script CGI en exemple sort les données correspondantes.
D'autres concepts importants des systèmes d'exploitation Unix auxquels vous avez accès avec les fonctions Perl sont les alarmes, les processus enfants et ce qu'on appelle les canaux de communication (Pipes). Vous trouverez de plus amples informations à ce sujet dans la documentation spécialisée Unix.
Il ne s'agit pas ici à proprement parler d'une fonction Perl, mais d'une forme particulière de règle pour la notation de chaînes de caractères. qx
figure pour quoted executable. La chaîne de caractères qui s'y trouve est simplement transformée par Perl en un appel de la ligne de commande. La sortie standard de la commande appelée, du programme étranger ou du script est capturée et peut être sauvegardée dans une variable. Une autre possibilité de noter cette sorte de chaîne de caractères exécutable, sont ce qu'on appelle les Backticks. Là vous travaillez au lieu de qx(commande quelconque)
avec l'accent grave `
en notant une `commande quelconque`
.
La fonctionnalité de la chaîne de caractères exécutable est extrêmement utile aux les scripts CGI pour leur permettre d'envoyer les sorties d'autres processus au navigateur. Ainsi par exemple des données XML peuvent être transcrites en HTML au moyen de XSLT et d'un processeur XSLT. Quand ce processeur écrit ses résultats sur le canal de sortie standard STDOUT
, le script CGI peut capturer la sortie et l'envoyer au navigateur. C'est ce que montre l'exemple suivant.
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; my $sortie = qx(/usr/bin/saxon /donnees/xml/clients.xml /donnees/xml/clients.xsl); print "$sortie"; |
Il ne faut pas plus que ce script minuscule pour envoyer des données XML sous forme de données HTML à un navigateur Web appelant, dans la mesure ou un processeur XSLT assure le travail de transcription. L'exemple exécute la commande suivante:
/usr/bin/saxon /donnees/xml/clients.xml /donnees/xml/clients.xsl
Ici saxon
est le nom d'un processeur XSLT, donc d'un programme exécutable. Ce programme attend normalement deux paramètres d'appel: en premier la mention d'un fichier XML, et en deuxième la mention d'un fichier XSL qui lui convienne avec les instructions XSLT. Saxon transcrit les marquages XML sur la base des mentions X en constructions HTML et sort le résultat, un fichier HTML complet sur la sortie standard. Le script capture cette sortie standard en la sauvegardant dans la variable $sortie
. Dans cette variable se trouve le contenu complet des données HTML résultant de l'appel de Saxon. Une simple commande print suffit ensuite pour envoyer la totalité des données HTML au navigateur appelant.
Peu importe la façon de mettre entre parenthèses lors de l'utilisation de qx
- Vous pouvez aussi utiliser des crochets, des parenthèses accolades ou des barres obliques - ces dernières étant cependant à déconseiller, parce que beaucoup de commandes nécessitent des mentions de chemin et qu'il vous faudrait alors dans ce cas masquer toutes les barres obliques dans les mentions de chemin.
Dans les mentions de chemin utilisez aussi toujours pour qx(...)
les barres obliques simples - même si le script Perl est exécuté sous Windows/DOS.
Avec des Backticks l'appel de l'exemple ci dessus donnerait:
my $sortie = `/usr/bin/saxon /donnees/xml/clients.xml /donnees/xml/clients.xsl`;
Pour créer des backticks appuyez sur la touche correspondant à l'accent grave, puis sur la barre d'espace.
Dans l'offre en ligne de SELFHTML actuel vous trouverez des liens à Index des liens: logiciels XML. Vous y trouverez aussi des liens à des produits comme Saxon.
La possibilité décrite ici est applicable à toutes les commandes qui écrivent quelque chose sur la sortie standard STDOUT
, donc par exemple également aux commandes du système d'exploitation comme ls
(ou dir
), ou même à d'autres scripts Perl. Certains de ces programmes ou commandes écrivent cependant leur sortie en cas d'erreur lors de l'appel, non pas sur STDOUT
, mais sur STDERR
. Ces sorties ne sont pas capturées par les chaînes de caractères exécutables décrites ici.
Commande spécifique à Unix. fait en sorte que le processus reçoive un SIGALARM après un nombre de secondes déterminé par exemple lorsqu'une commande critique ne fonctionne pas.
Attend comme paramètre:
1. le nombre de secondes après lesquelles l'alarme est active.
Renvoie le nombre de secondes qui sont écoulées.
#!/usr/bin/perl -w use CGI::Carp qw(fatalsToBrowser); print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Sortie du test</title>\n"; print "</head><body><pre>\n"; eval { local $SIG{ALRM} = sub { die "Alarm" }; alarm(2); system("/usr/bin/perl -c /usr/web/myhome/cgi-bin/freelink.pl"); alarm(0); }; if ($@ and $@ !~ /Alarm/) { print "Problème! 2 secondes sont écoulées!\n"; } else { print "Tout est en ordre!\n"; } print "</pre></body></html>\n"; |
L'exemple montre comment vous pouvez traiter un "appel système critique" à l'aide d'une alarme en compte à rebours. Pour ce faire est tout d'abord noté dans le script un bloc eval typique pour ce genre de traitement. Y est défini un sous-programme de traitement pour SIGALARM avec l'instruction typique:
local $SIG{ALRM} = sub { die "Alarm" };
. Ensuite, un compte à rebours de 2 secondes est défini avec alarm(2)
, avant que l'alarme soit active. Avec alarm(0)
l'alarme est à nouveau initialisée.
Il est ensuite tenté avec system d'appeler l'interpréteur Perl, à savoir de telle façon qu'il vérifie la syntaxe d'un script déterminé. Si cette opération devait durer plus de 2 secondes, l'alarme est active.
Avec la requête if ($@ and $@ !~ /Alarm/)
il est vérifié si l'alarme a été active. Si oui, un message correspondant est sorti. Dans l'embranchement else
peut figurer du code qui est exécuté quand tout était en ordre. Dan l'exemple est simplement sorti un message correspondant.
Des appels avec system ou qx(...) en relation avec alarm
peuvent mener à ce qu'on appelle des zombies. Il est possible que, pour faire ce genre de choses , vous dussiez implémenter vous même ces appels à l'aide de fork et exec.
Lance un autre processus et met fin au script actuel. Le processus actuel est ici remplacé entièrement par un nouveau processus. Quand vous ne vous voulez pas mettre fin au script actuel, Utilisez system, qx(...) ou bien open avec l'opérateur de dérivation de données |
.
Attend comme paramètre:
1. appel de la commande du programme désiré,
2. jusqu'à n. (facultatif) liste de paramètres d'appel.
#!/usr/bin/perl -w exec("/usr/bin/perl","mystats.pl") if -e "mystats.pl"; |
L'exemple demande à l'aide d'un opérateur de test fichier pour fichiers et répertoires -e
si un fichier du nom de mystats.pl
existe dans le répertoire actuel. Si oui, l'interpréteur Perl est lancé (dans un nouveau processus distinct) et exécute mystats.pl
.
Commande spécifique à Unix. Crée une copie du processus actuel qui est subordonnée au processus actuel géniteur. Un script Perl peut ainsi traiter des données dans deux processus différents. Les deux processus peuvent ici accéder à tous les fichiers ouverts. Tout le reste comme les variables etc... est copié par le processus parent dans le processus enfant. La variable qui sauvegarde la valeur renvoyée par fork
a cependant une valeur dans le processus parent, à savoir le numéro de processus du processus enfant, tandis qu'elle a dans le processus enfant la valeur 0
.
N'attend aucun paramètre.
Renvoie le numéro de processus affecté par le système d'exploitation au processus enfant.
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); $| = 1; print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Sortie du test</title>\n"; print "</head><body>\n"; my $pid_parent = $$; my $pid_enfant = fork(); if($pid_enfant) { print "<p>Ceci est le processus parent. le processus enfant a le PID <b>$pid_enfant</b></p>\n"; wait; } else { my $pid_parent = getppid(); print "<p>Ceci est le processus enfant. le processus parent a le PID <b>$pid_parent</b></p>\n"; exit(0); } print "</body></html>\n"; |
L'exemple crée avec fork
un processus enfant. La valeur renvoyée, le numéro du processus enfant, est sauvegardée dans la scalaire $pid_enfant
. Dans l'exemple est ensuite notée une requête if
. Avec if($pid_enfant)
il est demandé si la scalaire $pid_enfant
a une valeur différente de 0
. Si c'est le cas, des instructions relevant du processus parent sont exécutées. Dans l'exemple, un message est sorti pour annoncer que le script se trouve dans le processus parent. Par ailleurs, le numéro de processus du processus enfant est sorti. Ensuite, l'instruction wait permet d'attendre que le processus enfant soit terminé. Dans l'embranchement else
dans lequel le script aboutit quand pid_enfant
a pour valeur 0
, il est sorti par contre que le processus enfant est actif. Par ailleurs, le numéro de processus du processus parent est sorti. Ensuite, le processus enfant est terminé avec l'instruction exit(0);
. Le processus parent qui n'attendait que ça, sort encore la dernière ligne de code HTML.
La conduite particulière du script qui tourne dans deux processus est mise en évidence dans l'exemple en ce que tant l'embranchement if
que l'embranchement else
sont exécutés. L'explication en est que la condition if
est vraie pour le processus parent, et que l'alternative else
l'est par contre pour le processus enfant.
Commande spécifique à Unix.
Attend comme paramètre:
1. un numéro de processus dont le groupe de processus correspondant doit être recherché. Pour rechercher le numéro de groupe du processus actuel, transmettre 0
.
Renvoie le numéro de groupe.
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Sortie du test</title>\n"; print "</head><body>\n"; my $numero_groupe = getpgrp(0); print "Le numéro du groupe de processus du processus actuel est <b>$numero_groupe</b>\n"; print "</body></html>\n"; |
L'exemple recherche le numéro de groupe du processus actuel avec getpgrp
, envoie du code HTML au navigateur et sort le numéro trouvé.
Commande spécifique à Unix.
N'attend aucun paramètre.
Renvoie le numéro de processus du processus parent du script actuel.
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Sortie du test</title>\n"; print "</head><body>\n"; my $pid_parent = getppid(); print "Le PID du processus parent est <b>$pid_parent</b>\n"; print "</body></html>\n"; |
L'exemple recherche le PID du processus parent avec getppid
, envoie du code HTML au navigateur et sort le numéro trouvé.
Commande spécifique à Unix. Recherche la priorité actuelle d'un processus, d'un groupe de processus ou d'un utilisateur. Les processus avec une priorité haute reçoivent sous le processus actuellement en cours, plus de ressources système pour leur exécution.
Attend comme paramètre:
1. une mention exprimant si vous voulez rechercher la priorité pour un processus déterminé, un groupe de processus ou un utilisateur. Pour ce faire transmettez pour le mieux une des constantes qui sont définies dans resources.ph
(voir plus bas).
2. le numéro du processus, du groupe de processus ou de l'utilisateur.
Renvoie la priorité du processus, du groupe de processus ou de l'utilisateur en tant que nombre. La plage de valeurs possibles dépend du système.
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Sortie du test</title>\n"; print "</head><body>\n"; require "resource.ph"; my $Prio = getpriority(&PRIO_PROCESS,0); print "Priorité du processus actuel: $Prio\n"; print "</body></html>\n"; |
L'exemple recherche avec getpriority
la priorité du processus actuel et sort celle-ci. Pour ce faire est incorporé avec require "resource.ph"
le fichier d'entête qui contient la définition des constantes suivantes:
|
En la faisant précéder du signe &
vous pouvez transmettre l'une des constantes comme premier paramètre, comme dans l'exemple.
Cette fonction conduit à une erreur grave quand le système ne connaît pas la gestion de processus ou d'utilisateurs telle que la comprend Unix.
Commande spécifique à Unix. Grâce à cette commande, vous pouvez, à partir d'un script Perl, envoyer des signaux à d'autres processus qui tournent sur l'ordinateur et par là même, influencer ceux-ci. Ce qui est intéressant avant tout quand vous créez dans votre script Perl vos propres processus enfants (voir fork). Les processus parent et enfant peuvent alors communiquer par des signaux.
Attend comme paramètre:
1. Numéro ou nom d'une constante (voir le tableau ci-dessous) du signal désiré (ou transmettre 0
pour trouver si le processus, dont le numéro de processus suit dans la transmission, est encore "en vie"),
2. à n. un ou plusieurs processus auxquels le signal doit être envoyé.
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); $| = 1; print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Sortie du test</title>\n"; print "</head><body>\n"; my $pid_enfant = fork(); if(kill(0,$pid_enfant)) { print "<p>Ici un processus s'annonce</p>\n"; kill("KILL",$pid_enfant); } print "</body></html>\n"; |
L'exemple génère un processus enfant avec fork . Il est demandé si ce processus est encore en vie avec if(kill(0,$pid_enfant))
. Si oui,, une sortie signale qu'un processus s'annonce. Étant donné que dans l'exemple aucun code Perl distinct n'est noté pour le processus enfant et que les processus enfants copient d'abord tout de leurs processus parents, les deux processus s'annonceraient et sortiraient Ici un processus s'annonce
. Dans l'exemple, cela est cependant empêché par le fait que le processus parent tue le processus enfant avec kill("KILL",$pid_enfant)
avant que celui-ci ne puisse exécuter l'instruction avec la sortie du message. Le message n'est donc sorti qu'une seule fois en tout et pour tout.
Le tableau suivant contient les signaux typiques avec leur nom tels qu'ils peuvent être transmis comme premier paramètre à kill
. Il n'y a aucune garantie que tous les signaux dont la liste est dressé ici fonctionnent sur chaque ordinateur en Perl. Même les numéros correspondants ont été laissés de côté ici, étant donné qu'ils peuvent varier d'un système à l'autre. Finalement c'est en fin de compte toujours ce qui est défini dans le fichier /usr/include/signal.h
de l'ordinateur concerné qui l'emporte.
|
Avec le script suivant, vous pouvez questionner votre ordinateur serveur pour connaître quels signaux y sont configurés sous quel numéro de signal:
#!/usr/bin/perl use Config; defined $Config{sig_name} || die "Pas de module de configuration?"; foreach $name (split(' ', $Config{sig_name})) { $i++; printf "%3d) %s \t", $i, $name; if (($i % 5) == 0) { print "\n"; } } print "\n"; |
Commande spécifique à Unix. Permet à deux processus de communiquer entre eux. Un "canal" (Pipe) est ici le canal de communication pour les deux processus. Il existe un canal pour l'écriture de données et un autre pour la lecture de données. Il y a un "descripteur" pour chacun de ces deux canaux. Ces descripteurs de lecture et d'écriture sont tout à fait semblables aux descripteurs de fichiers. Il est courant qu'un canal soit ouvert avant même qu'un processus enfant soit créé avec fork. Les processus parent et enfant peuvent ainsi échanger des données par le canal ouvert.
Attend comme paramètre:
1. le nom d'un descripteur de lecture (peut être attribué librement),
2. le nom d'un descripteur d'écriture (peut être attribué librement)
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); $| = 1; print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Sortie du test</title>\n"; print "</head><body><pre>\n"; pipe(DESCRIPTEUR_LECTURE, DESCRIPTEUR_ECRITURE); my $pid_enfant = fork(); if ($pid_enfant) { close(DESCRIPTEUR_LECTURE); my $old_handle = select(DESCRIPTEUR_ECRITURE); $| = 1; for (my $i=1;$i<=5;$i++) { sleep(1); print DESCRIPTEUR_ECRITURE "$i (envoyé par le processus parent)\n"; } close(DESCRIPTEUR_ECRITURE); wait; select($old_handle); } else { close(DESCRIPTEUR_ECRITURE); my $memoire; while(defined($memoire = <DESCRIPTEUR_LECTURE>)) { print "Lu: $memoire \n"; } exit(0); } print "</pre></body></html>\n"; |
L'exemple crée un canal avec pipe
. Par les deux noms de descripteur transmis DESCRIPTEUR_LECTURE
et DESCRIPTEUR_ECRITURE
un échange de messages est ensuite possible entre deux processus. Le script génère un processus enfant à l'aide de fork . Le processus parent tourne dans l'embranchement if
du code qui suit, le processus enfant dans l'embranchement else
. Lors de la création du processus enfant, tout est copié exceptés les deux descripteurs du canal. Ceux-ci ne sont pas copiés, restent il est vrai disponibles pour les deux processus. C'est pourquoi chacun des deux processus doit d'abord fermer le descripteur dont il n'a pas besoin avec close. Pour pouvoir basculer la mise en mémoire tampon des données, il faut en outre, dans l'embranchement if
choisir le descripteur d'écriture avec select. Toutes les instructions que ce soit dans l'embranchement if
ou même dans l'embranchement else
sont exécutées cinq fois en tout. Car dans une boucle for, qui compte de 1 à 5, le processus parent écrit l'état actuel du compteur dans le descripteur d'écriture, après qu'il a attendu une seconde pour les raisons du test (voir sleep). Le processus enfant peut lire ces données dans l'embranchement else
en employant une boucle while où il lit le descripteur de lecture. Pour le contrôle, le processus enfant sort ce qu'il a lu.
Commande spécifique à Unix. Affecte un processus à un groupe de processus.
Attend comme paramètre:
1. le numéro de processus (PID) du processus souhaité (transmettre 0
pour le processus actuel),
2. le numéro du groupe de processus auquel ce processus doit être affecté ((transmettre 0
pour le groupe de processus actuel).
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Sortie du test</title>\n"; print "</head><body>\n"; my $ancien_groupe = getpgrp(0); print "ancien groupe de processus: <b>$ancien_groupe</b><br>\n"; setpgrp(0,0); my $nouveau_groupe = getpgrp(0); print "ancien groupe de processus: <b>$nouveau_groupe</b>\n"; print "</body></html>\n"; |
L'exemple affecte le processus actuel au groupe de processus actuel et génère ainsi son propre groupe de processus. Pour permettre de comparer, le groupe de processus est lu et sorti respectivement avant et après.
Commande spécifique à Unix. Fixe la priorité d'un processus, d'un groupe de processus ou d'un utilisateur. Les processus avec un degré de priorité plus élevé reçoivent sous le processus actuellement en cours plus de ressources système pour leur exécution.
Étant donné que cette fonction est "critique pour le système", elle n'est disponible sur la plupart des systèmes Unix, que pour les utilisateurs disposant d'une identification racine.
Paramètres comme pour getpriority
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Sortie du test</title>\n"; print "</head><body>\n"; require "resource.ph"; my $Prio = getpriority(&PRIO_PROCESS,0); $Prio += 1; setpriority (&PRIO_PROCESS, 0, $Prio); print "Nouvelle priorité du processus actuel: $Prio\n"; print "</body></html>\n"; |
L'exemple lit la priorité du processus actuel avec getpriority
, augmente ensuite celle-ci de 1 et fixe alors la nouvelle valeur avec setpriority
. Pour le contrôle, le script sort la valeur actuelle de la priorité.
Cette fonction conduit à une erreur grave quand le système ne connaît pas la gestion de processus ou d'utilisateurs telle que la comprend Unix.
Arrête l'exécution du script pour un certain nombre de secondes avant de poursuivre.
Attend comme paramètre:
1. le nombre de secondes que doit durer la pause. Quand rien n'est mentionné, la pause dure "éternellement".
#!/usr/bin/perl -w use strict; sleep(10); exec("/usr/bin/perl","reveil.pl"); |
L'exemple attend 10 secondes par un appel de sleep(10)
et exécute ensuite un autre script avec exec.
Appelle un autre programme et recherche la valeur qu'il renvoie. Quand vous êtes intéressé par les sorties générées par l'autre programme, vous devez utiliser la fonction open avec le signe |
ou qx(...) ou encore `...`
(Backticks).
Attend comme paramètre:
1. une chaîne de caractères ou une liste. Si plusieurs paramètres sont transmis, donc une liste, le premier paramètre est interprété comme programme ou commande à exécuter et les autres paramètres comme paramètres transmis au programme ou à la commande.
Renvoie la valeur retournée par le programme ou la commande exécutés.
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); (my $fichier_1, my $fichier_2) = split(/&/,$ENV{'QUERY_STRING'}); my $fichier_chemin_1 = "/usr/web/daten/ancien/".$fichier_1; my $fichier_chemin_2 = "/usr/web/daten/nouveau/".$fichier_2; my $comparaison = system("cmp $fichier_chemin_1 $fichier_chemin_2 >/dev/null"); print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Sortie du test</title></head><body>\n"; if($comparaison == 0) { print "<tt>$fichier_chemin_1</tt><br>et<br><tt>$fichier_chemin_2</tt><br><b>sont identiques!</b>!\n"; } else { print "<tt>$fichier_chemin_1</tt><br>et<br><tt>$fichier_chemin_2</tt><br><b>sont différents!</b>!\n"; } print "</body></html>\n"; |
Le script en exemple recherche le contenu de la variable d'environnement CGI QUERY_STRING
, y recherche un ET commercial (&
) et sépare la partie qui le précède de celle qui lui succède dans les scalaires $fichier_1
et $fichier_2
. Les deux données sont interprétées comme fichiers. Un appel en exemple du script pourrait être:
/cgi-bin/script.pl?nouveautes.htm&nouveautes.htm
Le script accroche les deux fichiers du même nom à différents noms de chemin sur le serveur en créant ainsi deux mentions différentes de chemin de fichier dans les scalaires $fichier_chemin_1
et $fichier_chemin_2
. Avec system
la commande de ligne de commande cmp
(sous Unix) est lancée, et vérifie si les deux fichiers sont identiques. Les deux scalaires sont transmises à la commande avec les mentions de chemin. Si c'est le cas, la commande ne doit pas créer de sortie. C'est la raison pour laquelle sa sortie est déviée vers /dev/null
. La valeur renvoyée par l'appel de system
et par là même par la commande cmp
est cependant sauvegardée, à savoir dans la scalaire $comparaison
. Quand la valeur est 0
les fichiers comparés sont identiques, sinon ils sont différents. Cette information est renvoyée au navigateur appelant.
Recherche la durée d'activité d'un processus (et s'il y en a de ses processus enfants) depuis la création jusqu'à l'exécution de cet appel times
. Deux valeurs sont recherchées pour chaque processus: "user time" et "system time". Alors que "user time" désigne depuis combien de temps le processus lui-même est en cours, "system time" mentionne depuis combien de temps le processus occupe le système d'exploitation. La somme des deux durées est la durée totale d'utilisation du CPU.
Les temps mesurés se basent sur le cadencement. Le cadencement par seconde est réglable sur les systèmes Unix (TICKSPERSEC
dans le fichier conf.h
).
N'attend aucun paramètre.
Renvoie une liste avec les durées d'exécution en secondes (nombres à virgules flottante, avec mention des fractions de secondes) . Schéma:
($user_time,$system_time[,$user_time_enfant,$system_time_enfant,...])
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); my $x; for(my $i = 0; $i < 1000; $i++) { for(my $k = 0; $k < 100; $k++) { $x = $i * $k / time(); } } my ($duree_systeme, $duree_utilisateur) = times(); my $duree_CPU = $duree_systeme + $duree_utilisateur; print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Sortie du test</title>\n"; print "</head><body>\n"; print "durée système utilisée: <b>$duree_systeme</b> secondes<br>\n"; print "durée utilisateur utilisée: <b>$duree_utilisateur</b> secondes<br>\n"; print "durée CPU utilisée: <b>$duree_CPU</b> secondes\n"; print "</body></html>\n"; |
L'exemple contient deux boucles for imbriquées dans lesquelles beaucoup de calculs sont à faire (ce sont en tout 100.000 appels de la fonction time et autant de calculs de nombres fractionnaires qui sont exécutés). Ensuite, l'exemple recherche les nombres nécessaires. Les deux premiers éléments de liste de l'appel de la fonction times
à savoir ceux pour le processus actuel, sont sauvegardés dans les scalaires $duree_systeme
et $duree_utilisateur
. À partir de la somme de ces deux durées est déduite la durée CPU qui est sauvegardée dans $duree_CPU
. Pour le contrôle, le script sort les durées trouvées.
Commande spécifique à Unix.
N'attend aucun paramètre.
#!/usr/bin/perl -w #use strict; use CGI::Carp qw(fatalsToBrowser); $| = 1; print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Sortie du test</title>\n"; print "</head><body>\n"; my $pid_enfant = fork(); if($pid_enfant) { print "<p>Ici c'est le processus parent.</p>\n"; wait(); print "<p>Le processus enfant est terminé.</p>\n"; } else { print "<p>Ici c'est le processus enfant.</p>\n"; exit(0); } print "</body></html>\n"; |
L'exemple crée un processus enfant avec fork. Il est demandé avec if($pid_enfant)
si la scalaire $pid_enfant
a une valeur différente de 0
. Si c'est le cas, des instructions sont exécutées qui relèvent du processus parent. Dans l'exemple un message est sorti selon lequel le script se trouve dans le processus parent. Dans l'embranchement else
dans lequel le script aboutit quand la valeur de pid_enfant
égale 0
, il est sorti que le processus enfant est actif.
En principe c'est d'abord l'embranchement if
qui est traité puis l'embranchement else
. Par l'instruction wait()
de l'embranchement if
, le processus parent attend cependant la fin du processus enfant avant de poursuivre. Ainsi, l'embranchement else
est traité auparavant et ensuite, le dernier message de l'embranchement if
est sorti.
Commande spécifique à Unix. Appelle directement le système d'exploitation à la différence de wait.
Attend comme paramètre:
1. le numéro de processus (PID) du processus enfant souhaité.
2. interrupteur (drapeaux - voir tableau ci-dessous)
Renvoie le numéro de processus (PID) du processus arrêté ou -1
, si le processus enfant souhaité n'existe pas ou n'existe plus. Sur certains systèmes la valeur renvoyée 0
est elle aussi possible - elle signifie que le processus enfant tourne encore toujours (c'est à dire un compte à rebours lors de l'attente a été dépassé).
#!/usr/bin/perl -w #use strict; use CGI::Carp qw(fatalsToBrowser); use POSIX; $| = 1; print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Sortie du test</title>\n"; print "</head><body>\n"; my $pid_enfant = fork(); if($pid_enfant) { print "<p>Ici c'est le processus parent.</p>\n"; use POSIX ":sys_wait_h"; do { my $pid_enfant = waitpid(-1,&WNOHANG); } until $pid_enfant == -1; print "<p>Le processus enfant est terminé.</p>\n"; } else { print "<p>Ici c'est le processus enfant.</p>\n"; exit(0); } print "</body></html>\n"; |
L'exemple fait la même chose que celui de wait. Dans le cas présent toutefois, il est attendu avec une boucle do-until jusqu'à ce que le processus enfant soit fini. C'est le cas quand la fonction waitpid
retourne la valeur -1
, le processus enfant n'existe lors donc plus.
À la fonction waitpid
le drapeau &WNOHANG
est transmis dans l'exemple. Les constantes pour le faire sont définies dans le module standard POSIX
. C'est pourquoi il est indispensable d'incorporer ce module comme dans l'exemple avec use POSIX ":sys_wait_h"
.
Le tableau suivant dresse la liste des drapeaux pouvant être transmis à cet endroit.
|
Fonctions pour les informations tirées des fichiers de configuration | |
Fonctions pour la gestion de fichiers et de répertoires | |
SELFHTML/Aides à la navigation CGI/Perl Fonctions Perl |
© 2001 Stefan Münz / © 2003 Traduction Serge François, 13405@free.fr
selfhtml@fr.selfhtml.org