Le SAPI CLI : PHP en ligne de commande


Depuis la version 4.3.0, PHP supporte un nouveau SAPI (acronyme pour Server Programming Interface) nomme communément CLI (Command Line Interface) qui, comme son nom l’indique, se concentre sur le développement d’applications Shell avec PHP.Les Scripts PHP ne seraient plus exécutées uniquement via un navigateur, mais directement depuis la ligne de commande d’un serveur, ce qui ouvre la porte a plusieurs opportunités.

On peut utiliser PHP CLI dans les crons, les traitements par lots (Batch), si on veut gérer / controler des processus ou si on veux faire du chaînage de commandes sur linux via les pipes.

Principes de base

Chaque script CLI est appelé via le binaire PHP. les arguments passés au script sont interprétés via des variables spéciales dans php. Aussi l’input peut être passé via STDIN, les outputs retournées dans STDOUT, et les erreurs dans STDERROR. Ce qui rend le piping possible.

Arguments

Par exemple :

$ php cli.php arg1 arg2

Il est possible de récupérer les arguments avec $_SERVER, similairement a un shell script:
• $_SERVER[‘argc’] représente le nombre d’arguments
• $_SERVER[‘argv’][0] est le premier paramètre (qui est le nom du script) (cli.php)
• $_SERVER[‘argv’][1] est le premier argument (arg1)
• $_SERVER[‘argv’][2] est le deuxième arguments (arg2)

Aussi, si ‘register_argc_argv’ est activée, il sera possible d’utiliser plutôt les variables $argc, $argv, $argv[0] etc.

Une autre facon est de récupérer les arguments est d’utiliser getopt() :
la fonction getopt() récupère les valeurs des arguments en se basant sur les options suivantes :
• des caractères individuels
• pour les caractères suivis par “deux points” la valeur est requise
• pour les caractères suivis par deux “deux points” la valeur est optionnelle
• les options longues sont bien supportées dans PHP 5.3
Exemple

$options = getopt(‘ab:c::’);

Exemples

Lire depuis STDIN en ouvrant un flux (stream)

$handle!=fopen('php://stdin','r');

Lire une ligne depuis STDIN

$stdin!=trim(fgets(STDIN));

Ecrire dans STDOUT en ouvrant un flux

$handle!=fopen('php://stdout','w');

Ecrire une ligne dans STDOUT

fwrite(STDOUT,‘output’);

Utiliser STDIN, STDOUT et STDERR avec les flux permet a vos scripts d’être utilisés avec les pipes unix :

$ cat input.ext | php myScript.php > output.ext
$ php myScript.php | grep filterText > output.ext

Vous pouvez aussi utiliser des arguments

$ php myScript.php arg1 arg2 > output.ext
$ cat input.ext | php myScript.php arg1 arg2 arg3 | grep

Apache versus CLI

Apache CLI
• Apache utilise le protocole HTTP qui est un protocole sans état
• L’interactivité est limitée
• Les sessions et les cookies sont une solution pour ces limitations
• Timeout d’exécution possibles
• Taille de paquets limitée
• L’état est contrôlable
• Plus d’interactivité
• Pas besoin de sessions

Lorsque vous developpez des scripts en CLI, il faut “oublier” la mentalité Apache. N’utilisez pas les sessions ou les cookies, utilisez plutôt des variables locales. N’utilisez pas $_GET / $_POST, lisez plutôt vos entrées avec getopt() ou $_SERVER[‘argc’] et $_SERVER[‘argv’]. Si vous exécutez un script CLI avec votre navigateur, la sortie sera affichée parceque les sorties CLI sont groupées aussi avec Apache. Pretez aussi attention avec les chemins relatifs et utilisez toujours dirname(__FILE__) ou chdir() parceque CLI ne change pas automatiquent de répertoire de travail.

Les options CLI

Usage: php [options] [-f]  [--] [args...]
       php [options] -r  [--] [args...]
       php [options] [-B ] -R  [-E ] [--] [args...]
       php [options] [-B ] -F  [-E ] [--] [args...]
       php [options] -- [args...]
       php [options] -a
  -a               Run interactively
  -c
| Look for php.ini file in this directory
  -n               No php.ini file will be used
  -d foo[=bar]     Define INI entry foo with value 'bar'
  -e               Generate extended information for debugger/profiler
  -f         Parse and execute .
  -h               This help
  -i               PHP information
  -l               Syntax check only (lint)
  -m               Show compiled in modules
  -r         Run PHP  without using script tags 
  -B   Run PHP  before processing input lines
  -R         Run PHP  for every input line
  -F         Parse and execute  for every input line
  -E     Run PHP  after processing all input lines
  -H               Hide any passed arguments from external tools.
  -s               Display colour syntax highlighted source.
  -v               Version number
  -w               Display source with stripped comments and whitespace.
  -z         Load Zend extension .
  args...          Arguments passed to script. Use -- args when first argument
                   starts with - or script is read from stdin
  --ini            Show configuration file names
  --rf       Show information about function .
  --rc       Show information about class .
  --re       Show information about extension .
  --ri       Show configuration for extension .

