Date post: | 15-Jan-2015 |
Category: |
Technology |
Upload: | combell-group |
View: | 3,086 times |
Download: | 3 times |
About me
I’m an Evangelist at Combell
About me
I’m a board member at PHPBenelux
Follow me on Twi+er: @ThijsFeryn
Give me feedback: h+p://joind.in/3596
SAPI?
The way you interact with PHP
Common SAPIs
Common SAPIs
• Apache/Apache 2
• FPM
• FastCGI
• ISAPI
• CLI
• GTK
The CLI SAPI
PHP script execuWon via the command line interface
When to use
When to use
• In crons
• For batch tasks
• For worker processes
• Daemons
• Process control
• InteracWon with other binaries
CLI 101
CLI 101
The PHP binary
Passing arguments
Reading from STDIN
I/O with pipes
CLI 101Invoking a script with the
PHP binary
php file.php
CLI 101Passing arguments
php file.php arg1 arg2
CLI 101interpreting arguments
<?phpecho "Number of arguments {$argc}\n";foreach($argv as $key=>$argument){ echo "Argument # {$key}: {$argument}\n"; }
CLI 101interpreting arguments
<?phpecho "Number of arguments {$argc}\n";foreach($argv as $key=>$argument){ echo "Argument # {$key}: {$argument}\n"; }
Argument countArgument
array
CLI 101interpreting arguments
$ php args.php arg1 arg2Number of arguments 3Argument # 0: args.phpArgument # 1: arg1Argument # 2: arg2$
The PHP file is an argument too
CLI 101interpreting arguments
$argc
$argv
$_SERVER[‘argc’]
$_SERVER[‘argv’]
!!! register_argc_argv !!!
CLI 101getopt
<?php$arguments = getopt('ab:c::');var_dump($arguments);
CLI 101getopt
<?php$arguments = getopt('ab:c::');var_dump($arguments);
OpWonal value
Flag (no value)
Required value
CLI 101php getopt.php -‐a -‐b 2 -‐c3array(3) { ["a"]=> bool(false) ["b"]=> string(1) "2" ["c"]=> string(1) "3"}
No spacing for opWonal arguments
CLI 101getopt: longopts
<?php$arguments = getopt('',array('arg1','arg2:','arg3::'));var_dump($arguments);
CLI 101php getopt2.php -‐-‐arg1 -‐-‐arg2 123 -‐-‐arg3=xarray(3) { ["arg1"]=> bool(false) ["arg2"]=> string(3) "123" ["arg3"]=> string(1) "x"}
Mind the “=” sign
CLI 101REading 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);
CLI 101$ cat test.txt | php stdin.php enOowTeerhT$
CLI 101$ cat test.txt | php stdin.php enOowTeerhT$
Output file
Convert output to input with pipes
Comparing the Apache & CLI SAPI
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
Comparing the Apache & CLI SAPI
CLI SAPI• Controlable state
• Controlable script execuWon
• ConWnuous interacWon
• No need for sessions
• No execuWon Wmeouts
The PHP binary
php
The PHP binary
Usage: 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
InteracMve mode (-‐a)
$ php -‐aInteractive shell
php > echo 5+8;13php > function addTwo($n)php > {php { return $n + 2;php { }php > var_dump(addtwo(2));int(4)php >
InteracMve mode (-‐a)
$ php -‐aInteractive shell
php > stri[TAB][TAB]strip_tags stripcslashes stripslashes stristr stripos php > stri
Tab compleWon
Run code (-‐r)
$ php -‐r "echo date('Y-‐m-‐d H:i:s');"2011-‐03-‐02 22:04:45$
Config directory (-‐c)
$ php -‐c /custom/dir/php.ini script.php
Define custom INI seSng (-‐d)
$ php -‐d max_execution_time=20 -‐r '$foo = ini_get("max_execution_time"); var_dump($foo);'string(2) "20"$
Get INI informaMon (-‐i)
$ php -‐i | grep “log_”define_syslog_variables => Off => Offlog_errors => On => Onlog_errors_max_len => 1024 => 1024$
Filtering items
Syntax/lint check (-‐l)
$ php -‐l myFile.phpNo syntax errors detected in myFile.php$
Only checks parse
errors
Module list (-‐m)
$ php -‐m[PHP Modules]bcmathbz2calendarCorectypecurldatedba$
Syntax highlighMng (-‐s)
$ php -‐s helloworld.php > helloworld.html$
<?phpecho "Hello world";
Syntax highlighMng (-‐s)
<?phpecho "Hello world";
<code><span style="color: #000000"><span style="color: #0000BB"><?php<br /></span><span style="color: #007700">echo </span><span style="color: #DD0000">"Hello world"</span><span style="color: #007700">;</span></span>
Version info (-‐v)
$ php -‐vPHP 5.3.3-‐1ubuntu9.3 with Suhosin-‐Patch (cli) (built: Jan 12 2011 16:07:38) Copyright (c) 1997-‐2009 The PHP GroupZend Engine v2.3.0, Copyright (c) 1998-‐2010 Zend Technologies$
FuncMon reflecMon (-‐-‐rf)
$ php -‐-‐rf json_encodeFunction [ <internal:json> function json_encode ] {
-‐ Parameters [2] { Parameter #0 [ <required> $value ] Parameter #1 [ <optional> $options ] }}$
Class reflecMon (-‐-‐rc)
$ php -‐-‐rc stdclassClass [ <internal:Core> class stdClass ] { -‐ Constants [0] { } -‐ Static properties [0] { } -‐ Static methods [0] { } -‐ Properties [0] { } -‐ Methods [0] { }}$
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 ] } }...}
Extension INI informaMon (-‐-‐ri)
$ php -‐-‐ri pdo
PDO
PDO support => enabledPDO drivers => mysql, sqlite, sqlite2$
Back on track
Back to I/O
Input & output
Web• $_SERVER
• $_GET
• $_POST
• $_COOKIE
• $_SESSION
• $_ENV
CLI• $_SERVER
• $argc/$argv
• $_ENV
• getopt()
• STDIN/STDOUT/STDERR
Change your mindset
Change your mindset
Don’t use sessions & cookies
Just use local variables
Change your mindset
If you don’t need HTTP, use CLI
Avoid overhead
E.g. cronjobs
Change your mindset
Current directory != webroot
➡Use dirname(__FILE__)
➡Use chdir()
➡Use getcwd()
CLI scripts are executable everywhere
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);
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);
STDIN
<?php
while(!feof(STDIN)){ $line = trim(fgets(STDIN)); if(strlen($line) > 0){ echo strrev($line).PHP_EOL; }}
STDIN
<?php
while(!feof(STDIN)){ $line = trim(fgets(STDIN)); if(strlen($line) > 0){ echo strrev($line).PHP_EOL; }}
Stream that is opened by default
STDIN
$ php -‐r "var_dump(STDIN);"resource(1) of type (stream)$
The proof !
Stream that is opened by default
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;}
Wordcount example
$ cat wordcount.txt UK ThijsThijsUKThijs PHPNW11ThijsUK$ cat wordcount.txt | php wordcount.php PHPNW11: 1Thijs: 4UK: 3$
STDOUT
<?php$handle = fopen('php://stdout','w');fwrite($handle,'Hello world');fclose($handle);
STDOUT ==
echo
STDOUT
<?phpfwrite(STDOUT,'Hello world');
STDERR
<?php$handle = fopen('php://stderr','w');fwrite($handle,'Serious error!');fclose($handle);
STDERR
<?phpfwrite(STDERR,'Serious error!');
Mixing STDOUT & STDERR
<?phpfwrite(STDOUT,'STDOUT output'.PHP_EOL);fwrite(STDERR,'STDERR output'.PHP_EOL);
$ php stdmix.php STDOUT outputSTDERR output$
Mixing STDOUT & STDERR
<?phpfwrite(STDOUT,'STDOUT output'.PHP_EOL);fwrite(STDERR,'STDERR output'.PHP_EOL);
$ php stdmix.php STDOUT outputSTDERR output$
Looks the same
Mixing STDOUT & STDERR
$ php stdmix.php > /dev/null STDERR output$
$ php stdmix.php &> /dev/null$
Mixing STDOUT & STDERR
$ php stdmix.php > /dev/null STDERR output$
$ php stdmix.php &> /dev/null$
STDOUT is caught
STDOUT & STDERR are
caught
AlternaMve output
<?phpfclose(STDOUT);$handle = fopen(realpath(dirname(__FILE__).'/output.txt'),'a');echo "Hello world!".PHP_EOL;fclose($handle);
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
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$
Readline
<?php$name = readline("What's your name: ");$location = readline("Where do you live: ");echo PHP_EOL."Hello $name from $location\n";
$ php readline.php What's your name: ThijsWhere do you live: Belgium
Hello Thijs from Belgium$
Shebang !
Shebang !
#!/usr/bin/php<?phpecho "Hello world".PHP_EOL;
$ chmod +x shebang.php$ ./shebang.phpHello world$
Encore
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.
Forking
<?php$pid = pcntl_fork();if ($pid == -1) {
//Forking failed} else if ($pid) {
//Parent logic} else {
//Child logic}
Copy program execuWon
PID value determines context
PID of child process
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;}
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;}
Perform forking
Wait for child terminaWon
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);
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);
Process terminaWon
Process interrupWon
Catch signals
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);}
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);}
Prefork PID ==
parent PID
Parent PID of parent == session PID
parent PID
child PID
child PID
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;}
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;}
“KILL 0” checks existence
Send SIGTERM signal
Child process is dead
Jeroen Keppens: @jkeppenshttp://www.slideshare.net/jkeppens/php-‐in-‐the-‐dark
Talk dedicated to
process control in PHP
Check this guy out !
•January 27th & 28th 2012•Best Western Hotel Ter Elst Antwerp (Belgium)
•Call For Papers unWl October 15th•Schedule & Wcket announcements beginning of November
Q&A
Thanks !