Cli the other sapi pbc11

1,720 views

Published on

Slides for my pbc11 talks in Barcelona

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,720
On SlideShare
0
From Embeds
0
Number of Embeds
11
Actions
Shares
0
Downloads
25
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

Cli the other sapi pbc11

  1. 1. CLI,  the  other  SAPI PHPBarcelona  Conference Friday  October  28th  2011 Barcelona,  Spain php Thijs  Feryn Evangelist +32  (0)9  218  79  06 thijs@combellgroup.com
  2. 2. About  me I’m  an  Evangelist  at  Combell
  3. 3. About  me I’m  a  board  member  at  PHPBenelux
  4. 4. Follow  me  on  Twi+er:  @ThijsFerynGive  me  feedback:  h+p://joind.in/4323
  5. 5. SAPI? The  way  you  interact  with  PHP
  6. 6. Common  SAPIs
  7. 7. Common  SAPIs • Apache/Apache  2 • FPM • FastCGI • ISAPI • CLI • GTK
  8. 8. The  CLI  SAPIPHP  script  execuYon  via  the  command  line  interface
  9. 9. When  to  use
  10. 10. When  to  use• In  crons• For  batch  tasks• For  worker  processes• Daemons• Process  control• InteracYon  with  other  binaries
  11. 11. CLI 101
  12. 12. CLI 101The PHP binaryPassing argumentsReading from STDINI/O with pipes
  13. 13. CLI 101Invoking a script with the PHP binaryphp  file.php
  14. 14. CLI 101 Passing argumentsphp  file.php  arg1  arg2
  15. 15. CLI 101 interpreting arguments<?phpecho "Number of arguments {$argc}n";foreach($argv as $key=>$argument){    echo "Argument # {$key}: {$argument}n"; }
  16. 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. 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. 18. CLI 101 interpreting arguments$_SERVER[‘argc’] $argc$_SERVER[‘argv’] $argv !!! register_argc_argv !!!
  19. 19. CLI 101 getopt<?php$arguments = getopt(ab:c::);var_dump($arguments);
  20. 20. CLI 101 getopt OpYonal   Flag   (no  value) value<?php$arguments = getopt(ab:c::);var_dump($arguments); Required   value
  21. 21. CLI 101php  getopt.php  -­‐a  -­‐b  2  -­‐c3array(3)  {    ["a"]=> No      bool(false)    ["b"]=> spacing  for      string(1)  "2" opYonal      ["c"]=> arguments    string(1)  "3"}
  22. 22. CLI 101 getopt: longopts<?php$arguments = getopt(,array(arg1,arg2:,arg3::));var_dump($arguments);
  23. 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. 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. 25. CLI 101$  cat  test.txt  |  php  stdin.php  enOowTeerhT$
  26. 26. CLI 101$  cat  test.txt  |  php  stdin.php  enOowT Output   Convert  eerhT$ file output  to   input  with   pipes
  27. 27. Comparing  the  Apache  &  CLI  SAPI
  28. 28. Comparing  the  Apache  &  CLI  SAPI Web  based  SAPI’s• HTTP  is  a  stateless  protocol• Request/response  based• Limited  interacYon• Sessions  &  cookies  as  workaround• ExecuYon  Ymeouts• Limited  request/response  size
  29. 29. Comparing  the  Apache  &  CLI  SAPI CLI  SAPI• Controlable  state• Controlable  script  execuYon• ConYnuous  interacYon• No  need  for  sessions• No  execuYon  Ymeouts
  30. 30. The  PHP  binary php
  31. 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. 32. InteracLve  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. 33. InteracLve  mode  (-­‐a) $  php  -­‐a Tab   Interactive  shell compleYon php  >  stri[TAB][TAB] strip_tags          stripcslashes     stripslashes      stristr                 stripos                 php  >  stri
  34. 34. Run  code  (-­‐r) $  php  -­‐r  "echo  date(Y-­‐m-­‐d  H:i:s);" 2011-­‐03-­‐02  22:04:45 $
  35. 35. Config  directory  (-­‐c) $  php  -­‐c  /custom/dir/php.ini  script.php
  36. 36. Define  custom  INI  seRng  (-­‐d) $  php  -­‐d  max_execution_time=20  -­‐r  $foo  =   ini_get("max_execution_time");   var_dump($foo); string(2)  "20" $
  37. 37. Get  INI  informaLon  (-­‐i) Filtering   items $  php  -­‐i  |  grep  “log_” define_syslog_variables  =>  Off  =>  Off log_errors  =>  On  =>  On log_errors_max_len  =>  1024  =>  1024 $
  38. 38. Syntax/lint  check  (-­‐l) Only   checks  parse   errors $  php  -­‐l  myFile.php No  syntax  errors  detected  in  myFile.php $
  39. 39. Module  list  (-­‐m) $  php  -­‐m [PHP  Modules] bcmath bz2 calendar Core ctype curl date dba $
  40. 40. Syntax  highlighLng  (-­‐s)<?phpecho  "Hello  world";$  php  -­‐s  helloworld.php  >  helloworld.html$
  41. 41. Syntax  highlighLng  (-­‐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. 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. 43. FuncLon  reflecLon  (-­‐-­‐rf)$  php  -­‐-­‐rf  json_encodeFunction  [  <internal:json>  function  json_encode  ]  {    -­‐  Parameters  [2]  {        Parameter  #0  [  <required>  $value  ]        Parameter  #1  [  <optional>  $options  ]    }}$
  44. 44. Class  reflecLon  (-­‐-­‐rc) $  php  -­‐-­‐rc  stdclass Class  [  <internal:Core>  class  stdClass  ]  {    -­‐  Constants  [0]  {    }    -­‐  Static  properties  [0]  {    }    -­‐  Static  methods  [0]  {    }    -­‐  Properties  [0]  {    }    -­‐  Methods  [0]  {    } } $
  45. 45. Extension  reflecLon  (-­‐-­‐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. 46. Extension  INI  informaLon  (-­‐-­‐ri) $  php  -­‐-­‐ri  pdo PDO PDO  support  =>  enabled PDO  drivers  =>  mysql,  sqlite,  sqlite2 $
  47. 47. Back  on  track
  48. 48. Back  to  I/O
  49. 49. Input  &  output Web CLI• $_SERVER • $_SERVER• $_GET • $argc/$argv• $_POST • $_ENV• $_COOKIE • getopt()• $_SESSION • STDIN/STDOUT/ STDERR• $_ENV
  50. 50. Change  your  mindset
  51. 51. Change  your  mindset Don’t  use  sessions  &  cookies Just  use  local  variables
  52. 52. Change  your  mindset If  you  don’t  need  HTTP,  use  CLI E.g.   cronjobs Avoid  overhead
  53. 53. Change  your  mindset Current  directory  !=  webroot CLI   scripts  are  ➡Use  dirname(__FILE__) executable   everywhere➡Use  chdir()➡Use  getcwd()
  54. 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. 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. 56. STDIN <?php while(!feof(STDIN)){     $line = trim(fgets(STDIN));     if(strlen($line) > 0){         echo strrev($line).PHP_EOL;     } }
  57. 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. 58. STDIN The   Stream   that  is  opened   proof  ! by  default $  php  -­‐r  "var_dump(STDIN);" resource(1)  of  type  (stream) $
  59. 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. 60. Wordcount  example$  cat  wordcount.txt  Barcelona  ThijsThijsBarcelonaThijs  PHPThijsBarcelona$  cat  wordcount.txt    |  php  wordcount.php  PHP:  1Thijs:  4Barcelona:  3$
  61. 61. STDOUT STDOUT   ==   echo<?php$handle = fopen(php://stdout,w);fwrite($handle,Hello world);fclose($handle);
  62. 62. STDOUT<?phpfwrite(STDOUT,Hello world);
  63. 63. STDERR<?php$handle = fopen(php://stderr,w);fwrite($handle,Serious error!);fclose($handle);
  64. 64. STDERR<?phpfwrite(STDERR,Serious error!);
  65. 65. Mixing  STDOUT  &  STDERR<?phpfwrite(STDOUT,STDOUT output.PHP_EOL);fwrite(STDERR,STDERR output.PHP_EOL);$  php  stdmix.php  STDOUT  outputSTDERR  output$
  66. 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. 67. Mixing  STDOUT  &  STDERR$  php  stdmix.php  >  /dev/null  STDERR  output$$  php  stdmix.php  &>    /dev/null$
  68. 68. Mixing  STDOUT  &  STDERR STDOUT   is  caught$  php  stdmix.php  >  /dev/null   STDOUT  STDERR  output$ &  STDERR  are   caught$  php  stdmix.php  &>    /dev/null$
  69. 69. AlternaLve  output<?phpfclose(STDOUT);$handle = fopen(realpath(dirname(__FILE__)./output.txt),a);echo "Hello world!".PHP_EOL;fclose($handle);
  70. 70. AlternaLve  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. 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. 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. 73. Shebang  !
  74. 74. Shebang  !#!/usr/bin/php<?phpecho "Hello world".PHP_EOL;$  chmod  +x  shebang.php$  ./shebang.phpHello  world$
  75. 75. Encore
  76. 76. Process  Control  should  not  be  enabled   within  a  web  server  environment  and   unexpected  results  may  happen  if  any  Process  Control  funcYons  are  used  within   a  web  server  environment.
  77. 77. Forking PID  value   determines   context Copy  <?php program  $pid = pcntl_fork();if ($pid == -1) { execuYon //Forking failed} else if ($pid) { //Parent logic} else { PID  of  child   //Child logic} process
  78. 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. 79. Forking Perform   forking<?php$pid = pcntl_fork();if ($pid == -1) {     die(could not fork); Wait  for  child  } else if ($pid) { terminaYon     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. 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. 81. Signals<?phpdeclare(ticks = 1); Process   terminaYonfunction sig_handler($signo){     switch ($signo) {         case SIGTERM: Process               echo PHP_EOL."SIGTERM".PHP_EOL;             exit();             break;         case SIGINT: interrupYon             echo PHP_EOL."SIGINT".PHP_EOL;             exit();             break; Catch  signals     }}pcntl_signal(SIGTERM, "sig_handler");pcntl_signal(SIGINT, "sig_handler");sleep(100);
  82. 82. POSIX  process  control  funcLons<?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. 83. Parent  PID   Prefork  PID  POSIX  process  c==   funcLons 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. 84. POSIX  process  control  funcLons<?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. 85. POSIX  process  control  funcLons “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. 86. Talk   dedicated  to   process  control  Check  this  guy  out  ! in  PHP Jeroen  Keppens:  @jkeppens http://www.slideshare.net/jkeppens/ zendcon-­‐2011-­‐php-­‐in-­‐the-­‐dark
  87. 87. •January  27th  &  28th  2012•Best  Western  Hotel  Ter  Elst  Antwerp  (Belgium)•Call  For  Papers  CLOSED•Schedule  &  Ycket  announcements  in  a  couple  of  weeks
  88. 88. Q&A
  89. 89. Thanks  !

×