CLI, the other SAPI phpnw11

  • 3,061 views
Uploaded on

Slides for my PHPNW11 talk about the command line interface SAPI for PHP

Slides for my PHPNW11 talk about the command line interface SAPI for PHP

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
3,061
On Slideshare
0
From Embeds
0
Number of Embeds
9

Actions

Shares
Downloads
22
Comments
0
Likes
5

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. CLI,  the  other  SAPI phpThijs  FerynEvangelist+32  (0)9  218  79  06thijs@combellgroup.com
  • 2. About  me I’m  an  Evangelist  at  Combell
  • 3. About  me I’m  a  board  member  at  PHPBenelux
  • 4. Follow  me  on  Twi+er:  @ThijsFerynGive  me  feedback:  h+p://joind.in/3596
  • 5. SAPI? The  way  you  interact  with  PHP
  • 6. Common  SAPIs
  • 7. Common  SAPIs • Apache/Apache  2 • FPM • FastCGI • ISAPI • CLI • GTK
  • 8. The  CLI  SAPIPHP  script  execuWon  via  the  command  line  interface
  • 9. When  to  use
  • 10. When  to  use• In  crons• For  batch  tasks• For  worker  processes• Daemons• Process  control• InteracWon  with  other  binaries
  • 11. CLI 101
  • 12. CLI 101The PHP binaryPassing argumentsReading from STDINI/O with pipes
  • 13. CLI 101Invoking a script with the PHP binaryphp  file.php
  • 14. CLI 101 Passing argumentsphp  file.php  arg1  arg2
  • 15. CLI 101 interpreting arguments<?phpecho "Number of arguments {$argc}n";foreach($argv as $key=>$argument){    echo "Argument # {$key}: {$argument}n"; }
  • 16. CLI 101 interpreting arguments Argument   Argument   count array<?phpecho "Number of arguments {$argc}n";foreach($argv as $key=>$argument){    echo "Argument # {$key}: {$argument}n"; }
  • 17. CLI 101 The   PHP  file  is  an  interpreting arguments argument  too$  php  args.php  arg1  arg2Number  of  arguments  3Argument  #  0:  args.phpArgument  #  1:  arg1Argument  #  2:  arg2$
  • 18. CLI 101 interpreting arguments$_SERVER[‘argc’] $argc$_SERVER[‘argv’] $argv !!! register_argc_argv !!!
  • 19. CLI 101 getopt<?php$arguments = getopt(ab:c::);var_dump($arguments);
  • 20. CLI 101 getopt OpWonal   Flag   (no  value) value<?php$arguments = getopt(ab:c::);var_dump($arguments); Required   value
  • 21. CLI 101php  getopt.php  -­‐a  -­‐b  2  -­‐c3array(3)  {    ["a"]=> No      bool(false)    ["b"]=> spacing  for      string(1)  "2" opWonal      ["c"]=> arguments    string(1)  "3"}
  • 22. CLI 101 getopt: longopts<?php$arguments = getopt(,array(arg1,arg2:,arg3::));var_dump($arguments);
  • 23. CLI 101php  getopt2.php  -­‐-­‐arg1  -­‐-­‐arg2  123  -­‐-­‐arg3=xarray(3)  {    ["arg1"]=>    bool(false) Mind      ["arg2"]=> the  “=”  sign    string(3)  "123"    ["arg3"]=>    string(1)  "x"}
  • 24. CLI 101 REading From STDIN<?php$handle = fopen(php://stdin,r);while(!feof($handle)){    $line = trim(fgets($handle));    if(strlen($line) > 0){        echo strrev($line).PHP_EOL;    }}fclose($handle);
  • 25. CLI 101$  cat  test.txt  |  php  stdin.php  enOowTeerhT$
  • 26. CLI 101$  cat  test.txt  |  php  stdin.php  enOowT Output   Convert  eerhT$ file output  to   input  with   pipes
  • 27. Comparing  the  Apache  &  CLI  SAPI
  • 28. Comparing  the  Apache  &  CLI  SAPI Web  based  SAPI’s• HTTP  is  a  stateless  protocol• Request/response  based• Limited  interacWon• Sessions  &  cookies  as  workaround• ExecuWon  Wmeouts• Limited  request/response  size
  • 29. Comparing  the  Apache  &  CLI  SAPI CLI  SAPI• Controlable  state• Controlable  script  execuWon• ConWnuous  interacWon• No  need  for  sessions• No  execuWon  Wmeouts
  • 30. The  PHP  binary php
  • 31. The  PHP  binaryUsage:  php  [options]  [-­‐f]  <file>  [-­‐-­‐]  [args...]              php  [options]  -­‐r  <code>  [-­‐-­‐]  [args...]              php  [options]  [-­‐B  <begin_code>]  -­‐R  <code>  [-­‐E  <end_code>]  [-­‐-­‐]  [args...]              php  [options]  [-­‐B  <begin_code>]  -­‐F  <file>  [-­‐E  <end_code>]  [-­‐-­‐]  [args...]              php  [options]  -­‐-­‐  [args...]              php  [options]  -­‐a
  • 32. InteracMve  mode  (-­‐a) $  php  -­‐a Interactive  shell php  >  echo  5+8; 13 php  >  function  addTwo($n) php  >  { php  {  return  $n  +  2; php  {  } php  >  var_dump(addtwo(2)); int(4) php  >
  • 33. InteracMve  mode  (-­‐a) $  php  -­‐a Tab   Interactive  shell compleWon php  >  stri[TAB][TAB] strip_tags          stripcslashes     stripslashes      stristr                 stripos                 php  >  stri
  • 34. Run  code  (-­‐r) $  php  -­‐r  "echo  date(Y-­‐m-­‐d  H:i:s);" 2011-­‐03-­‐02  22:04:45 $
  • 35. Config  directory  (-­‐c) $  php  -­‐c  /custom/dir/php.ini  script.php
  • 36. Define  custom  INI  seSng  (-­‐d) $  php  -­‐d  max_execution_time=20  -­‐r  $foo  =   ini_get("max_execution_time");   var_dump($foo); string(2)  "20" $
  • 37. Get  INI  informaMon  (-­‐i) Filtering   items $  php  -­‐i  |  grep  “log_” define_syslog_variables  =>  Off  =>  Off log_errors  =>  On  =>  On log_errors_max_len  =>  1024  =>  1024 $
  • 38. Syntax/lint  check  (-­‐l) Only   checks  parse   errors $  php  -­‐l  myFile.php No  syntax  errors  detected  in  myFile.php $
  • 39. Module  list  (-­‐m) $  php  -­‐m [PHP  Modules] bcmath bz2 calendar Core ctype curl date dba $
  • 40. Syntax  highlighMng  (-­‐s)<?phpecho  "Hello  world";$  php  -­‐s  helloworld.php  >  helloworld.html$
  • 41. Syntax  highlighMng  (-­‐s)<code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /></span><span style="color:#007700">echo&nbsp;</span><spanstyle="color:#DD0000">"Hello&nbsp;world"</span><spanstyle="color: #007700">;</span></span><?phpecho "Hello world";
  • 42. Version  info  (-­‐v) $  php  -­‐v PHP  5.3.3-­‐1ubuntu9.3  with  Suhosin-­‐Patch   (cli)  (built:  Jan  12  2011  16:07:38)   Copyright  (c)  1997-­‐2009  The  PHP  Group Zend  Engine  v2.3.0,  Copyright  (c)  1998-­‐2010   Zend  Technologies $
  • 43. FuncMon  reflecMon  (-­‐-­‐rf)$  php  -­‐-­‐rf  json_encodeFunction  [  <internal:json>  function  json_encode  ]  {    -­‐  Parameters  [2]  {        Parameter  #0  [  <required>  $value  ]        Parameter  #1  [  <optional>  $options  ]    }}$
  • 44. Class  reflecMon  (-­‐-­‐rc) $  php  -­‐-­‐rc  stdclass Class  [  <internal:Core>  class  stdClass  ]  {    -­‐  Constants  [0]  {    }    -­‐  Static  properties  [0]  {    }    -­‐  Static  methods  [0]  {    }    -­‐  Properties  [0]  {    }    -­‐  Methods  [0]  {    } } $
  • 45. Extension  reflecMon  (-­‐-­‐re)$  php  -­‐-­‐re  jsonExtension  [  <persistent>  extension  #20  json  version  1.2.1  ]  {...    -­‐  Functions  {        Function  [  <internal:json>  function  json_encode  ]  {            -­‐  Parameters  [2]  {                Parameter  #0  [  <required>  $value  ]                Parameter  #1  [  <optional>  $options  ]            }        }...}
  • 46. Extension  INI  informaMon  (-­‐-­‐ri) $  php  -­‐-­‐ri  pdo PDO PDO  support  =>  enabled PDO  drivers  =>  mysql,  sqlite,  sqlite2 $
  • 47. Back  on  track
  • 48. Back  to  I/O
  • 49. Input  &  output Web CLI• $_SERVER • $_SERVER• $_GET • $argc/$argv• $_POST • $_ENV• $_COOKIE • getopt()• $_SESSION • STDIN/STDOUT/ STDERR• $_ENV
  • 50. Change  your  mindset
  • 51. Change  your  mindset Don’t  use  sessions  &  cookies Just  use  local  variables
  • 52. Change  your  mindset If  you  don’t  need  HTTP,  use  CLI E.g.   cronjobs Avoid  overhead
  • 53. Change  your  mindset Current  directory  !=  webroot CLI   scripts  are  ➡Use  dirname(__FILE__) executable   everywhere➡Use  chdir()➡Use  getcwd()
  • 54. STDIN <?php $handle = fopen(php://stdin,r); while(!feof($handle)){     $line = trim(fgets($handle));     if(strlen($line) > 0){         echo strrev($line).PHP_EOL;     } } fclose($handle);
  • 55. STDIN <?php $handle = fopen(php://stdin,r); while(!feof($handle)){     $line = trim(fgets($handle));     if(strlen($line) > 0){         echo strrev($line).PHP_EOL;     } } fclose($handle);
  • 56. STDIN <?php while(!feof(STDIN)){     $line = trim(fgets(STDIN));     if(strlen($line) > 0){         echo strrev($line).PHP_EOL;     } }
  • 57. STDIN Stream   that  is  opened   <?php by  default while(!feof(STDIN)){     $line = trim(fgets(STDIN));     if(strlen($line) > 0){         echo strrev($line).PHP_EOL;     } }
  • 58. STDIN The   Stream   that  is  opened   proof  ! by  default $  php  -­‐r  "var_dump(STDIN);" resource(1)  of  type  (stream) $
  • 59. Wordcount  example<?php$wordArray = array();while(!feof(STDIN)){    $line = trim(fgets(STDIN));    if(strlen($line) > 0){        foreach(preg_split(/[s]+/,$line) as $word){            if(!array_key_exists($word,$wordArray)){                $wordArray[$word] = 0;            }            $wordArray[$word]++;        }    }}ksort($wordArray);foreach($wordArray as $word=>$count){    echo "$word: $count".PHP_EOL;}
  • 60. Wordcount  example$  cat  wordcount.txt  UK  ThijsThijsUKThijs  PHPNW11ThijsUK$  cat  wordcount.txt    |  php  wordcount.php  PHPNW11:  1Thijs:  4UK:  3$
  • 61. STDOUT STDOUT   ==   echo<?php$handle = fopen(php://stdout,w);fwrite($handle,Hello world);fclose($handle);
  • 62. STDOUT<?phpfwrite(STDOUT,Hello world);
  • 63. STDERR<?php$handle = fopen(php://stderr,w);fwrite($handle,Serious error!);fclose($handle);
  • 64. STDERR<?phpfwrite(STDERR,Serious error!);
  • 65. Mixing  STDOUT  &  STDERR<?phpfwrite(STDOUT,STDOUT output.PHP_EOL);fwrite(STDERR,STDERR output.PHP_EOL);$  php  stdmix.php  STDOUT  outputSTDERR  output$
  • 66. Mixing  STDOUT  &  STDERR<?php Looks  fwrite(STDOUT,STDOUT output.PHP_EOL); the  samefwrite(STDERR,STDERR output.PHP_EOL);$  php  stdmix.php  STDOUT  outputSTDERR  output$
  • 67. Mixing  STDOUT  &  STDERR$  php  stdmix.php  >  /dev/null  STDERR  output$$  php  stdmix.php  &>    /dev/null$
  • 68. Mixing  STDOUT  &  STDERR STDOUT   is  caught$  php  stdmix.php  >  /dev/null   STDOUT  STDERR  output$ &  STDERR  are   caught$  php  stdmix.php  &>    /dev/null$
  • 69. AlternaMve  output<?phpfclose(STDOUT);$handle = fopen(realpath(dirname(__FILE__)./output.txt),a);echo "Hello world!".PHP_EOL;fclose($handle);
  • 70. AlternaMve  output<?phpfclose(STDOUT);$handle = fopen(realpath(dirname(__FILE__)./output.txt),a);echo "Hello world!".PHP_EOL;fclose($handle); echo   output  is  wrioen   to  file
  • 71. Piping$  php  -­‐r  for($i=0;$i<10;$i++)  echo  $i.PHP_EOL;0123456789$  php  -­‐r  for($i=0;$i<10;$i++)  echo  $i.PHP_EOL;  |  wc  -­‐l            10$
  • 72. Readline<?php$name = readline("Whats your name: ");$location = readline("Where do you live: ");echo PHP_EOL."Hello $name from $locationn";$  php  readline.php  Whats  your  name:  ThijsWhere  do  you  live:  BelgiumHello  Thijs  from  Belgium$
  • 73. Shebang  !
  • 74. Shebang  !#!/usr/bin/php<?phpecho "Hello world".PHP_EOL;$  chmod  +x  shebang.php$  ./shebang.phpHello  world$
  • 75. Encore
  • 76. Process  Control  should  not  be  enabled   within  a  web  server  environment  and   unexpected  results  may  happen  if  any  Process  Control  funcWons  are  used  within   a  web  server  environment.
  • 77. Forking PID  value   determines   context Copy  <?php program  $pid = pcntl_fork();if ($pid == -1) { execuWon //Forking failed} else if ($pid) { //Parent logic} else { PID  of  child   //Child logic} process
  • 78. Forking<?php$pid = pcntl_fork();if ($pid == -1) {     die(could not fork);} else if ($pid) {     echo "[parent] Starting".PHP_EOL;     pcntl_wait($status);     echo "[parent] Exiting".PHP_EOL;} else {        echo "[child] Starting".PHP_EOL;    for($i=0;$i<3;$i++){        echo "[child] Loop $i".PHP_EOL;        sleep(1);    }    echo "[child] Exiting".PHP_EOL;    exit;}
  • 79. Forking Perform   forking<?php$pid = pcntl_fork();if ($pid == -1) {     die(could not fork); Wait  for  child  } else if ($pid) { terminaWon     echo "[parent] Starting".PHP_EOL;     pcntl_wait($status);     echo "[parent] Exiting".PHP_EOL;} else {        echo "[child] Starting".PHP_EOL;    for($i=0;$i<3;$i++){        echo "[child] Loop $i".PHP_EOL;        sleep(1);    }    echo "[child] Exiting".PHP_EOL;    exit;}
  • 80. Signals<?phpdeclare(ticks = 1);function sig_handler($signo){     switch ($signo) {         case SIGTERM:             echo PHP_EOL."SIGTERM".PHP_EOL;             exit();             break;         case SIGINT:             echo PHP_EOL."SIGINT".PHP_EOL;             exit();             break;     }}pcntl_signal(SIGTERM, "sig_handler");pcntl_signal(SIGINT, "sig_handler");sleep(100);
  • 81. Signals<?phpdeclare(ticks = 1); Process   terminaWonfunction sig_handler($signo){     switch ($signo) {         case SIGTERM: Process               echo PHP_EOL."SIGTERM".PHP_EOL;             exit();             break;         case SIGINT: interrupWon             echo PHP_EOL."SIGINT".PHP_EOL;             exit();             break; Catch  signals     }}pcntl_signal(SIGTERM, "sig_handler");pcntl_signal(SIGINT, "sig_handler");sleep(100);
  • 82. POSIX  process  control  funcMons<?phpecho "[prefork] PID:".posix_getpid().", parent PID: ".posix_getppid().PHP_EOL;$pid = pcntl_fork();if ($pid == -1) {  die(could not fork);} else if ($pid == 0) {echo "[child] PID: ".posix_getpid().", parent PID: ".posix_getppid().PHP_EOL;  exit;} else {  echo "[parent] PID: ".posix_getpid().", parent PID: ".posix_getppid().PHP_EOL;  pcntl_wait($status);
  • 83. Parent  PID   Prefork  PID  POSIX  process  c==   funcMons of  parent   ontrol   ==  <?phpsession  PID parent  PIDecho "[prefork] PID:".posix_getpid().", parent PID: ".posix_getppid().PHP_EOL;$pid = pcntl_fork();if ($pid == -1) { child  PID     die(could not fork); child  PID} else if ($pid == 0) {        echo "[child] PID: ".posix_getpid().", parent PID: ".posix_getppid().PHP_EOL; parent          exit;} else { PID        echo "[parent] PID: ".posix_getpid().", parent PID: ".posix_getppid().PHP_EOL;        pcntl_wait($status);}
  • 84. POSIX  process  control  funcMons<?php$pid=pcntl_fork();if ($pid == -1) {    die("could not fork");} else if ($pid) {    $exists = posix_kill($pid,0)?still:no longer;    echo "[parent] Child process $pid $exists exists".PHP_EOL;    echo "[parent] Killing child process $pid".PHP_EOL;    posix_kill($pid,SIGTERM);    echo "[parent] Child process $pid killed".PHP_EOL;    pcntl_wait($status);    $exists = posix_kill($pid,0)?still:no longer;    echo "[parent] Child process $pid $exists exists".PHP_EOL;} else {    while(true){        sleep(100);    }    exit;}
  • 85. POSIX  process  control  funcMons “KILL  0”  checks  <?php$pid=pcntl_fork(); existenceif ($pid == -1) {    die("could not fork");} else if ($pid) { Send  SIGTERM      $exists = posix_kill($pid,0)?still:no longer;    echo "[parent] Child process $pid $exists exists".PHP_EOL; signal    echo "[parent] Killing child process $pid".PHP_EOL;    posix_kill($pid,SIGTERM);    echo "[parent] Child process $pid killed".PHP_EOL;    pcntl_wait($status);    $exists = posix_kill($pid,0)?still:no longer;    echo "[parent] Child process $pid $exists exists".PHP_EOL;} else {    while(true){ Child  process          sleep(100);    } is  dead    exit;}
  • 86. Talk   dedicated  to   process  control  Check  this  guy  out  ! in  PHP Jeroen  Keppens:  @jkeppens http://www.slideshare.net/jkeppens/php-­‐in-­‐the-­‐dark
  • 87. •January  27th  &  28th  2012•Best  Western  Hotel  Ter  Elst  Antwerp  (Belgium)•Call  For  Papers  unWl  October  15th•Schedule  &  Wcket  announcements  beginning  of  November
  • 88. Q&A
  • 89. Thanks  !