voici une explication de quelques options :
• option binaire -r : parse et exécute le code PHP qui est passé en argument

$ php -r “echo \"un exemple de sortie\";” 
un exemple de sortie 
$

• Mode interactif -a : exécute le code PHP interactivement en ligne de commande. ceci requiert que PHP soit compilé avec readline

$ php -a 
$ php > echo "un exemple interactif"; 
un exemple interactif 
$ php>

• définition de variable de configuration -d : définit une configuration ini a l'exécution

$ php -d max_execution_time=25 -r “echo ini_get("max_execution_time");” 
25 
$ 

• Analyse syntaxique Lint -l : execute un test lint sur un fichier php pour valider la syntaxe du script. les erreurs sont affichées via STDOUT. Le shell retourne un code 0 ou 1. par ailleurs, cette option ne peut pas être combinée avec l'option -r. Aussi, lint ne détecte pas les erreurs fatales (fonction indéfinie par exemple), il exécute une analyse syntaxique seulement.

• Afficher la version de PHP -v

$ php -v 
PHP 5.2.8 (cli) (built: Feb  5 2009 21:21:13) 
Copyright (c) 1997-2008 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2008 Zend Technologies 
with Xdebug v2.0.3, Copyright (c) 2002-2007, by Derick Rethans 
$

Exemple de scripts CLI

Lecture de STDIN et sortie Distribuée

 0)
   { 
     echo "$line# $input".PHP_EOL; 
   }
   else
   { 
     break; 
   } 
}
while (true);

résultat

$ php cli.php 
et 
1# et 
voila 
2# voila 

$

Passage d'arguments


résultat

$ php cli.php --arg1 -arg2 --option1=value1 argumentSansNom 
Key: flag1 - Value: 1 
Key: flag2 - Value: 1 
Key: option1 - Value1 
Key: 5 - Value: argumentSansNom 
$ 

Exécuter avec le shell

#!/usr/bin/php 

par la suite

$ chmod +x ./script.php
$ ./script
L'heure courante est 18:30:07

conclusion

Le SAPI CLI de PHP est une alternative extrêmement intéressante dans le cas d'exécution de scripts démons. Aussi, ce SAPI permet de gérer l'exécution de multi-processus dans un environnement UNIX avec PCNTL. Ceci va être couvert dans mon prochain article.

Anis Berejeb

Anis est avant tout un passioné de l'agilité et du développement. Avec plus de 15 ans dans le domaine du développement web, son expertise combine des connaissances accrues dans l'ensemble des notions partant du développement logiciel jusqu'à l'organisation des équipes dans les environnements agiles à grande échelle.

You may also like...

  • Merci pour l’article tu fais bien d’insister sur l’utilisation des chemins relatifs, surtout lorsqu’il s’agit d’utiliser des Crons.

    Bonne continuation 😉

  • Pingback: Anis Berejeb » La gestion multi-processus dans PHP avec PCNTL et POSIX()

  • Pingback: Anis Berejeb » Générer vos diagrammes UML depuis votre source PHP avec PHP2XMI()

  • Tres bon article ! exactement ce que je cherchais… merci ! 😉

  • Comment faire lorsque l’on a deux options à ajouter :

    /usr/local/bin/php -d “memory_limit=512M” -d short_open_tag=on script.php

    ou

    /usr/local/bin/php -d “memory_limit=512M” , “short_open_tag=on” script.php

    ou

    /usr/local/bin/php -d memory_limit=512M short_open_tag=on script.php

    Merci de votre aide

  • admin

    $ php -d max_execution_time=20 -r ‘$foo = ini_get(“max_execution_time”); var_dump($foo);’
    $ string(2) “20”

    // si je mets une erreur (ini_gett) pour provoquer une erreur
    $ php -d max_execution_time=20 -r ‘$foo = ini_gett(“max_execution_time”); var_dump($foo);’
    Fatal error: Call to undefined function ini_gett() in Command line code on line 1

    // et si je ne veux pas afficher les erreurs
    $ php -d max_execution_time=20 -d display_errors=false -r ‘$foo = ini_gett(“max_execution_time”); var_dump($foo);’
    // ca n’affiche rien