SlideShare une entreprise Scribd logo
1  sur  126
Jeroen Keppens
• Amazium bvba
• Team Leader
• Scrum Master
• Senior PHP Developer
• @jkeppens
• blog.amazium.com
Download code examples



 http://www.amazium.com/
      phpinthedark.tgz
shell scripting




     photo : istockphoto
php-cli
• server api (sapi)
                                                                          PHP Extensions
• coordinates php
      lifecycle
                                                                  PHP CORE          Zend Engine
                                                                 request mgmt       Compile/Exec
• command line interface                                        network & file i/o   Memory alloc

• shebang
                                                                         SAPI (Server API)
http://www.slideshare.net/combell/cli-the-other-sapi-confoo11
globals
• no $_POST, $_GET           Array (
                                 [TERM_PROGRAM] => Apple_Terminal
                                 [TERM] => xterm-color

• no HTTP_*
                                 [SHELL] => /bin/bash
                                 [TERM_PROGRAM_VERSION] => 273
                                 [USER] => jkeppens
                                 [COMMAND_MODE] => unix2003
• no REMOTE_*                    [PWD] => /Users/jkeppens
                                 [HOME] => /Users/jkeppens
                                 [LOGNAME] => jkeppens

• no SERVER_*                    [LC_CTYPE] => UTF-8
                                 [DISPLAY] => /tmp/launch-hr4Dxt/
                             org.x:0

• term / shell information
                                 [argv] => Array ( [0] => /tmp/
                             test.php )
                                 [argc] => 1
                             )
• argv / argc
cronjobs
• schedule task ( crontab -u username -e )
  *   *   *   *   *   command to be executed
  |   |   |   |   |
  |   |   |   |   +----- day of week (0 - 6) (Sunday=0)
  |   |   |   +------- month (1 - 12)
  |   |   +--------- day of month (1 - 31)
  |   +----------- hour (0 - 23)
  +------------- min (0 - 59)

• define constants, access via $_SERVER[‘name’]
  NAME = VALUE
cronjobs
; define constants
APPLICATION_ENVIRONMENT = development
DB_SERVER = db1.somehost.com

; run every day at 4:30
30 4    *   *   *   /path/to/somescript.php -daily

; run every 5 minutes
*/5 *   *   *   *   /path/to/somescript.php

; run every monday and thursday, at midnight and 9AM
* 0,9 *     *   1,4 /path/to/somescript
input / output




 http://www.fotopedia.com/items/flickr-217097889
the basics : argc | argv
• $argc = number of
  arguments

• $argv = array of
  arguments

• first element = script
  filename


            photo by Kore Nordmann - http://kore-nordmann.de/photos/misc/full/elephpant_39.html
the basics : argc | argv
• $argc = number of       // Number of arguments
                          echo '$argc = ';
  arguments               echo $argc . PHP_EOL;

                          // Array of arguments

• $argv = array of        echo '$argv = ';
                          print_r($argv);
  arguments

• first element = script
  filename
./01-basic-input.php -u Jeroen -p test -h -v




                       Text
./01-basic-input.php -u Jeroen -p test -h -v
$argc = 7
$argv = Array
(
    [0] => ./01-basic-input.php
    [1] => -u
    [2] => Jeroen
    [3] => -p               Text
    [4] => test
    [5] => -h
    [6] => -v
)
getopt ( )
• arguments are parsed
• no validation
• short options
• long options since 5.3
• no, optional or
  required values

       photo by Martha de Jong-Lantink - http://www.fotopedia.com/wiki/Emperor_Penguin#!/items/flickr-2080338469
// Define short options
                           $short = "hv";
                           $short.= "u:"; // required

getopt ( )
                           $short.= "p::"; // optional

                           // Define long options
                           $long  = array(
                               "help", "verbose",
• arguments are parsed         "user:",    // required
                               "passwd::", // optional
                           );
• no validation
                           // Get the options (php 5.3)
• short options            $options = getopt(
                               $shortopts,
                               $longopts
• long options since 5.3   );


• no, optional or          // Show it
                           print_r($options);
  required values
./02-basic-getopt.php -u Jeroen -h -ppasswd
./02-basic-getopt.php -u Jeroen -h -ppasswd
Array
(
    [u] => Jeroen
    [p] => passwd
    [h] =>
)
./02-basic-getopt.php -u Jeroen -h -ppasswd
Array
(
    [u] => Jeroen
    [p] => passwd
    [h] =>
)



./02-basic-getopt.php -u -h -p passwd
./02-basic-getopt.php -u Jeroen -h -ppasswd
Array
(
    [u] => Jeroen
    [p] => passwd
    [h] =>
)



./02-basic-getopt.php -u -h -p passwd
Array
(
    [u] => -h
    [p] =>
)
pear | getopt

• Console_Getopt class
• readPHPArgv ( )
• getopt ( )
• getopt2 ( )
• PEAR Errors
• short / long options unlinked
// Define short options
                                  $shortopts = "hv";
                                  $shortopts.= "u:";
                                  $shortopts.= "p::";


pear | getopt
                                  // Define long options
                                  $longopts  = array(
                                      "help", "verbose",
                                      "user=",
                                      "password==",
                                  );
• Console_Getopt class
                                  $getopt = new Console_Getopt();

• readPHPArgv ( )                 // Get the arguments & remove script
                                  $args = $getopt->readPHPArgv();
• getopt ( )                      array_shift($args);

                                  // Parse the options
• getopt2 ( )                     $options = $getopt->getopt2(
                                      $args, $shortopts, $longopts);

• PEAR Errors                     if (PEAR::isError($options)) {
                                      echo 'Got error: ';
• short / long options unlinked       echo $options->getMessage();
                                  } else {
                                      print_r($options);
                                  }
zend | getopt
• Zend_Console_Getopt
• options linked
• value type validation
• usage message
• object returned
• exceptions
                          photo : istockphoto
// Define short option
                          $cfg = array(
                            "help|h"   => "Show help",
                            "verbose|v" => "Verbose mode",


zend | getopt
                            "user|u=s"  => "Username (string)",
                            "password|p-s"  
                               => "Password (string) (optional)"
                          );

                          try {
                            $opts = new Zend_Console_Getopt($cfg);
• Zend_Console_Getopt       $opts->parse();
                            if (!empty($opts->help)) {
                              echo $opts->getUsageMessage();

• options linked            } else {
                              $user     = $opts->user;
                              $passwd  = $opts->password;

• value type validation
                              $verbose = !empty($opts->v);
                              echo "Log in [$user / $passwd]";
                              if ($verbose) {
                                echo " in verbose mode";
• usage message               }
                            }
                          } 

• object returned         catch (Zend_Console_Getopt_Exception $e) 
                          {
                            echo $opts->getUsageMessage();

• exceptions
                          }
./03-zend-getopt.php -h
./03-zend-getopt.php -h
Usage: ./03-zend-getopt.php [ options ]
--help|-h                  Show help
--verbose|-v               Verbose mode
--user|-u <string>         Username (string)
--password|-p [ <string> ] Password (string) (optional)
readline
• interactive input
• GNU Readline library
• auto-completion
• command history
• callback functions

           photo by Gracey Heart - http://www.flickr.com/photos/graceyheartphotography/5552036368/
// Autocompletion
function autocomplete() {
    return array('history', 'clear', 'cls', 'quit', 'exit');
}
readline_completion_function('autocomplete');

// Initiate history
if (is_file($historyFile)) readline_read_history($historyFile);

while (true) {
   $line = strtolower(trim(readline('Command: ')));
   echo 'Received [ ' . $line . ' ]' . PHP_EOL;
   readline_add_history($line); // add command to history

    switch ($line) {
      case 'clear': case 'cls':
            readline_clear_history(); break;
        case 'history':
            print_r(readline_list_history()); break;
        case 'quit': case 'exit':
            break 2;
    }
}

readline_write_history($historyFile); // Write back to disk
// Autocompletion
function autocomplete() {
    return array('history', 'clear', 'cls', 'quit', 'exit');
}
readline_completion_function('autocomplete');

// Initiate history
if (is_file($historyFile)) readline_read_history($historyFile);

while (true) {
   $line = strtolower(trim(readline('Command: ')));
   echo 'Received [ ' . $line . ' ]' . PHP_EOL;
   readline_add_history($line); // add command to history

    switch ($line) {
      case 'clear': case 'cls':
            readline_clear_history(); break;
        case 'history':
            print_r(readline_list_history()); break;
        case 'quit': case 'exit':
            break 2;
    }
}

readline_write_history($historyFile); // Write back to disk
// Autocompletion
function autocomplete() {
    return array('history', 'clear', 'cls', 'quit', 'exit');
}
readline_completion_function('autocomplete');

// Initiate history
if (is_file($historyFile)) readline_read_history($historyFile);

while (true) {
   $line = strtolower(trim(readline('Command: ')));
   echo 'Received [ ' . $line . ' ]' . PHP_EOL;
   readline_add_history($line); // add command to history

    switch ($line) {
      case 'clear': case 'cls':
            readline_clear_history(); break;
        case 'history':
            print_r(readline_list_history()); break;
        case 'quit': case 'exit':
            break 2;
    }
}

readline_write_history($historyFile); // Write back to disk
// Autocompletion
function autocomplete() {
    return array('history', 'clear', 'cls', 'quit', 'exit');
}
readline_completion_function('autocomplete');

// Initiate history
if (is_file($historyFile)) readline_read_history($historyFile);

while (true) {
   $line = strtolower(trim(readline('Command: ')));
   echo 'Received [ ' . $line . ' ]' . PHP_EOL;
   readline_add_history($line); // add command to history

    switch ($line) {
      case 'clear': case 'cls':
            readline_clear_history(); break;
        case 'history':
            print_r(readline_list_history()); break;
        case 'quit': case 'exit':
            break 2;
    }
}

readline_write_history($historyFile); // Write back to disk
// Autocompletion
function autocomplete() {
    return array('history', 'clear', 'cls', 'quit', 'exit');
}
readline_completion_function('autocomplete');

// Initiate history
if (is_file($historyFile)) readline_read_history($historyFile);

while (true) {
   $line = strtolower(trim(readline('Command: ')));
   echo 'Received [ ' . $line . ' ]' . PHP_EOL;
   readline_add_history($line); // add command to history

    switch ($line) {
      case 'clear': case 'cls':
            readline_clear_history(); break;
        case 'history':
            print_r(readline_list_history()); break;
        case 'quit': case 'exit':
            break 2;
    }
}

readline_write_history($historyFile); // Write back to disk
// Autocompletion
function autocomplete() {
    return array('history', 'clear', 'cls', 'quit', 'exit');
}
readline_completion_function('autocomplete');

// Initiate history
if (is_file($historyFile)) readline_read_history($historyFile);

while (true) {
   $line = strtolower(trim(readline('Command: ')));
   echo 'Received [ ' . $line . ' ]' . PHP_EOL;
   readline_add_history($line); // add command to history

    switch ($line) {
      case 'clear': case 'cls':
            readline_clear_history(); break;
        case 'history':
            print_r(readline_list_history()); break;
        case 'quit': case 'exit':
            break 2;
    }
}

readline_write_history($historyFile); // Write back to disk
// Autocompletion
function autocomplete() {
    return array('history', 'clear', 'cls', 'quit', 'exit');
}
readline_completion_function('autocomplete');

// Initiate history
if (is_file($historyFile)) readline_read_history($historyFile);

while (true) {
   $line = strtolower(trim(readline('Command: ')));
   echo 'Received [ ' . $line . ' ]' . PHP_EOL;
   readline_add_history($line); // add command to history

    switch ($line) {
      case 'clear': case 'cls':
            readline_clear_history(); break;
        case 'history':
            print_r(readline_list_history()); break;
        case 'quit': case 'exit':
            break 2;
    }
}

readline_write_history($historyFile); // Write back to disk
// Autocompletion
function autocomplete() {
    return array('history', 'clear', 'cls', 'quit', 'exit');
}
readline_completion_function('autocomplete');

// Initiate history
if (is_file($historyFile)) readline_read_history($historyFile);

while (true) {
   $line = strtolower(trim(readline('Command: ')));
   echo 'Received [ ' . $line . ' ]' . PHP_EOL;
   readline_add_history($line); // add command to history

    switch ($line) {
      case 'clear': case 'cls':
            readline_clear_history(); break;
        case 'history':
            print_r(readline_list_history()); break;
        case 'quit': case 'exit':
            break 2;
    }
}

readline_write_history($historyFile); // Write back to disk
// Autocompletion
function autocomplete() {
    return array('history', 'clear', 'cls', 'quit', 'exit');
}
readline_completion_function('autocomplete');

// Initiate history
if (is_file($historyFile)) readline_read_history($historyFile);

while (true) {
   $line = strtolower(trim(readline('Command: ')));
   echo 'Received [ ' . $line . ' ]' . PHP_EOL;
   readline_add_history($line); // add command to history

    switch ($line) {
      case 'clear': case 'cls':
            readline_clear_history(); break;
        case 'history':
            print_r(readline_list_history()); break;
        case 'quit': case 'exit':
            break 2;
    }
}

readline_write_history($historyFile); // Write back to disk
output
helpers
• pear Console_*
• ez consoletools
• text formatting
• progressbars
• tables
ncurses
• terminfo format
• padding
• coloring
• windows
• keyboard / mouse input
• alternative: whiptail
daemons




photo by PSA Peugeot Citroen - http://bit.ly/peugeot-car-welding
steps to create a daemon
• Fork off the parent process
steps to create a daemon
• Fork off the parent process
• Change the file mode mask
steps to create a daemon
• Fork off the parent process
• Change the file mode mask
• Open any logs for writing
steps to create a daemon
• Fork off the parent process
• Change the file mode mask
• Open any logs for writing
• Create a new session id & detach current session
steps to create a daemon
• Fork off the parent process
• Change the file mode mask
• Open any logs for writing
• Create a new session id & detach current session
• Change the current working directory
steps to create a daemon
• Fork off the parent process
• Change the file mode mask
• Open any logs for writing
• Create a new session id & detach current session
• Change the current working directory
• Close standard file descriptors
fork off the parent process
• pcntl_fork ( )
• creates copy of parent
• different pid & ppid
• [pid] : parent process
• 0 : child process
• -1 : error forking
              photo by Conan (conanil) - http://www.flickr.com/photos/conanil/1215118030/
fork off the parent process
•   pcntl_fork ( )         // We fork the script
                           $pid = pcntl_fork();

• creates copy of parent   // We add our daemon &
                           //   child code
• different pid & ppid     if ($pid == -1) {
                               die('Could not fork!');
• [pid] : parent process   } elseif ($pid) {
                               // we are the child
                           } else {
• 0 : child process            // we are the parent
                           }
• -1 : error forking
change the file mode mask
• umask (mask)
• mask: octal notation
• system umask & mask
• revoke permissions
• 0: reset to system mask
• dirs: 0777, files: 0666
           photo by The Mad Hatter - http://www.lauraleeburch.com/blog/2010/05/the-mad-hatter-2/
change the file mode mask
•   umask (mask)            // system umask = 0022
                            touch($testFile);
                            // resulting permissions:
• mask: octal notation      // 0666 - 0022 = 0644

• system umask & mask       // remove test file
                            unlink($testFile);
• revoke permissions        // reset umask = 0007
                            umask(0007);
• 0: reset to system mask   touch($testFile);
                            // resulting permissions:
• dirs: 0777, files: 0666    // 0666 - 0007 = 0660
Open any logs for writing
• no feedback via shell
• debug info via logs
• logging via
  • database
  • logfiles
  • syslogd
                photo by Miranda Hine - http://www.flickr.com/photos/mirandahine/5500665022
Open any logs for writing
•   no feedback via shell   // open syslog wth processID
                            openlog('SyslogTest', 
                                LOG_PID | LOG_PERROR, 
• debug info via logs           LOG_LOCAL0);

• logging via               $access = date('H:i:s');
                            syslog(LOG_WARNING, 'Data 
    • database              was accessed @ ' . $access);

                            closelog();
    • logfiles
                            // Oct 20 15:36:12 amazium
    • syslogd               SyslogTest[11785]: Data was
                            accessed @ 15:36:12
Create a new session id
• acquire unique SID
• avoid system orphans
• posix_setsid ( )
  • sid on success
  • -1 on error


                     photo by Notch Brewing - http://www.notchsession.com
Create a new session id
•   acquire unique SID   // Forked, client part

                         // let's detach
• avoid system orphans   $sid = posix_setsid();

• posix_setsid ( )       // Die on failure to detach
                         if ($sid < 0) {
    • sid on success         die('Could not detach 
                                  session id.');
                         }
    • -1 on error
Change current working dir
• daemon can be started
  from any location
• mounts can disappear
• change cwd to a safe
  location
• getcwd ( )
• chdir ( )
               photo by Majeq - http://majeq.deviantart.com/art/Broken-Bridge-Speedy-176766406
Close standard file descriptors
• STDIN, STDOUT, STDERR
• inherited from parent
• unknown targets
• i.e. output still to shell
• close & reconnect file
  descriptors with fclose
  & fopen
                           photo : istockphoto
// Log file to write to
$logfile = '/tmp/some-log-file.log';

// Close standard I/O descriptors
fclose(STDIN);
fclose(STDOUT);
fclose(STDERR);

// First 3 descriptors fill up the blanks
$fdIN  = fopen('/dev/null', 'r');
$fdOUT = fopen($logfile, 'a');
$fdERR = fopen('php://stdout', 'a');

// STDIN reads from /dev/null
// STDOUT writes to $logfile
// STDERR writes to STDOUT, so also to $logfile
$pid = pcntl_fork();
if ($pid > 1) {
    exit(0);
} elseif ($pid == 0) {
    umask(0);
    openlog('MyLog', LOG_PID | LOG_PERROR, LOG_LOCAL0);
    $sid = posix_setsid();
    if ($sid < 0) {
        syslog(LOG_ERROR, 'Could not detach session id.');
        exit(1);
    }
    chdir(dirname(__FILE__)); Text
    fclose(STDIN); fclose(STDOUT); fclose(STDERR);
    $fdIN  = fopen('/dev/null', 'r');
    $fdOUT = fopen($logfile, 'a');
    $fdERR = fopen('php://stdout', 'a');
    while (true) { /* ... */ }
    closelog();
    exit(0);
}
$pid = pcntl_fork();             fork off the parent process
if ($pid > 1) {
    exit(0);
} elseif ($pid == 0) {
    umask(0);
    openlog('MyLog', LOG_PID | LOG_PERROR, LOG_LOCAL0);
    $sid = posix_setsid();
    if ($sid < 0) {
        syslog(LOG_ERROR, 'Could not detach session id.');
        exit(1);
    }
    chdir(dirname(__FILE__)); Text
    fclose(STDIN); fclose(STDOUT); fclose(STDERR);
    $fdIN  = fopen('/dev/null', 'r');
    $fdOUT = fopen($logfile, 'a');
    $fdERR = fopen('php://stdout', 'a');
    while (true) { /* ... */ }
    closelog();
    exit(0);
}
$pid = pcntl_fork();             set the user creation mask
if ($pid > 1) {
    exit(0);
} elseif ($pid == 0) {
    umask(0);
    openlog('MyLog', LOG_PID | LOG_PERROR, LOG_LOCAL0);
    $sid = posix_setsid();
    if ($sid < 0) {
        syslog(LOG_ERROR, 'Could not detach session id.');
        exit(1);
    }
    chdir(dirname(__FILE__)); Text
    fclose(STDIN); fclose(STDOUT); fclose(STDERR);
    $fdIN  = fopen('/dev/null', 'r');
    $fdOUT = fopen($logfile, 'a');
    $fdERR = fopen('php://stdout', 'a');
    while (true) { /* ... */ }
    closelog();
    exit(0);
}
$pid = pcntl_fork();                      open any log files
if ($pid > 1) {
    exit(0);
} elseif ($pid == 0) {
    umask(0);
    openlog('MyLog', LOG_PID | LOG_PERROR, LOG_LOCAL0);
    $sid = posix_setsid();
    if ($sid < 0) {
        syslog(LOG_ERROR, 'Could not detach session id.');
        exit(1);
    }
    chdir(dirname(__FILE__)); Text
    fclose(STDIN); fclose(STDOUT); fclose(STDERR);
    $fdIN  = fopen('/dev/null', 'r');
    $fdOUT = fopen($logfile, 'a');
    $fdERR = fopen('php://stdout', 'a');
    while (true) { /* ... */ }
    closelog();
    exit(0);
}
$pid = pcntl_fork();                 detach current session
if ($pid > 1) {
    exit(0);
} elseif ($pid == 0) {
    umask(0);
    openlog('MyLog', LOG_PID | LOG_PERROR, LOG_LOCAL0);
    $sid = posix_setsid();
    if ($sid < 0) {
        syslog(LOG_ERROR, 'Could not detach session id.');
        exit(1);
    }
    chdir(dirname(__FILE__)); Text
    fclose(STDIN); fclose(STDOUT); fclose(STDERR);
    $fdIN  = fopen('/dev/null', 'r');
    $fdOUT = fopen($logfile, 'a');
    $fdERR = fopen('php://stdout', 'a');
    while (true) { /* ... */ }
    closelog();
    exit(0);
}
$pid = pcntl_fork();             change current working      dir
if ($pid > 1) {
    exit(0);
} elseif ($pid == 0) {
    umask(0);
    openlog('MyLog', LOG_PID | LOG_PERROR, LOG_LOCAL0);
    $sid = posix_setsid();
    if ($sid < 0) {
        syslog(LOG_ERROR, 'Could not detach session id.');
        exit(1);
    }
    chdir(dirname(__FILE__)); Text
    fclose(STDIN); fclose(STDOUT); fclose(STDERR);
    $fdIN  = fopen('/dev/null', 'r');
    $fdOUT = fopen($logfile, 'a');
    $fdERR = fopen('php://stdout', 'a');
    while (true) { /* ... */ }
    closelog();
    exit(0);
}
$pid = pcntl_fork();             close open file descriptors
if ($pid > 1) {
    exit(0);
} elseif ($pid == 0) {
    umask(0);
    openlog('MyLog', LOG_PID | LOG_PERROR, LOG_LOCAL0);
    $sid = posix_setsid();
    if ($sid < 0) {
        syslog(LOG_ERROR, 'Could not detach session id.');
        exit(1);
    }
    chdir(dirname(__FILE__)); Text
    fclose(STDIN); fclose(STDOUT); fclose(STDERR);
    $fdIN  = fopen('/dev/null', 'r');
    $fdOUT = fopen($logfile, 'a');
    $fdERR = fopen('php://stdout', 'a');
    while (true) { /* ... */ }
    closelog();
    exit(0);
}
$pid = pcntl_fork();                                 payload
if ($pid > 1) {
    exit(0);
} elseif ($pid == 0) {
    umask(0);
    openlog('MyLog', LOG_PID | LOG_PERROR, LOG_LOCAL0);
    $sid = posix_setsid();
    if ($sid < 0) {
        syslog(LOG_ERROR, 'Could not detach session id.');
        exit(1);
    }
    chdir(dirname(__FILE__)); Text
    fclose(STDIN); fclose(STDOUT); fclose(STDERR);
    $fdIN  = fopen('/dev/null', 'r');
    $fdOUT = fopen($logfile, 'a');
    $fdERR = fopen('php://stdout', 'a');
    while (true) { /* ... */ }
    closelog();
    exit(0);
}
$pid = pcntl_fork();
if ($pid > 1) {
    exit(0);
} elseif ($pid == 0) {
    umask(0);
    openlog('MyLog', LOG_PID | LOG_PERROR, LOG_LOCAL0);
    $sid = posix_setsid();
    if ($sid < 0) {
        syslog(LOG_ERROR, 'Could not detach session id.');
        exit(1);
    }
    chdir(dirname(__FILE__)); Text
    fclose(STDIN); fclose(STDOUT); fclose(STDERR);
    $fdIN  = fopen('/dev/null', 'r');
    $fdOUT = fopen($logfile, 'a');
    $fdERR = fopen('php://stdout', 'a');
    while (true) { /* ... */ }
    closelog();
    exit(0);
}
garbage collection
• no garbage collection
• since php 5.3:
  • gc_enable ( )
  • gc_collect_cycles ( )
• clearstatcache ( )
• memory_get_usage ( )
             photo by Rob Wallace - http://www.flickr.com/photos/robwallace/129263335
pear | System_Daemon
• hide complexity
• start() = fork point
• generate init.d scripts
• More info see:
  http://kevin.vanzonneveld.net/techblog/
  article/create_daemons_in_php/




                     photo by Rob Wallace - http://www.flickr.com/photos/robwallace/129263335
Text
inter-process communication
signals
• standard vs real-time
• communication
• alerts
• timers
• signal handling

           photo by Majeq - http://majeq.deviantart.com/art/Broken-Bridge-Speedy-176766406
signals
•   SIGINT - CRTL-C
•   SIGTSTP - CTRL-Z
•   SIGQUIT - CTRL-
•   SIGTERM - kill [pid]
•   SIGKILL - kill -9 [pid]
•   SIGHUP - kill -hup [pid]
•   SIGUSR1 - kill -10 [pid]
              photo by Majeq - http://majeq.deviantart.com/art/Broken-Bridge-Speedy-176766406
// SIGKILL to self
                               $pid  = posix_getpid();
                               posix_kill($pid, 9);

signals                        // SIGUSR1 to process group
                               $pgrp = posix_getpgrp();
                               posix_kill($pgrp, SIGUSR1);


•   SIGINT - CRTL-C            // SIGHUP to nr of processes
                               $pids = array(/* .. */);
•   SIGTSTP - CTRL-Z           foreach ($pids as $pid) {
                                   posix_kill($pid, SIGHUP);
•   SIGQUIT - CTRL-           }


•   SIGTERM - kill [pid]       // Check process alive
                               if (posix_kill($aPid, 0)) {
•   SIGKILL - kill -9 [pid]       echo "$aPid is alive!";
                               } else {
•   SIGHUP - kill -hup [pid]       echo "$aPid is dead.";
                               }
•   SIGUSR1 - kill -10 [pid]
declare(ticks = 1);

                               function handler($signal) {
                                   global $doPing;


signals
                                   switch ($signal) {
                                       case SIGTERM: case SIGQUIT:
                                           echo "We’re done!n";
                                           // handle shutdown tasks
                                           exit(); break;
                                       case SIGINT:
                                           echo "Stop pinging!n";
•   SIGINT - CRTL-C                        $doPing = false; break;
                                       case SIGUSR1:

•
                                           echo "Caught SIGUSR1!n";
    SIGTSTP - CTRL-Z                       break;
                                   }

•   SIGQUIT - CTRL-           }
                               // Setup Signal Handlers
                               pcntl_signal(SIGTERM, "handler");
•   SIGTERM - kill [pid]       pcntl_signal(SIGQUIT, "handler");
                               pcntl_signal(SIGINT,  "handler");

•
                               pcntl_signal(SIGUSR1, "handler");
    SIGKILL - kill -9 [pid]
                               global $doPing; $doPing = true;

•   SIGHUP - kill -hup [pid]   while ($doPing) {
                                   echo "Ping!" . PHP_EOL;
                               }
•   SIGUSR1 - kill -10 [pid]   // Send SIGUSR1 to current process id
                               posix_kill(posix_getpid(), SIGUSR1);
alerts &
timers
• pcntl_alarm ( )
• set alarm or timer
• signals SIGALRM
• each call cancels
  previous set alarm



                       photo : istockphoto
alerts &
timers
• pcntl_alarm ( )      declare(ticks = 1);

                       function handler($signal) {
• set alarm or timer       echo "Caught SIGALRMn";
                           pcntl_alarm(5);

• signals SIGALRM      }

                       pcntl_signal(SIGALRM, 
• each call cancels                 'handler', 
                                    true);
  previous set alarm   pcntl_alarm(5);

                       while(1) { /* ... */ }
shared memory
• ftok for generating key
• shm_* & shmop_*
• shm php specific,
  shmop more generic

• shmop is faster
• shm has variables
shared memory
• ftok for generating key             • shm_attach,
                                             shm_detach
• shm_* & shmop_*
                                      • shm_has_var,
• shm php specific,                           shm_get_var,
  shmop more generic                         shm_put_var,
                                             shm_remove_var
• shmop is faster
• shm has variables                   • shm_remove
                       photo : istockphoto
shared memory
• ftok for generating key             • shmop_open,
                                             shmop_close
• shm_* & shmop_*
                                      • shmop_read,
• shm php specific,                           shmop_write,
  shmop more generic                         shmop_delete
• shmop is faster                     • shmop_size
• shm has variables
                       photo : istockphoto
alternative shared memory
• memcached
  • high performance
  • distributed
  • lightweight
  • object storage
  • server pooling
resource access control
• semaphores
• provide exclusive
  access to resources

• sem_* functions
• specify number of
  allowed users
message queues
• semaphores
• provide exclusive
  access to resources

• sem_* functions
• specify number of
  allowed users
message queues
• semaphores                            • msg_get_queue,
                                              msg_set_queue,
• provide exclusive                           msg_queue_exists,
  access to resources                         msg_remove_queue
• sem_* functions                       • msg_send,
                                              msg_receive,
• specify number of                           msg_stat_queue
  allowed users

                        photo : istockphoto
ipcs | ipcrm | ipcmk
• queues, semaphores,
  memory segments

• ipcs : status
• ipcmk : create
• ipcrm : remove
socket pairs
• two connected sockets
• stored in an array
• 2-way communication
• socket_create_pair
• socket_read,
  socket_write

                 photo : http://photo.net/photodb/photo?photo_id=11216293
angels




photo by DragoArt.com - http://www.dragoart.com/tuts/9270/1/1/how-to-draw-tattoo-angels,-angel-tattoos.htm
monitoring
• angel scripts
• supervisord
• runit
• daemontools
• beware for zombies!

           photo by Anthony Citrano - http://www.flickr.com/photos/zigzaglens/2956275907
angel scripts
• guardian angels
• pid file present: check
  process is running

• not running: (remove
  pid &) restart script

• angel scheduled cron

            photo by Stu Hill Photography- www.flickr.com/photos/stuhillphotography/5526181346/
foreach ($daemons as $daemon) {
    if (file_exists($daemon['pidfile'])) {
        $pid = trim(file_get_contents($daemon['pidfile']));
        if (!empty($pid)) {
            // fake 0 signal to check if alive
            if (posix_kill($pid, 0)) { 
                continue; // Next check
            }
        }
        @unlink($daemon['pidfile']);
    }
    $pid = pcntl_fork();
    if ($pid === 0) {
        $sid = posix_setsid();
        if ($sid != -1) {
            pcntl_exec($daemon['command'], $daemon['params']);
        }
    }
}
foreach ($daemons as $daemon) {
    if (file_exists($daemon['pidfile'])) {
        $pid = trim(file_get_contents($daemon['pidfile']));
        if (!empty($pid)) {
            // fake 0 signal to check if alive
            if (posix_kill($pid, 0)) { 
                continue; // Next check
            }
        }
        @unlink($daemon['pidfile']);
    }
    $pid = pcntl_fork();
    if ($pid === 0) {
        $sid = posix_setsid();
        if ($sid != -1) {
            pcntl_exec($daemon['command'], $daemon['params']);
        }
    }
}
foreach ($daemons as $daemon) {
    if (file_exists($daemon['pidfile'])) {
        $pid = trim(file_get_contents($daemon['pidfile']));
        if (!empty($pid)) {
            // fake 0 signal to check if alive
            if (posix_kill($pid, 0)) { 
                continue; // Next check
            }
        }
        @unlink($daemon['pidfile']);
    }
    $pid = pcntl_fork();
    if ($pid === 0) {
        $sid = posix_setsid();
        if ($sid != -1) {
            pcntl_exec($daemon['command'], $daemon['params']);
        }
    }
}
foreach ($daemons as $daemon) {
    if (file_exists($daemon['pidfile'])) {
        $pid = trim(file_get_contents($daemon['pidfile']));
        if (!empty($pid)) {
            // fake 0 signal to check if alive
            if (posix_kill($pid, 0)) { 
                continue; // Next check
            }
        }
        @unlink($daemon['pidfile']);
    }
    $pid = pcntl_fork();
    if ($pid === 0) {
        $sid = posix_setsid();
        if ($sid != -1) {
            pcntl_exec($daemon['command'], $daemon['params']);
        }
    }
}
foreach ($daemons as $daemon) {
    if (file_exists($daemon['pidfile'])) {
        $pid = trim(file_get_contents($daemon['pidfile']));
        if (!empty($pid)) {
            // fake 0 signal to check if alive
            if (posix_kill($pid, 0)) { 
                continue; // Next check
            }
        }
        @unlink($daemon['pidfile']);
    }
    $pid = pcntl_fork();
    if ($pid === 0) {
        $sid = posix_setsid();
        if ($sid != -1) {
            pcntl_exec($daemon['command'], $daemon['params']);
        }
    }
}
foreach ($daemons as $daemon) {
    if (file_exists($daemon['pidfile'])) {
        $pid = trim(file_get_contents($daemon['pidfile']));
        if (!empty($pid)) {
            // fake 0 signal to check if alive
            if (posix_kill($pid, 0)) { 
                continue; // Next check
            }
        }
        @unlink($daemon['pidfile']);
    }
    $pid = pcntl_fork();
    if ($pid === 0) {
        $sid = posix_setsid();
        if ($sid != -1) {
            pcntl_exec($daemon['command'], $daemon['params']);
        }
    }
}
foreach ($daemons as $daemon) {
    if (file_exists($daemon['pidfile'])) {
        $pid = trim(file_get_contents($daemon['pidfile']));
        if (!empty($pid)) {
            // fake 0 signal to check if alive
            if (posix_kill($pid, 0)) { 
                continue; // Next check
            }
        }
        @unlink($daemon['pidfile']);
    }
    $pid = pcntl_fork();
    if ($pid === 0) {
        $sid = posix_setsid();
        if ($sid != -1) {
            pcntl_exec($daemon['command'], $daemon['params']);
        }
    }
}
foreach ($daemons as $daemon) {
    if (file_exists($daemon['pidfile'])) {
        $pid = trim(file_get_contents($daemon['pidfile']));
        if (!empty($pid)) {
            // fake 0 signal to check if alive
            if (posix_kill($pid, 0)) { 
                continue; // Next check
            }
        }
        @unlink($daemon['pidfile']);
    }
    $pid = pcntl_fork();
    if ($pid === 0) {
        $sid = posix_setsid();
        if ($sid != -1) {
            pcntl_exec($daemon['command'], $daemon['params']);
        }
    }
}
foreach ($daemons as $daemon) {
    if (file_exists($daemon['pidfile'])) {
        $pid = trim(file_get_contents($daemon['pidfile']));
        if (!empty($pid)) {
            // fake 0 signal to check if alive
            if (posix_kill($pid, 0)) { 
                continue; // Next check
            }
        }
        @unlink($daemon['pidfile']);
    }
    $pid = pcntl_fork();
    if ($pid === 0) {
        $sid = posix_setsid();
        if ($sid != -1) {
            pcntl_exec($daemon['command'], $daemon['params']);
        }
    }
}
foreach ($daemons as $daemon) {
    if (file_exists($daemon['pidfile'])) {
        $pid = trim(file_get_contents($daemon['pidfile']));
        if (!empty($pid)) {
            // fake 0 signal to check if alive
            if (posix_kill($pid, 0)) { 
                continue; // Next check
            }
        }
        @unlink($daemon['pidfile']);
    }
    $pid = pcntl_fork();
    if ($pid === 0) {
        $sid = posix_setsid();
        if ($sid != -1) {
            pcntl_exec($daemon['command'], $daemon['params']);
        }
    }
}
foreach ($daemons as $daemon) {
    if (file_exists($daemon['pidfile'])) {
        $pid = trim(file_get_contents($daemon['pidfile']));
        if (!empty($pid)) {
            // fake 0 signal to check if alive
            if (posix_kill($pid, 0)) { 
                continue; // Next check
            }
        }
        @unlink($daemon['pidfile']);
    }
    $pid = pcntl_fork();
    if ($pid === 0) {
        $sid = posix_setsid();
        if ($sid != -1) {
            pcntl_exec($daemon['command'], $daemon['params']);
        }
    }
}
supervisord
• process control system
• simple
• centralized
• efficient
• extensible
• http://supervisord.org
supervisord
• process control system   [program:gearman_tika]
                           command=/path/to/script.php
• simple                   autostart=true
                           autorestart=true
• centralized              logfile=/var/log/myscript.log

• efficient
• extensible
• http://supervisord.org
monit
• manage & monitor
  processes, files,
  directories & devices

• restart failed daemons
• control file with
  service entries or
  checks
check process processQueues with pidfile "/var/
run/amazium/processQueues.pid"
    start = “/etc/init.d/processQueues start"
    stop = "/etc/init.d/processQueues stop"
    if does not exist then restart
    if cpu usage is greater than 60 percent for
      2 cycles then alert
    if cpu usage > 98% for 5 cycles then restart
    if 2 restarts within 3 cycles then timeout
  alert foo@bar.baz
daemontools
• collection of tools to
  manage services

• supervise : monitors a
  service

• requires run script
  with code to start
  daemon
zombies
• defunct process
• child has finished but
  is still in process table
• reaper for SIGCHLD
• pcntl_signal(SIGCHLD,
  SIG_IGN);


              wallpaper from Pozadia - http://dark.pozadia.org/wallpaper/Dawn-of-the-Zombies/
// Reaper to clean up zombies
                              function reaper($signal) 
                              {
                                 $pid = pcntl_waitpid(-1,


zombies
                                                        $status, 
                                                        WNOHANG);
                                 if ($pid == -1) {
                                      // No child waiting.
                                 } else {
                                      if (pcntl_wifexited($signal)) {
                                          echo 'Process $pid exited';

• defunct process               
                                  
                                      } else {
                                          echo 'False alarm on $pid';
                                      }

• child has finished but         
                                      // Check if more children ended
                                      reaper($signal);
  is still in process table        }
                                 pcntl_signal(SIGCHLD, 'reaper');
                              }

• exec wait system call       // Install signal handler on SIGCHLD
                              pcntl_signal(SIGCHLD, 'reaper');

• reaper for SIGCHLD
                              // If there is no need to know when a

• pcntl_signal(SIGCHLD,       // child has finished, you don’t need
                              // to use the reaper, use SIG_IGN:

  SIG_IGN);                   pcntl_signal(SIGCHLD, SIG_IGN);
parallel processing




 photo by Christian Guthier - http://www.flickr.com/photos/wheatfields/116810137
parallel processing
• concurrent processing
• spread work over
  multiple processes

• daemonize parent
• create children
• do not change SID!
                       photo : istockphoto
step 1 : daemonize parent
// Daemonize the parent
$pid = pcntl_fork();
if ($pid == -1) {
    writeToLog('Could not daemonize!');
    exit(1);
} elseif ($pid > 0) {
    writeToLog('Daemonized to ' . $pid);
    exit(0);
} else { // Daemonized
     umask(0); 
     $sid = posix_setsid(); 
     if ($sid < 0) {
         writeToLog('Could not detach session id.');
         exit(1);
     }
}
step 2 : create children
$parentPid = getmypid();

// Create our children
for ($i = 0; $i < MAX_CHILDREN; $i++) {
    if (getmypid() == $parentPid) {
        $pids[] = $pid = pcntl_fork(); // SPAWN NEW CHILD
        if ($pid < 0) {
            writeToLog('Could not fork!');
            exit(1);
        }
    }
}

if (getmypid() == $parentPid) {
    // Parent Code
} else {
    // Child Code
}
distributed scripting




 photo by Christian Guthier - http://www.flickr.com/photos/wheatfields/116810137
distribution?
• parallel processing on
  multiple servers

• spread the load
• more efficient
• easier to scale
Gearman
• application framework
• farm out work
• open source
• multi-language
• fast
• flexible
ØMQ
• socket library
• designed for high
    load / low latency

• flexible & advanced
• complicated
•   http://vimeo.com/20605470
RabbitMQ
• broker architecture
• central node
• easy to use & deploy
• less scalable
• slower
Apache ActiveMQ
• middle ground
• broker architecture
• p2p architecture
• easier to implement
• less performant
Apache hadoop
• process large datasets
• MapReduce
• local processing &
    storage

• failures detection at
    application level
•   http://vimeo.com/20955076
need more information on distribution?

• see workshop “Think like an ant, distribute the
  workload” by Helgi Þormar Þorbjörnsson

• Video : http://vimeo.com/41013062
• Slides : http://www.slideshare.net/helgith/scale-
  like-an-ant-distribute-the-workload-dpc-
  amsterdam-2011
please rate my talk
https://joind.in/6226

  twitter : @jkeppens
    blog : blog.amazium.com

Contenu connexe

Tendances

Python client api
Python client apiPython client api
Python client apidreampuf
 
SPL: The Missing Link in Development
SPL: The Missing Link in DevelopmentSPL: The Missing Link in Development
SPL: The Missing Link in Developmentjsmith92
 
Static Optimization of PHP bytecode (PHPSC 2017)
Static Optimization of PHP bytecode (PHPSC 2017)Static Optimization of PHP bytecode (PHPSC 2017)
Static Optimization of PHP bytecode (PHPSC 2017)Nikita Popov
 
Php tips-and-tricks4128
Php tips-and-tricks4128Php tips-and-tricks4128
Php tips-and-tricks4128PrinceGuru MS
 
Corephpcomponentpresentation 1211425966721657-8
Corephpcomponentpresentation 1211425966721657-8Corephpcomponentpresentation 1211425966721657-8
Corephpcomponentpresentation 1211425966721657-8PrinceGuru MS
 
Looping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsLooping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsMark Baker
 
Bioinformatics p5-bioperl v2013-wim_vancriekinge
Bioinformatics p5-bioperl v2013-wim_vancriekingeBioinformatics p5-bioperl v2013-wim_vancriekinge
Bioinformatics p5-bioperl v2013-wim_vancriekingeProf. Wim Van Criekinge
 
A Functional Guide to Cat Herding with PHP Generators
A Functional Guide to Cat Herding with PHP GeneratorsA Functional Guide to Cat Herding with PHP Generators
A Functional Guide to Cat Herding with PHP GeneratorsMark Baker
 
PHP 5.3 and Lithium: the most rad php framework
PHP 5.3 and Lithium: the most rad php frameworkPHP 5.3 and Lithium: the most rad php framework
PHP 5.3 and Lithium: the most rad php frameworkG Woo
 
The Zen of Lithium
The Zen of LithiumThe Zen of Lithium
The Zen of LithiumNate Abele
 
Dependency injection - phpday 2010
Dependency injection - phpday 2010Dependency injection - phpday 2010
Dependency injection - phpday 2010Fabien Potencier
 
PHP 7 – What changed internally? (Forum PHP 2015)
PHP 7 – What changed internally? (Forum PHP 2015)PHP 7 – What changed internally? (Forum PHP 2015)
PHP 7 – What changed internally? (Forum PHP 2015)Nikita Popov
 
News of the Symfony2 World
News of the Symfony2 WorldNews of the Symfony2 World
News of the Symfony2 WorldFabien Potencier
 
PHP 5.3 Overview
PHP 5.3 OverviewPHP 5.3 Overview
PHP 5.3 Overviewjsmith92
 
Descobrindo a linguagem Perl
Descobrindo a linguagem PerlDescobrindo a linguagem Perl
Descobrindo a linguagem Perlgarux
 

Tendances (20)

Python client api
Python client apiPython client api
Python client api
 
SPL: The Missing Link in Development
SPL: The Missing Link in DevelopmentSPL: The Missing Link in Development
SPL: The Missing Link in Development
 
Static Optimization of PHP bytecode (PHPSC 2017)
Static Optimization of PHP bytecode (PHPSC 2017)Static Optimization of PHP bytecode (PHPSC 2017)
Static Optimization of PHP bytecode (PHPSC 2017)
 
Php tips-and-tricks4128
Php tips-and-tricks4128Php tips-and-tricks4128
Php tips-and-tricks4128
 
Corephpcomponentpresentation 1211425966721657-8
Corephpcomponentpresentation 1211425966721657-8Corephpcomponentpresentation 1211425966721657-8
Corephpcomponentpresentation 1211425966721657-8
 
Looping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsLooping the Loop with SPL Iterators
Looping the Loop with SPL Iterators
 
Bioinformatics p5-bioperl v2013-wim_vancriekinge
Bioinformatics p5-bioperl v2013-wim_vancriekingeBioinformatics p5-bioperl v2013-wim_vancriekinge
Bioinformatics p5-bioperl v2013-wim_vancriekinge
 
Bioinformatica p6-bioperl
Bioinformatica p6-bioperlBioinformatica p6-bioperl
Bioinformatica p6-bioperl
 
A Functional Guide to Cat Herding with PHP Generators
A Functional Guide to Cat Herding with PHP GeneratorsA Functional Guide to Cat Herding with PHP Generators
A Functional Guide to Cat Herding with PHP Generators
 
PHP 5.3 and Lithium: the most rad php framework
PHP 5.3 and Lithium: the most rad php frameworkPHP 5.3 and Lithium: the most rad php framework
PHP 5.3 and Lithium: the most rad php framework
 
The Zen of Lithium
The Zen of LithiumThe Zen of Lithium
The Zen of Lithium
 
ReUse Your (Puppet) Modules!
ReUse Your (Puppet) Modules!ReUse Your (Puppet) Modules!
ReUse Your (Puppet) Modules!
 
Dependency injection - phpday 2010
Dependency injection - phpday 2010Dependency injection - phpday 2010
Dependency injection - phpday 2010
 
PHP 7 – What changed internally? (Forum PHP 2015)
PHP 7 – What changed internally? (Forum PHP 2015)PHP 7 – What changed internally? (Forum PHP 2015)
PHP 7 – What changed internally? (Forum PHP 2015)
 
Symfony2 - OSIDays 2010
Symfony2 - OSIDays 2010Symfony2 - OSIDays 2010
Symfony2 - OSIDays 2010
 
Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010
 
News of the Symfony2 World
News of the Symfony2 WorldNews of the Symfony2 World
News of the Symfony2 World
 
Anatomy of a reusable module
Anatomy of a reusable moduleAnatomy of a reusable module
Anatomy of a reusable module
 
PHP 5.3 Overview
PHP 5.3 OverviewPHP 5.3 Overview
PHP 5.3 Overview
 
Descobrindo a linguagem Perl
Descobrindo a linguagem PerlDescobrindo a linguagem Perl
Descobrindo a linguagem Perl
 

Similaire à DPC 2012 : PHP in the Dark Workshop

関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐいHisateru Tanaka
 
Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2Shinya Ohyanagi
 
CLI, the other SAPI phpnw11
CLI, the other SAPI phpnw11CLI, the other SAPI phpnw11
CLI, the other SAPI phpnw11Combell NV
 
Cli the other SAPI confoo11
Cli the other SAPI confoo11Cli the other SAPI confoo11
Cli the other SAPI confoo11Combell NV
 
PHP Basics and Demo HackU
PHP Basics and Demo HackUPHP Basics and Demo HackU
PHP Basics and Demo HackUAnshu Prateek
 
Cli the other sapi pbc11
Cli the other sapi pbc11Cli the other sapi pbc11
Cli the other sapi pbc11Combell NV
 
autopkgtest lightning talk
autopkgtest lightning talkautopkgtest lightning talk
autopkgtest lightning talkmartin-pitt
 
Debugging: Rules & Tools
Debugging: Rules & ToolsDebugging: Rules & Tools
Debugging: Rules & ToolsIan Barber
 
Let's read code: the python-requests library
Let's read code: the python-requests libraryLet's read code: the python-requests library
Let's read code: the python-requests librarySusan Tan
 
Preparing for the next PHP version (5.6)
Preparing for the next PHP version (5.6)Preparing for the next PHP version (5.6)
Preparing for the next PHP version (5.6)Damien Seguy
 
第49回Php勉強会@関東 Datasource
第49回Php勉強会@関東 Datasource第49回Php勉強会@関東 Datasource
第49回Php勉強会@関東 DatasourceKaz Watanabe
 
Php on the desktop and php gtk2
Php on the desktop and php gtk2Php on the desktop and php gtk2
Php on the desktop and php gtk2Elizabeth Smith
 
Go Web Development
Go Web DevelopmentGo Web Development
Go Web DevelopmentCheng-Yi Yu
 

Similaire à DPC 2012 : PHP in the Dark Workshop (20)

関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい
 
Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2
 
CLI, the other SAPI phpnw11
CLI, the other SAPI phpnw11CLI, the other SAPI phpnw11
CLI, the other SAPI phpnw11
 
Perl basics for pentesters part 2
Perl basics for pentesters part 2Perl basics for pentesters part 2
Perl basics for pentesters part 2
 
Perl basics for Pentesters
Perl basics for PentestersPerl basics for Pentesters
Perl basics for Pentesters
 
Cli the other SAPI confoo11
Cli the other SAPI confoo11Cli the other SAPI confoo11
Cli the other SAPI confoo11
 
PHP Basics and Demo HackU
PHP Basics and Demo HackUPHP Basics and Demo HackU
PHP Basics and Demo HackU
 
Starting Out With PHP
Starting Out With PHPStarting Out With PHP
Starting Out With PHP
 
Cli the other sapi pbc11
Cli the other sapi pbc11Cli the other sapi pbc11
Cli the other sapi pbc11
 
autopkgtest lightning talk
autopkgtest lightning talkautopkgtest lightning talk
autopkgtest lightning talk
 
Drupal 8 migrate!
Drupal 8 migrate!Drupal 8 migrate!
Drupal 8 migrate!
 
Debugging: Rules & Tools
Debugging: Rules & ToolsDebugging: Rules & Tools
Debugging: Rules & Tools
 
Let's read code: the python-requests library
Let's read code: the python-requests libraryLet's read code: the python-requests library
Let's read code: the python-requests library
 
Puppet fundamentals
Puppet fundamentalsPuppet fundamentals
Puppet fundamentals
 
Preparing for the next PHP version (5.6)
Preparing for the next PHP version (5.6)Preparing for the next PHP version (5.6)
Preparing for the next PHP version (5.6)
 
Php Intermediate
Php IntermediatePhp Intermediate
Php Intermediate
 
第49回Php勉強会@関東 Datasource
第49回Php勉強会@関東 Datasource第49回Php勉強会@関東 Datasource
第49回Php勉強会@関東 Datasource
 
Blog Hacks 2011
Blog Hacks 2011Blog Hacks 2011
Blog Hacks 2011
 
Php on the desktop and php gtk2
Php on the desktop and php gtk2Php on the desktop and php gtk2
Php on the desktop and php gtk2
 
Go Web Development
Go Web DevelopmentGo Web Development
Go Web Development
 

Dernier

#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGSujit Pal
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxOnBoard
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 

Dernier (20)

#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAG
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptx
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 

DPC 2012 : PHP in the Dark Workshop

  • 1.
  • 2. Jeroen Keppens • Amazium bvba • Team Leader • Scrum Master • Senior PHP Developer • @jkeppens • blog.amazium.com
  • 3. Download code examples http://www.amazium.com/ phpinthedark.tgz
  • 4. shell scripting photo : istockphoto
  • 5. php-cli • server api (sapi) PHP Extensions • coordinates php lifecycle PHP CORE Zend Engine request mgmt Compile/Exec • command line interface network & file i/o Memory alloc • shebang SAPI (Server API) http://www.slideshare.net/combell/cli-the-other-sapi-confoo11
  • 6. globals • no $_POST, $_GET Array ( [TERM_PROGRAM] => Apple_Terminal [TERM] => xterm-color • no HTTP_* [SHELL] => /bin/bash [TERM_PROGRAM_VERSION] => 273 [USER] => jkeppens [COMMAND_MODE] => unix2003 • no REMOTE_* [PWD] => /Users/jkeppens [HOME] => /Users/jkeppens [LOGNAME] => jkeppens • no SERVER_* [LC_CTYPE] => UTF-8 [DISPLAY] => /tmp/launch-hr4Dxt/ org.x:0 • term / shell information [argv] => Array ( [0] => /tmp/ test.php ) [argc] => 1 ) • argv / argc
  • 7. cronjobs • schedule task ( crontab -u username -e ) * * * * * command to be executed | | | | | | | | | +----- day of week (0 - 6) (Sunday=0) | | | +------- month (1 - 12) | | +--------- day of month (1 - 31) | +----------- hour (0 - 23) +------------- min (0 - 59) • define constants, access via $_SERVER[‘name’] NAME = VALUE
  • 8. cronjobs ; define constants APPLICATION_ENVIRONMENT = development DB_SERVER = db1.somehost.com ; run every day at 4:30 30 4 * * * /path/to/somescript.php -daily ; run every 5 minutes */5 * * * * /path/to/somescript.php ; run every monday and thursday, at midnight and 9AM * 0,9 * * 1,4 /path/to/somescript
  • 9. input / output http://www.fotopedia.com/items/flickr-217097889
  • 10. the basics : argc | argv • $argc = number of arguments • $argv = array of arguments • first element = script filename photo by Kore Nordmann - http://kore-nordmann.de/photos/misc/full/elephpant_39.html
  • 11. the basics : argc | argv • $argc = number of // Number of arguments echo '$argc = '; arguments echo $argc . PHP_EOL; // Array of arguments • $argv = array of echo '$argv = '; print_r($argv); arguments • first element = script filename
  • 12. ./01-basic-input.php -u Jeroen -p test -h -v Text
  • 13. ./01-basic-input.php -u Jeroen -p test -h -v $argc = 7 $argv = Array ( [0] => ./01-basic-input.php [1] => -u [2] => Jeroen [3] => -p Text [4] => test [5] => -h [6] => -v )
  • 14. getopt ( ) • arguments are parsed • no validation • short options • long options since 5.3 • no, optional or required values photo by Martha de Jong-Lantink - http://www.fotopedia.com/wiki/Emperor_Penguin#!/items/flickr-2080338469
  • 15. // Define short options $short = "hv"; $short.= "u:"; // required getopt ( ) $short.= "p::"; // optional // Define long options $long  = array( "help", "verbose", • arguments are parsed     "user:", // required     "passwd::", // optional ); • no validation // Get the options (php 5.3) • short options $options = getopt(     $shortopts,     $longopts • long options since 5.3 ); • no, optional or // Show it print_r($options); required values
  • 17. ./02-basic-getopt.php -u Jeroen -h -ppasswd Array ( [u] => Jeroen [p] => passwd [h] => )
  • 18. ./02-basic-getopt.php -u Jeroen -h -ppasswd Array ( [u] => Jeroen [p] => passwd [h] => ) ./02-basic-getopt.php -u -h -p passwd
  • 19. ./02-basic-getopt.php -u Jeroen -h -ppasswd Array ( [u] => Jeroen [p] => passwd [h] => ) ./02-basic-getopt.php -u -h -p passwd Array ( [u] => -h [p] => )
  • 20. pear | getopt • Console_Getopt class • readPHPArgv ( ) • getopt ( ) • getopt2 ( ) • PEAR Errors • short / long options unlinked
  • 21. // Define short options $shortopts = "hv"; $shortopts.= "u:"; $shortopts.= "p::"; pear | getopt // Define long options $longopts  = array(     "help", "verbose",     "user=",     "password==", ); • Console_Getopt class $getopt = new Console_Getopt(); • readPHPArgv ( ) // Get the arguments & remove script $args = $getopt->readPHPArgv(); • getopt ( ) array_shift($args); // Parse the options • getopt2 ( ) $options = $getopt->getopt2(     $args, $shortopts, $longopts); • PEAR Errors if (PEAR::isError($options)) {     echo 'Got error: '; • short / long options unlinked     echo $options->getMessage(); } else {     print_r($options); }
  • 22. zend | getopt • Zend_Console_Getopt • options linked • value type validation • usage message • object returned • exceptions photo : istockphoto
  • 23. // Define short option $cfg = array(   "help|h"   => "Show help",   "verbose|v" => "Verbose mode", zend | getopt   "user|u=s"  => "Username (string)",   "password|p-s"   => "Password (string) (optional)" ); try {   $opts = new Zend_Console_Getopt($cfg); • Zend_Console_Getopt   $opts->parse();   if (!empty($opts->help)) {     echo $opts->getUsageMessage(); • options linked   } else {     $user  = $opts->user;     $passwd  = $opts->password; • value type validation     $verbose = !empty($opts->v);     echo "Log in [$user / $passwd]";     if ($verbose) {       echo " in verbose mode"; • usage message     }   } }  • object returned catch (Zend_Console_Getopt_Exception $e)  {   echo $opts->getUsageMessage(); • exceptions }
  • 25. ./03-zend-getopt.php -h Usage: ./03-zend-getopt.php [ options ] --help|-h Show help --verbose|-v Verbose mode --user|-u <string> Username (string) --password|-p [ <string> ] Password (string) (optional)
  • 26. readline • interactive input • GNU Readline library • auto-completion • command history • callback functions photo by Gracey Heart - http://www.flickr.com/photos/graceyheartphotography/5552036368/
  • 27. // Autocompletion function autocomplete() { return array('history', 'clear', 'cls', 'quit', 'exit'); } readline_completion_function('autocomplete'); // Initiate history if (is_file($historyFile)) readline_read_history($historyFile); while (true) {    $line = strtolower(trim(readline('Command: ')));    echo 'Received [ ' . $line . ' ]' . PHP_EOL;    readline_add_history($line); // add command to history   switch ($line) {       case 'clear': case 'cls':         readline_clear_history(); break;      case 'history': print_r(readline_list_history()); break;         case 'quit': case 'exit':             break 2;     } } readline_write_history($historyFile); // Write back to disk
  • 28. // Autocompletion function autocomplete() { return array('history', 'clear', 'cls', 'quit', 'exit'); } readline_completion_function('autocomplete'); // Initiate history if (is_file($historyFile)) readline_read_history($historyFile); while (true) {    $line = strtolower(trim(readline('Command: ')));    echo 'Received [ ' . $line . ' ]' . PHP_EOL;    readline_add_history($line); // add command to history   switch ($line) {       case 'clear': case 'cls':         readline_clear_history(); break;      case 'history': print_r(readline_list_history()); break;         case 'quit': case 'exit':             break 2;     } } readline_write_history($historyFile); // Write back to disk
  • 29. // Autocompletion function autocomplete() { return array('history', 'clear', 'cls', 'quit', 'exit'); } readline_completion_function('autocomplete'); // Initiate history if (is_file($historyFile)) readline_read_history($historyFile); while (true) {    $line = strtolower(trim(readline('Command: ')));    echo 'Received [ ' . $line . ' ]' . PHP_EOL;    readline_add_history($line); // add command to history   switch ($line) {       case 'clear': case 'cls':         readline_clear_history(); break;      case 'history': print_r(readline_list_history()); break;         case 'quit': case 'exit':             break 2;     } } readline_write_history($historyFile); // Write back to disk
  • 30. // Autocompletion function autocomplete() { return array('history', 'clear', 'cls', 'quit', 'exit'); } readline_completion_function('autocomplete'); // Initiate history if (is_file($historyFile)) readline_read_history($historyFile); while (true) {    $line = strtolower(trim(readline('Command: ')));    echo 'Received [ ' . $line . ' ]' . PHP_EOL;    readline_add_history($line); // add command to history   switch ($line) {       case 'clear': case 'cls':         readline_clear_history(); break;      case 'history': print_r(readline_list_history()); break;         case 'quit': case 'exit':             break 2;     } } readline_write_history($historyFile); // Write back to disk
  • 31. // Autocompletion function autocomplete() { return array('history', 'clear', 'cls', 'quit', 'exit'); } readline_completion_function('autocomplete'); // Initiate history if (is_file($historyFile)) readline_read_history($historyFile); while (true) {    $line = strtolower(trim(readline('Command: ')));    echo 'Received [ ' . $line . ' ]' . PHP_EOL;    readline_add_history($line); // add command to history   switch ($line) {       case 'clear': case 'cls':         readline_clear_history(); break;      case 'history': print_r(readline_list_history()); break;         case 'quit': case 'exit':             break 2;     } } readline_write_history($historyFile); // Write back to disk
  • 32. // Autocompletion function autocomplete() { return array('history', 'clear', 'cls', 'quit', 'exit'); } readline_completion_function('autocomplete'); // Initiate history if (is_file($historyFile)) readline_read_history($historyFile); while (true) {    $line = strtolower(trim(readline('Command: ')));    echo 'Received [ ' . $line . ' ]' . PHP_EOL;    readline_add_history($line); // add command to history   switch ($line) {       case 'clear': case 'cls':         readline_clear_history(); break;      case 'history': print_r(readline_list_history()); break;         case 'quit': case 'exit':             break 2;     } } readline_write_history($historyFile); // Write back to disk
  • 33. // Autocompletion function autocomplete() { return array('history', 'clear', 'cls', 'quit', 'exit'); } readline_completion_function('autocomplete'); // Initiate history if (is_file($historyFile)) readline_read_history($historyFile); while (true) {    $line = strtolower(trim(readline('Command: ')));    echo 'Received [ ' . $line . ' ]' . PHP_EOL;    readline_add_history($line); // add command to history   switch ($line) {       case 'clear': case 'cls':         readline_clear_history(); break;      case 'history': print_r(readline_list_history()); break;         case 'quit': case 'exit':             break 2;     } } readline_write_history($historyFile); // Write back to disk
  • 34. // Autocompletion function autocomplete() { return array('history', 'clear', 'cls', 'quit', 'exit'); } readline_completion_function('autocomplete'); // Initiate history if (is_file($historyFile)) readline_read_history($historyFile); while (true) {    $line = strtolower(trim(readline('Command: ')));    echo 'Received [ ' . $line . ' ]' . PHP_EOL;    readline_add_history($line); // add command to history   switch ($line) {       case 'clear': case 'cls':         readline_clear_history(); break;      case 'history': print_r(readline_list_history()); break;         case 'quit': case 'exit':             break 2;     } } readline_write_history($historyFile); // Write back to disk
  • 35. // Autocompletion function autocomplete() { return array('history', 'clear', 'cls', 'quit', 'exit'); } readline_completion_function('autocomplete'); // Initiate history if (is_file($historyFile)) readline_read_history($historyFile); while (true) {    $line = strtolower(trim(readline('Command: ')));    echo 'Received [ ' . $line . ' ]' . PHP_EOL;    readline_add_history($line); // add command to history   switch ($line) {       case 'clear': case 'cls':         readline_clear_history(); break;      case 'history': print_r(readline_list_history()); break;         case 'quit': case 'exit':             break 2;     } } readline_write_history($historyFile); // Write back to disk
  • 36. output helpers • pear Console_* • ez consoletools • text formatting • progressbars • tables
  • 37. ncurses • terminfo format • padding • coloring • windows • keyboard / mouse input • alternative: whiptail
  • 38. daemons photo by PSA Peugeot Citroen - http://bit.ly/peugeot-car-welding
  • 39. steps to create a daemon • Fork off the parent process
  • 40. steps to create a daemon • Fork off the parent process • Change the file mode mask
  • 41. steps to create a daemon • Fork off the parent process • Change the file mode mask • Open any logs for writing
  • 42. steps to create a daemon • Fork off the parent process • Change the file mode mask • Open any logs for writing • Create a new session id & detach current session
  • 43. steps to create a daemon • Fork off the parent process • Change the file mode mask • Open any logs for writing • Create a new session id & detach current session • Change the current working directory
  • 44. steps to create a daemon • Fork off the parent process • Change the file mode mask • Open any logs for writing • Create a new session id & detach current session • Change the current working directory • Close standard file descriptors
  • 45. fork off the parent process • pcntl_fork ( ) • creates copy of parent • different pid & ppid • [pid] : parent process • 0 : child process • -1 : error forking photo by Conan (conanil) - http://www.flickr.com/photos/conanil/1215118030/
  • 46. fork off the parent process • pcntl_fork ( ) // We fork the script $pid = pcntl_fork(); • creates copy of parent // We add our daemon & // child code • different pid & ppid if ($pid == -1) {     die('Could not fork!'); • [pid] : parent process } elseif ($pid) {     // we are the child } else { • 0 : child process     // we are the parent } • -1 : error forking
  • 47. change the file mode mask • umask (mask) • mask: octal notation • system umask & mask • revoke permissions • 0: reset to system mask • dirs: 0777, files: 0666 photo by The Mad Hatter - http://www.lauraleeburch.com/blog/2010/05/the-mad-hatter-2/
  • 48. change the file mode mask • umask (mask) // system umask = 0022 touch($testFile); // resulting permissions: • mask: octal notation // 0666 - 0022 = 0644 • system umask & mask // remove test file unlink($testFile); • revoke permissions // reset umask = 0007 umask(0007); • 0: reset to system mask touch($testFile); // resulting permissions: • dirs: 0777, files: 0666 // 0666 - 0007 = 0660
  • 49. Open any logs for writing • no feedback via shell • debug info via logs • logging via • database • logfiles • syslogd photo by Miranda Hine - http://www.flickr.com/photos/mirandahine/5500665022
  • 50. Open any logs for writing • no feedback via shell // open syslog wth processID openlog('SyslogTest',  LOG_PID | LOG_PERROR,  • debug info via logs LOG_LOCAL0); • logging via $access = date('H:i:s'); syslog(LOG_WARNING, 'Data  • database was accessed @ ' . $access); closelog(); • logfiles // Oct 20 15:36:12 amazium • syslogd SyslogTest[11785]: Data was accessed @ 15:36:12
  • 51. Create a new session id • acquire unique SID • avoid system orphans • posix_setsid ( ) • sid on success • -1 on error photo by Notch Brewing - http://www.notchsession.com
  • 52. Create a new session id • acquire unique SID // Forked, client part // let's detach • avoid system orphans $sid = posix_setsid(); • posix_setsid ( ) // Die on failure to detach if ($sid < 0) { • sid on success     die('Could not detach  session id.'); } • -1 on error
  • 53. Change current working dir • daemon can be started from any location • mounts can disappear • change cwd to a safe location • getcwd ( ) • chdir ( ) photo by Majeq - http://majeq.deviantart.com/art/Broken-Bridge-Speedy-176766406
  • 54. Close standard file descriptors • STDIN, STDOUT, STDERR • inherited from parent • unknown targets • i.e. output still to shell • close & reconnect file descriptors with fclose & fopen photo : istockphoto
  • 56. $pid = pcntl_fork(); if ($pid > 1) {     exit(0); } elseif ($pid == 0) {     umask(0);     openlog('MyLog', LOG_PID | LOG_PERROR, LOG_LOCAL0);     $sid = posix_setsid();     if ($sid < 0) {         syslog(LOG_ERROR, 'Could not detach session id.');         exit(1);     }     chdir(dirname(__FILE__)); Text     fclose(STDIN); fclose(STDOUT); fclose(STDERR);     $fdIN  = fopen('/dev/null', 'r');     $fdOUT = fopen($logfile, 'a');     $fdERR = fopen('php://stdout', 'a');     while (true) { /* ... */ }     closelog(); exit(0); }
  • 57. $pid = pcntl_fork(); fork off the parent process if ($pid > 1) {     exit(0); } elseif ($pid == 0) {     umask(0);     openlog('MyLog', LOG_PID | LOG_PERROR, LOG_LOCAL0);     $sid = posix_setsid();     if ($sid < 0) {         syslog(LOG_ERROR, 'Could not detach session id.');         exit(1);     }     chdir(dirname(__FILE__)); Text     fclose(STDIN); fclose(STDOUT); fclose(STDERR);     $fdIN  = fopen('/dev/null', 'r');     $fdOUT = fopen($logfile, 'a');     $fdERR = fopen('php://stdout', 'a');     while (true) { /* ... */ }     closelog(); exit(0); }
  • 58. $pid = pcntl_fork(); set the user creation mask if ($pid > 1) {     exit(0); } elseif ($pid == 0) {     umask(0);     openlog('MyLog', LOG_PID | LOG_PERROR, LOG_LOCAL0);     $sid = posix_setsid();     if ($sid < 0) {         syslog(LOG_ERROR, 'Could not detach session id.');         exit(1);     }     chdir(dirname(__FILE__)); Text     fclose(STDIN); fclose(STDOUT); fclose(STDERR);     $fdIN  = fopen('/dev/null', 'r');     $fdOUT = fopen($logfile, 'a');     $fdERR = fopen('php://stdout', 'a');     while (true) { /* ... */ }     closelog(); exit(0); }
  • 59. $pid = pcntl_fork(); open any log files if ($pid > 1) {     exit(0); } elseif ($pid == 0) {     umask(0);     openlog('MyLog', LOG_PID | LOG_PERROR, LOG_LOCAL0);     $sid = posix_setsid();     if ($sid < 0) {         syslog(LOG_ERROR, 'Could not detach session id.');         exit(1);     }     chdir(dirname(__FILE__)); Text     fclose(STDIN); fclose(STDOUT); fclose(STDERR);     $fdIN  = fopen('/dev/null', 'r');     $fdOUT = fopen($logfile, 'a');     $fdERR = fopen('php://stdout', 'a');     while (true) { /* ... */ }     closelog(); exit(0); }
  • 60. $pid = pcntl_fork(); detach current session if ($pid > 1) {     exit(0); } elseif ($pid == 0) {     umask(0);     openlog('MyLog', LOG_PID | LOG_PERROR, LOG_LOCAL0);     $sid = posix_setsid();     if ($sid < 0) {         syslog(LOG_ERROR, 'Could not detach session id.');         exit(1);     }     chdir(dirname(__FILE__)); Text     fclose(STDIN); fclose(STDOUT); fclose(STDERR);     $fdIN  = fopen('/dev/null', 'r');     $fdOUT = fopen($logfile, 'a');     $fdERR = fopen('php://stdout', 'a');     while (true) { /* ... */ }     closelog(); exit(0); }
  • 61. $pid = pcntl_fork(); change current working dir if ($pid > 1) {     exit(0); } elseif ($pid == 0) {     umask(0);     openlog('MyLog', LOG_PID | LOG_PERROR, LOG_LOCAL0);     $sid = posix_setsid();     if ($sid < 0) {         syslog(LOG_ERROR, 'Could not detach session id.');         exit(1);     }     chdir(dirname(__FILE__)); Text     fclose(STDIN); fclose(STDOUT); fclose(STDERR);     $fdIN  = fopen('/dev/null', 'r');     $fdOUT = fopen($logfile, 'a');     $fdERR = fopen('php://stdout', 'a');     while (true) { /* ... */ }     closelog(); exit(0); }
  • 62. $pid = pcntl_fork(); close open file descriptors if ($pid > 1) {     exit(0); } elseif ($pid == 0) {     umask(0);     openlog('MyLog', LOG_PID | LOG_PERROR, LOG_LOCAL0);     $sid = posix_setsid();     if ($sid < 0) {         syslog(LOG_ERROR, 'Could not detach session id.');         exit(1);     }     chdir(dirname(__FILE__)); Text     fclose(STDIN); fclose(STDOUT); fclose(STDERR);     $fdIN  = fopen('/dev/null', 'r');     $fdOUT = fopen($logfile, 'a');     $fdERR = fopen('php://stdout', 'a');     while (true) { /* ... */ }     closelog(); exit(0); }
  • 63. $pid = pcntl_fork(); payload if ($pid > 1) {     exit(0); } elseif ($pid == 0) {     umask(0);     openlog('MyLog', LOG_PID | LOG_PERROR, LOG_LOCAL0);     $sid = posix_setsid();     if ($sid < 0) {         syslog(LOG_ERROR, 'Could not detach session id.');         exit(1);     }     chdir(dirname(__FILE__)); Text     fclose(STDIN); fclose(STDOUT); fclose(STDERR);     $fdIN  = fopen('/dev/null', 'r');     $fdOUT = fopen($logfile, 'a');     $fdERR = fopen('php://stdout', 'a');     while (true) { /* ... */ }     closelog(); exit(0); }
  • 64. $pid = pcntl_fork(); if ($pid > 1) {     exit(0); } elseif ($pid == 0) {     umask(0);     openlog('MyLog', LOG_PID | LOG_PERROR, LOG_LOCAL0);     $sid = posix_setsid();     if ($sid < 0) {         syslog(LOG_ERROR, 'Could not detach session id.');         exit(1);     }     chdir(dirname(__FILE__)); Text     fclose(STDIN); fclose(STDOUT); fclose(STDERR);     $fdIN  = fopen('/dev/null', 'r');     $fdOUT = fopen($logfile, 'a');     $fdERR = fopen('php://stdout', 'a');     while (true) { /* ... */ }     closelog(); exit(0); }
  • 65. garbage collection • no garbage collection • since php 5.3: • gc_enable ( ) • gc_collect_cycles ( ) • clearstatcache ( ) • memory_get_usage ( ) photo by Rob Wallace - http://www.flickr.com/photos/robwallace/129263335
  • 66. pear | System_Daemon • hide complexity • start() = fork point • generate init.d scripts • More info see: http://kevin.vanzonneveld.net/techblog/ article/create_daemons_in_php/ photo by Rob Wallace - http://www.flickr.com/photos/robwallace/129263335
  • 67. Text
  • 69. signals • standard vs real-time • communication • alerts • timers • signal handling photo by Majeq - http://majeq.deviantart.com/art/Broken-Bridge-Speedy-176766406
  • 70. signals • SIGINT - CRTL-C • SIGTSTP - CTRL-Z • SIGQUIT - CTRL- • SIGTERM - kill [pid] • SIGKILL - kill -9 [pid] • SIGHUP - kill -hup [pid] • SIGUSR1 - kill -10 [pid] photo by Majeq - http://majeq.deviantart.com/art/Broken-Bridge-Speedy-176766406
  • 71. // SIGKILL to self $pid  = posix_getpid(); posix_kill($pid, 9); signals // SIGUSR1 to process group $pgrp = posix_getpgrp(); posix_kill($pgrp, SIGUSR1); • SIGINT - CRTL-C // SIGHUP to nr of processes $pids = array(/* .. */); • SIGTSTP - CTRL-Z foreach ($pids as $pid) {     posix_kill($pid, SIGHUP); • SIGQUIT - CTRL- } • SIGTERM - kill [pid] // Check process alive if (posix_kill($aPid, 0)) { • SIGKILL - kill -9 [pid]    echo "$aPid is alive!"; } else { • SIGHUP - kill -hup [pid]     echo "$aPid is dead."; } • SIGUSR1 - kill -10 [pid]
  • 72. declare(ticks = 1); function handler($signal) { global $doPing; signals     switch ($signal) {         case SIGTERM: case SIGQUIT:             echo "We’re done!n";             // handle shutdown tasks             exit(); break;         case SIGINT:             echo "Stop pinging!n"; • SIGINT - CRTL-C             $doPing = false; break;         case SIGUSR1: •             echo "Caught SIGUSR1!n"; SIGTSTP - CTRL-Z             break;     } • SIGQUIT - CTRL- } // Setup Signal Handlers pcntl_signal(SIGTERM, "handler"); • SIGTERM - kill [pid] pcntl_signal(SIGQUIT, "handler"); pcntl_signal(SIGINT,  "handler"); • pcntl_signal(SIGUSR1, "handler"); SIGKILL - kill -9 [pid] global $doPing; $doPing = true; • SIGHUP - kill -hup [pid] while ($doPing) { echo "Ping!" . PHP_EOL; } • SIGUSR1 - kill -10 [pid] // Send SIGUSR1 to current process id posix_kill(posix_getpid(), SIGUSR1);
  • 73. alerts & timers • pcntl_alarm ( ) • set alarm or timer • signals SIGALRM • each call cancels previous set alarm photo : istockphoto
  • 74. alerts & timers • pcntl_alarm ( ) declare(ticks = 1); function handler($signal) { • set alarm or timer     echo "Caught SIGALRMn";     pcntl_alarm(5); • signals SIGALRM } pcntl_signal(SIGALRM,  • each call cancels              'handler',               true); previous set alarm pcntl_alarm(5); while(1) { /* ... */ }
  • 75. shared memory • ftok for generating key • shm_* & shmop_* • shm php specific, shmop more generic • shmop is faster • shm has variables
  • 76. shared memory • ftok for generating key • shm_attach, shm_detach • shm_* & shmop_* • shm_has_var, • shm php specific, shm_get_var, shmop more generic shm_put_var, shm_remove_var • shmop is faster • shm has variables • shm_remove photo : istockphoto
  • 77.
  • 78. shared memory • ftok for generating key • shmop_open, shmop_close • shm_* & shmop_* • shmop_read, • shm php specific, shmop_write, shmop more generic shmop_delete • shmop is faster • shmop_size • shm has variables photo : istockphoto
  • 79.
  • 80. alternative shared memory • memcached • high performance • distributed • lightweight • object storage • server pooling
  • 81. resource access control • semaphores • provide exclusive access to resources • sem_* functions • specify number of allowed users
  • 82.
  • 83. message queues • semaphores • provide exclusive access to resources • sem_* functions • specify number of allowed users
  • 84. message queues • semaphores • msg_get_queue, msg_set_queue, • provide exclusive msg_queue_exists, access to resources msg_remove_queue • sem_* functions • msg_send, msg_receive, • specify number of msg_stat_queue allowed users photo : istockphoto
  • 85.
  • 86.
  • 87. ipcs | ipcrm | ipcmk • queues, semaphores, memory segments • ipcs : status • ipcmk : create • ipcrm : remove
  • 88.
  • 89. socket pairs • two connected sockets • stored in an array • 2-way communication • socket_create_pair • socket_read, socket_write photo : http://photo.net/photodb/photo?photo_id=11216293
  • 90.
  • 91. angels photo by DragoArt.com - http://www.dragoart.com/tuts/9270/1/1/how-to-draw-tattoo-angels,-angel-tattoos.htm
  • 92. monitoring • angel scripts • supervisord • runit • daemontools • beware for zombies! photo by Anthony Citrano - http://www.flickr.com/photos/zigzaglens/2956275907
  • 93. angel scripts • guardian angels • pid file present: check process is running • not running: (remove pid &) restart script • angel scheduled cron photo by Stu Hill Photography- www.flickr.com/photos/stuhillphotography/5526181346/
  • 94. foreach ($daemons as $daemon) {     if (file_exists($daemon['pidfile'])) {         $pid = trim(file_get_contents($daemon['pidfile']));         if (!empty($pid)) { // fake 0 signal to check if alive             if (posix_kill($pid, 0)) {                  continue; // Next check             }         }         @unlink($daemon['pidfile']);     }     $pid = pcntl_fork();     if ($pid === 0) {         $sid = posix_setsid();         if ($sid != -1) {             pcntl_exec($daemon['command'], $daemon['params']);         }     } }
  • 95. foreach ($daemons as $daemon) {     if (file_exists($daemon['pidfile'])) {         $pid = trim(file_get_contents($daemon['pidfile']));         if (!empty($pid)) { // fake 0 signal to check if alive             if (posix_kill($pid, 0)) {                  continue; // Next check             }         }         @unlink($daemon['pidfile']);     }     $pid = pcntl_fork();     if ($pid === 0) {         $sid = posix_setsid();         if ($sid != -1) {             pcntl_exec($daemon['command'], $daemon['params']);         }     } }
  • 96. foreach ($daemons as $daemon) {     if (file_exists($daemon['pidfile'])) {         $pid = trim(file_get_contents($daemon['pidfile']));         if (!empty($pid)) { // fake 0 signal to check if alive             if (posix_kill($pid, 0)) {                  continue; // Next check             }         }         @unlink($daemon['pidfile']);     }     $pid = pcntl_fork();     if ($pid === 0) {         $sid = posix_setsid();         if ($sid != -1) {             pcntl_exec($daemon['command'], $daemon['params']);         }     } }
  • 97. foreach ($daemons as $daemon) {     if (file_exists($daemon['pidfile'])) {         $pid = trim(file_get_contents($daemon['pidfile']));         if (!empty($pid)) { // fake 0 signal to check if alive             if (posix_kill($pid, 0)) {                  continue; // Next check             }         }         @unlink($daemon['pidfile']);     }     $pid = pcntl_fork();     if ($pid === 0) {         $sid = posix_setsid();         if ($sid != -1) {             pcntl_exec($daemon['command'], $daemon['params']);         }     } }
  • 98. foreach ($daemons as $daemon) {     if (file_exists($daemon['pidfile'])) {         $pid = trim(file_get_contents($daemon['pidfile']));         if (!empty($pid)) { // fake 0 signal to check if alive             if (posix_kill($pid, 0)) {                  continue; // Next check             }         }         @unlink($daemon['pidfile']);     }     $pid = pcntl_fork();     if ($pid === 0) {         $sid = posix_setsid();         if ($sid != -1) {             pcntl_exec($daemon['command'], $daemon['params']);         }     } }
  • 99. foreach ($daemons as $daemon) {     if (file_exists($daemon['pidfile'])) {         $pid = trim(file_get_contents($daemon['pidfile']));         if (!empty($pid)) { // fake 0 signal to check if alive             if (posix_kill($pid, 0)) {                  continue; // Next check             }         }         @unlink($daemon['pidfile']);     }     $pid = pcntl_fork();     if ($pid === 0) {         $sid = posix_setsid();         if ($sid != -1) {             pcntl_exec($daemon['command'], $daemon['params']);         }     } }
  • 100. foreach ($daemons as $daemon) {     if (file_exists($daemon['pidfile'])) {         $pid = trim(file_get_contents($daemon['pidfile']));         if (!empty($pid)) { // fake 0 signal to check if alive             if (posix_kill($pid, 0)) {                  continue; // Next check             }         }         @unlink($daemon['pidfile']);     }     $pid = pcntl_fork();     if ($pid === 0) {         $sid = posix_setsid();         if ($sid != -1) {             pcntl_exec($daemon['command'], $daemon['params']);         }     } }
  • 101. foreach ($daemons as $daemon) {     if (file_exists($daemon['pidfile'])) {         $pid = trim(file_get_contents($daemon['pidfile']));         if (!empty($pid)) { // fake 0 signal to check if alive             if (posix_kill($pid, 0)) {                  continue; // Next check             }         }         @unlink($daemon['pidfile']);     }     $pid = pcntl_fork();     if ($pid === 0) {         $sid = posix_setsid();         if ($sid != -1) {             pcntl_exec($daemon['command'], $daemon['params']);         }     } }
  • 102. foreach ($daemons as $daemon) {     if (file_exists($daemon['pidfile'])) {         $pid = trim(file_get_contents($daemon['pidfile']));         if (!empty($pid)) { // fake 0 signal to check if alive             if (posix_kill($pid, 0)) {                  continue; // Next check             }         }         @unlink($daemon['pidfile']);     }     $pid = pcntl_fork();     if ($pid === 0) {         $sid = posix_setsid();         if ($sid != -1) {             pcntl_exec($daemon['command'], $daemon['params']);         }     } }
  • 103. foreach ($daemons as $daemon) {     if (file_exists($daemon['pidfile'])) {         $pid = trim(file_get_contents($daemon['pidfile']));         if (!empty($pid)) { // fake 0 signal to check if alive             if (posix_kill($pid, 0)) {                  continue; // Next check             }         }         @unlink($daemon['pidfile']);     }     $pid = pcntl_fork();     if ($pid === 0) {         $sid = posix_setsid();         if ($sid != -1) {             pcntl_exec($daemon['command'], $daemon['params']);         }     } }
  • 104. foreach ($daemons as $daemon) {     if (file_exists($daemon['pidfile'])) {         $pid = trim(file_get_contents($daemon['pidfile']));         if (!empty($pid)) { // fake 0 signal to check if alive             if (posix_kill($pid, 0)) {                  continue; // Next check             }         }         @unlink($daemon['pidfile']);     }     $pid = pcntl_fork();     if ($pid === 0) {         $sid = posix_setsid();         if ($sid != -1) {             pcntl_exec($daemon['command'], $daemon['params']);         }     } }
  • 105. supervisord • process control system • simple • centralized • efficient • extensible • http://supervisord.org
  • 106. supervisord • process control system [program:gearman_tika] command=/path/to/script.php • simple autostart=true autorestart=true • centralized logfile=/var/log/myscript.log • efficient • extensible • http://supervisord.org
  • 107. monit • manage & monitor processes, files, directories & devices • restart failed daemons • control file with service entries or checks
  • 108. check process processQueues with pidfile "/var/ run/amazium/processQueues.pid" start = “/etc/init.d/processQueues start" stop = "/etc/init.d/processQueues stop" if does not exist then restart if cpu usage is greater than 60 percent for 2 cycles then alert if cpu usage > 98% for 5 cycles then restart if 2 restarts within 3 cycles then timeout alert foo@bar.baz
  • 109.
  • 110.
  • 111. daemontools • collection of tools to manage services • supervise : monitors a service • requires run script with code to start daemon
  • 112. zombies • defunct process • child has finished but is still in process table • reaper for SIGCHLD • pcntl_signal(SIGCHLD, SIG_IGN); wallpaper from Pozadia - http://dark.pozadia.org/wallpaper/Dawn-of-the-Zombies/
  • 113. // Reaper to clean up zombies function reaper($signal)  {    $pid = pcntl_waitpid(-1, zombies $status,  WNOHANG);    if ($pid == -1) {      // No child waiting.    } else { if (pcntl_wifexited($signal)) {      echo 'Process $pid exited'; • defunct process         } else { echo 'False alarm on $pid';    } • child has finished but    // Check if more children ended reaper($signal); is still in process table }    pcntl_signal(SIGCHLD, 'reaper'); } • exec wait system call // Install signal handler on SIGCHLD pcntl_signal(SIGCHLD, 'reaper'); • reaper for SIGCHLD // If there is no need to know when a • pcntl_signal(SIGCHLD, // child has finished, you don’t need // to use the reaper, use SIG_IGN: SIG_IGN); pcntl_signal(SIGCHLD, SIG_IGN);
  • 114. parallel processing photo by Christian Guthier - http://www.flickr.com/photos/wheatfields/116810137
  • 115. parallel processing • concurrent processing • spread work over multiple processes • daemonize parent • create children • do not change SID! photo : istockphoto
  • 116. step 1 : daemonize parent // Daemonize the parent $pid = pcntl_fork(); if ($pid == -1) {     writeToLog('Could not daemonize!');     exit(1); } elseif ($pid > 0) {     writeToLog('Daemonized to ' . $pid);     exit(0); } else { // Daemonized umask(0);  $sid = posix_setsid();  if ($sid < 0) {      writeToLog('Could not detach session id.');      exit(1); } }
  • 117. step 2 : create children $parentPid = getmypid(); // Create our children for ($i = 0; $i < MAX_CHILDREN; $i++) {     if (getmypid() == $parentPid) {         $pids[] = $pid = pcntl_fork(); // SPAWN NEW CHILD         if ($pid < 0) {             writeToLog('Could not fork!');             exit(1);         }     } } if (getmypid() == $parentPid) { // Parent Code } else { // Child Code }
  • 118. distributed scripting photo by Christian Guthier - http://www.flickr.com/photos/wheatfields/116810137
  • 119. distribution? • parallel processing on multiple servers • spread the load • more efficient • easier to scale
  • 120. Gearman • application framework • farm out work • open source • multi-language • fast • flexible
  • 121. ØMQ • socket library • designed for high load / low latency • flexible & advanced • complicated • http://vimeo.com/20605470
  • 122. RabbitMQ • broker architecture • central node • easy to use & deploy • less scalable • slower
  • 123. Apache ActiveMQ • middle ground • broker architecture • p2p architecture • easier to implement • less performant
  • 124. Apache hadoop • process large datasets • MapReduce • local processing & storage • failures detection at application level • http://vimeo.com/20955076
  • 125. need more information on distribution? • see workshop “Think like an ant, distribute the workload” by Helgi Þormar Þorbjörnsson • Video : http://vimeo.com/41013062 • Slides : http://www.slideshare.net/helgith/scale- like-an-ant-distribute-the-workload-dpc- amsterdam-2011
  • 126. please rate my talk https://joind.in/6226 twitter : @jkeppens blog : blog.amazium.com

Notes de l'éditeur

  1. \n
  2. \n
  3. \n
  4. When writing web applications, most of the action happens in a web context. But sometimes you need to support your application with scripts that run in the background.\nSome tasks can be generating reports, performing maintenance, loading external content, aggregating or analyzing data, sending out mass mailing, and much more.\nScripts performing these tasks, aren&amp;#x2019;t run via the browser. PHP CLI, short for Command Line Interface, is a special SAPI or Server API that allows you to run php scripts on the command line.\n
  5. The Server API or SAPI is responsible for coordinating the PHP lifecycle. You can look at it as the bridge between the web server or command line and php.\n\nThe sapi passes requests to PHP core, which will handle the requests, but is also responsible for low-level operations like file streams, error handling, etc...\n\nNext to this, we find the Zend Engine that parses and compiles the scripts we write and executes them in the Virtual Machine. \n\nAt times, Zend Engine hands over control to the extension layer where the php extension inject new functionality into php.\n
  6. When creating php scripts to run on the command line, you loose all functionality related to the web context. \n\nThis is mostly reflected in the php globals. $_GET and $_POST aren&amp;#x2019;t available anymore. $_SERVER is still there but is missing all web-related values. It did get terminal related information which can be quite useful at times.\n
  7. While you can run your scripts manually, one of the typical uses of the php on the command line is via the cron. Using cron, you can schedule when a specific script has to be executed.\n\nIt is possible to define constants which will be accessible in the $_SERVER global. We typically use this to pass on the application environment so the code knows which config to load from the ini files. \n
  8. At the top of this slide, you can see that I defined 2 constants.\n\nI also configured 3 scripts to run at specific times. I&amp;#x2019;m not going into this now, but you can always ask me after the presentation if you want more information.\n
  9. One of the key differences between web and command line scripts is the way they handle input/output. As said earlier, you don&amp;#x2019;t have access to the request globals, but your command line is also not able to display html in a nice way.\n
  10. The simplest way to do input, is using params that are passed when executing the script. 2 globals help you out with this, the first is $argc which holds the number of arguments and the other is $argv which is an array containing every argument.\n\nThe first element of the array is always the filename of the php script. As a result $argc is always 1 or bigger.\n\nYou can also find the argc and argv in the $_SERVER global array.\n
  11. So if we have a quick look at this script ...\n
  12. This gives following output. As you can see nothing is linked, it&amp;#x2019;s just an array with a bunch of values.\n\nWhile this might be good for very simple things, you usually wants something more.\n
  13. PHP has an implementation of the GNU getopt functions. Getopt allows you to parse arguments. Before php 5.3 only short options were possible, but since that, long options are also available.\n\nPer option you can define whether it has no value, an optional value or a required value. Whenever a value is optional, it needs to be attached to the short option, otherwise getopt will not be able to link it to the option.\n\nThere is no validation of the values entered and even in cases where you do something wrong, you don&amp;#x2019;t always receive an error.\n
  14. In this example you can see I defined the short options in a string and the long options in an array. I then pass this to getopt and receive an array of options.\n
  15. Let&amp;#x2019;s run this code. \n\nIn the first example, we provide a value for -u (which is required), and a value for -p (which is optional). As you can see, the value passwd is attached to the short option -p. The resulting array looks like we would expect it.\n\nLet&amp;#x2019;s mess things up a bit.\n\nIn the second example, I leave out the required value for -u and detach the value passwd for the short option -p. We don&amp;#x2019;t get an error, but a result that looks like this. \n\nAs you can see, -u has a value, which is the first argument following the option being -u. -p has no value, and the string &amp;#x201C;passwd&amp;#x201D; has been ignored.\n\nSo it&amp;#x2019;s already better than argv and argc, but there is still room for improvement.\n
  16. Let&amp;#x2019;s run this code. \n\nIn the first example, we provide a value for -u (which is required), and a value for -p (which is optional). As you can see, the value passwd is attached to the short option -p. The resulting array looks like we would expect it.\n\nLet&amp;#x2019;s mess things up a bit.\n\nIn the second example, I leave out the required value for -u and detach the value passwd for the short option -p. We don&amp;#x2019;t get an error, but a result that looks like this. \n\nAs you can see, -u has a value, which is the first argument following the option being -u. -p has no value, and the string &amp;#x201C;passwd&amp;#x201D; has been ignored.\n\nSo it&amp;#x2019;s already better than argv and argc, but there is still room for improvement.\n
  17. Let&amp;#x2019;s run this code. \n\nIn the first example, we provide a value for -u (which is required), and a value for -p (which is optional). As you can see, the value passwd is attached to the short option -p. The resulting array looks like we would expect it.\n\nLet&amp;#x2019;s mess things up a bit.\n\nIn the second example, I leave out the required value for -u and detach the value passwd for the short option -p. We don&amp;#x2019;t get an error, but a result that looks like this. \n\nAs you can see, -u has a value, which is the first argument following the option being -u. -p has no value, and the string &amp;#x201C;passwd&amp;#x201D; has been ignored.\n\nSo it&amp;#x2019;s already better than argv and argc, but there is still room for improvement.\n
  18. \n
  19. \n
  20. Pear, the ConsoleTools from EZ Components and Zend Framework each have there implementation of GetOpt. Personally I like the Zend Framework implementation best. The Zend_Console_Getopt class is a little gem. \n\nIt supports short and long options, which are linked. So it knows that -u and --user are the same thing. You can define a help message for each option and you can set whether value is required, optional or forbidden.\n\nThe class provides the getUsageMessage method which will generate a usage message based on the help messages you provided.\n\nAfter parsing the options, the options are available as properties. The properties are available with there short and long option name. These are aliases for each other, so even if you used -u with a value, you can access it on the return object using the user property.\n\nZend_Console_Getopt will throw exceptions in case of issues, so you can for instance show the usage message when this occurs. There are some extra features and if you need to know more, I suggest you check out the class reference on Zend Framework.\n\nLets have a look at a little code example.\n
  21. In contrast to the example for the basic getopt, you can see that the options are now linked together and that we provided a help message for each. This config array is passed when creating a new instance of Zend_Console_Getopt.\n\nAfter calling the parse method, we can now access the options via properties on the object. You can see we access help, user, password, but also v the short for verbose. When we get an exception or if the help option is provided, we display the usage message.\n\nWhen you run this code, it behaves as expected. But let&amp;#x2019;s have a quick look at the usage message, which is a nice feature.\n
  22. \n
  23. While command line arguments are one way to get input, it&amp;#x2019;s not always what you want. One of the strengths of the console is that you can interact with your user. It is possible to fiddle with input streams, but it&amp;#x2019;s not required.\n\nOn linux the GNU readline library does just that. It allows you to ask for information and read in what the customer provided. It has built in support for autocompletion and command history.\n\nIf you need interleaving of IO and user input, there is also support for callback handlers in combination with advanced stream stuff. But I haven&amp;#x2019;t tried that out yet myself. :)\n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. Pear, Zend Framework and the consoletools of EZ Components all provide functionality that allow you to make the output of your scripts a bit more attractive.\n\nThey allow for text formatting which includes coloring text and background, put text in bold or italics, underline texts and even supports blinking!\n\nThere is also support for progress bars and conversion of arrays into tables, including callback functionality on the table columns.\n\nI&amp;#x2019;ve added some examples from the pear console classes\n
  39. If you want to really go overboard, there is ncurses. Ncurses is also an implementation of a gnu library and allows you to create windows, it supports input from the mouse and keyboard, coloring, and much more.\n\nOne of the disadvantages of ncurses is that it&amp;#x2019;s documentation is really bad. If you want to use this, you might have to look at documentation of ncurses implementations in other languages or the linux manpages.\n\nJoshua Thijssen gave me an interesting tip about a linux command line tool called whiptail. The tool creates similar interfaces and it takes a lot of the work away from you. You can execute this from php, capture the return value and use this back in your script.\n
  40. Sometimes you need more. When I worked for Roulette69 we had a background process which analyzed real-time the games that were played, generated statistics and put those in memcache where they were picked up and showed to all players that were online.\n\nThe script responsible for this was a daemon. A daemon or service is basically a background process designed to run autonomously, with little or none user interaction.\n\nThe name has it&amp;#x2019;s origins in Greek mythology: daemons were neither good or evil, they were actually little spirits that did useful things for mankind.\n\nThe first time I created a daemon, I simply wrote a php script with an endless loop in it. Then I called it with an ampersand after the command, and it was sent to the background. It was easy.\n\nBut it was also bad. When you need a daemon, there are a couple of things you need to do to make sure it runs smoothly.\n
  41. Those 6 steps are:\n\n- Fork off the parent process\n- Change the file mode mask\n- Open any logs for writing\n- Create a new session id &amp; detach current session\n- Change the current working directory\n- Close standard file descriptors\n\nAfter you have taken care of this, you can add the payload, the code you actually want to execute.\n\nSo, what does this all mean?\n
  42. Those 6 steps are:\n\n- Fork off the parent process\n- Change the file mode mask\n- Open any logs for writing\n- Create a new session id &amp; detach current session\n- Change the current working directory\n- Close standard file descriptors\n\nAfter you have taken care of this, you can add the payload, the code you actually want to execute.\n\nSo, what does this all mean?\n
  43. Those 6 steps are:\n\n- Fork off the parent process\n- Change the file mode mask\n- Open any logs for writing\n- Create a new session id &amp; detach current session\n- Change the current working directory\n- Close standard file descriptors\n\nAfter you have taken care of this, you can add the payload, the code you actually want to execute.\n\nSo, what does this all mean?\n
  44. Those 6 steps are:\n\n- Fork off the parent process\n- Change the file mode mask\n- Open any logs for writing\n- Create a new session id &amp; detach current session\n- Change the current working directory\n- Close standard file descriptors\n\nAfter you have taken care of this, you can add the payload, the code you actually want to execute.\n\nSo, what does this all mean?\n
  45. Those 6 steps are:\n\n- Fork off the parent process\n- Change the file mode mask\n- Open any logs for writing\n- Create a new session id &amp; detach current session\n- Change the current working directory\n- Close standard file descriptors\n\nAfter you have taken care of this, you can add the payload, the code you actually want to execute.\n\nSo, what does this all mean?\n
  46. Those 6 steps are:\n\n- Fork off the parent process\n- Change the file mode mask\n- Open any logs for writing\n- Create a new session id &amp; detach current session\n- Change the current working directory\n- Close standard file descriptors\n\nAfter you have taken care of this, you can add the payload, the code you actually want to execute.\n\nSo, what does this all mean?\n
  47. Step one is forking of the parent process. A daemon can be started by the system itself or by a user on the terminal. When it is started, it behaves like an other executable on the system. To make it run autonomously, we must detach it from where it was started. You do this by creating a child process where the actual code is executed. This is known as forking.\nWhen you fork, you create a full copy of the original process. The original is called the parent, the copy the child. The only way they differ is in there process id (or pid) and their parent id (or ppid). \nThis also means that all variables initiated in the parent before the fork, are also available as is in the child&amp;#x2019;s thread of execution. This can lead to some unexpected and unwanted behaviours. For this reason, you always have to code as defensively as possible when working with daemons and do tons of error checking.\n
  48. When forking, we can have 3 return values:\n\nOn success, the PID of the child process is returned in the parent&amp;#x2019;s and 0 in the child&amp;#x2019;s thread of execution.\n\nOn failure, -1 is returned in the parent&amp;#x2019;s context, no child process will be created and a php error is raised.\n
  49. Our child process is a clone of the parent process up till the point of the fork. This means that amongst other things, we also inherited the umask of the parent. \n\nThe umask or user file creation mask limits the default permissions of newly created files and folders. The default permissions are 0777 (which stands for read/write/execute for all) on directories and 0666 (or read/write for all) on files. The system will typically set the umask to 0022. This means that it takes away the write access for group and other.\n\nThe child has no idea what the umask is set to, so it&amp;#x2019;s always good to reset it by using umask(0), even if we don&amp;#x2019;t plan to use it, so the daemon can write files (including logs) that receive the proper permissions.\n
  50. \n
  51. Since we don&amp;#x2019;t receive any feedback from the command line, we need an alternative: logging. This allows you to follow what is going on.\n\nLogging can happen to the database, to files or even using syslog.\n\n
  52. Syslog sends your log messages to a system wide logger, where they can be configured to be written to a file, send to a network server or filtered away entirely.\n\nI included a quick example for reference, but I&amp;#x2019;m not going to go into this right now.\n
  53. Each process on a unix or linux system is a member of a process group or session. The id of each group is the process id of it&amp;#x2019;s owner. \n\nAfter forking, the child inherits the process group of the parent. The child&amp;#x2019;s parent process id is equal to the parent&amp;#x2019;s process id.\n\nSince the parent is going to exit, the child needs to create its own process group and become its own process leader, otherwise it will become an orphan in the system.\n
  54. In php we detach our session using posix_setsid. Returns the new session_id on success or -1 on errors.\n
  55. You can already guess it. Our child also inherited the working directory of the parent.\n\nThe working directory could be a network mount, a removable drive or somewhere the administrator may want to unmount at some point.\n\nTo unmount any of these the system will have to kill any processes still using them, which would be unfortunate for our daemon.\n\nFor this reason we set our working directory to the root directory, which we are sure will always exist and can&amp;#x2019;t be unmounted.\n
  56. Since we detached the child from the terminal, it can&amp;#x2019;t interact with the user directly. As a consequence it has no use for the standard file descriptors STDIN, STDOUT and STDERR.\n\nAs with everything else, the file descriptors are inherited from the parent. The child has no idea what they are connected to. So we close the file descriptors. \n\nIf you don&amp;#x2019;t do this and you still have your terminal open after launching the daemon, you might get unwanted output from it at times.\n
  57. One of the cool things about the file descriptors is that after you have closed them, the system will reattach them to the firstly opened resources.\n\nThere is still little use to connect STDIN, so we point it to read from /dev/null.\n\nOn the other hand we reconnect the STDOUT &amp; STDERR to logfiles. Whenever you echo something to the screen, it will be written to the logfile.\n\n
  58. Let&amp;#x2019;s put it all together.\n
  59. Let&amp;#x2019;s put it all together.\n
  60. Let&amp;#x2019;s put it all together.\n
  61. Let&amp;#x2019;s put it all together.\n
  62. Let&amp;#x2019;s put it all together.\n
  63. Let&amp;#x2019;s put it all together.\n
  64. Let&amp;#x2019;s put it all together.\n
  65. Let&amp;#x2019;s put it all together.\n
  66. Let&amp;#x2019;s put it all together.\n
  67. Let&amp;#x2019;s put it all together.\n
  68. Let&amp;#x2019;s put it all together.\n
  69. Let&amp;#x2019;s put it all together.\n
  70. Let&amp;#x2019;s put it all together.\n
  71. Let&amp;#x2019;s put it all together.\n
  72. One of the things you need to keep in mind when writing daemons, is that you&amp;#x2019;re in it for the long run. Since php is typically used for short scripts, it doesn&amp;#x2019;t usually garbage collect during execution, but when the script has finished. This is problematic for daemons and can lead to a memory udage build up.\n\nBefore php 5.3 there wasn&amp;#x2019;t much you could do. Since then we got circular reference garbage collect which can make our lives a little easier. To get this to work, you need to decrease the reference count to chunks of memory by setting variables to null or by unsetting them.\n\nOnce in a while you should run gc_collect_cycles in your while loop to take out the trash. Don&amp;#x2019;t do this too often though.\n\nAnother thing to keep in mind is that php generates file statistics in the cache whenever it uses file functions. If you perform a lot of file operations on the same files in different runs of your loop, you will work on cached information instead of real-time information. If your daemon is running for a long time, this might ba problem, so you should run clearstatcache in regular intervals.\n
  73. One of the things you need to keep in mind when writing daemons, is that you&amp;#x2019;re in it for the long run. Since php is typically used for short scripts, it doesn&amp;#x2019;t usually garbage collect during execution, but when the script has finished. This is problematic for daemons and can lead to a memory udage build up.\n\nBefore php 5.3 there wasn&amp;#x2019;t much you could do. Since then we got circular reference garbage collect which can make our lives a little easier. To get this to work, you need to decrease the reference count to chunks of memory by setting variables to null or by unsetting them.\n\nOnce in a while you should run gc_collect_cycles in your while loop to take out the trash. Don&amp;#x2019;t do this too often though.\n\nAnother thing to keep in mind is that php generates file statistics in the cache whenever it uses file functions. If you perform a lot of file operations on the same files in different runs of your loop, you will work on cached information instead of real-time information. If your daemon is running for a long time, this might ba problem, so you should run clearstatcache in regular intervals.\n
  74. Let&amp;#x2019;s put it all together.\n
  75. IPC stands for Inter-process Communication.\nThis technique allows the processes to communicate with each another.\nSince each process has its own address space and unique user space, how does the process communicate each other?\nThe answer is Kernel, the heart of the Linux operating system that has access to the whole memory. So we can request the kernel to allocate the space which can be used to communicate between processes.The process can also communicate by having a file accessible to both the processes. Processes can open, and read/write the file, which requires lot of I/O operation that consumes time.\nDifferent Types of IPCS\nThere are various IPC&amp;#x2019;s which allows a process to communicate with another processes, either in the same computer or different computer in the same network.\nPipes &amp;#x2013; Provides a way for processes to communicate with each another by exchanging messages. Named pipes provide a way for processes running on different computer systems to communicate over the network.\nShared Memory &amp;#x2013; Processes can exchange values in the shared memory. One process will create a portion of memory which other process can access.\nMessage Queue &amp;#x2013; It is a structured and ordered list of memory segments where processes store or retrieve data.\nSemaphores &amp;#x2013; Provides a synchronizing mechanism for processes that are accessing the same resource. No data is passed with a semaphore; it simply coordinates access to shared resources.\n
  76. Sometimes you will need to communicate with a daemon process. One way to do so is by sending &amp;#x201C;signals&amp;#x201D;. There are a number of different signals you can send, some with a specific meaning, others interpreted by the application.\n\n
  77. To stop a process you can use SIGTERM and SIGKILL. Sigterm is the polite way to kill a script: you can catch it and end your daemon gracefully. You can&amp;#x2019;t catch sigkill.\nSIGHUP is typically a signal you send if you want the daemon to reinitialize (cfr. reloading logs).\nSIGINT typically gets triggered on system shutdown\nSIGUSR1 is typically a request to dump states to syslog\nSend signals from your script using posix_kill( $pid, $signal )\n
  78. To stop a process you can use SIGTERM and SIGKILL. Sigterm is the polite way to kill a script: you can catch it and end your daemon gracefully. You can&amp;#x2019;t catch sigkill.\nSIGHUP is typically a signal you send if you want the daemon to reinitialize (cfr. reloading logs).\nSIGINT typically gets triggered on system shutdown\nSIGUSR1 is typically a request to dump states to syslog\nSend signals from your script using posix_kill( $pid, $signal )\n
  79. To stop a process you can use SIGTERM and SIGKILL. Sigterm is the polite way to kill a script: you can catch it and end your daemon gracefully. You can&amp;#x2019;t catch sigkill.\nSIGHUP is typically a signal you send if you want the daemon to reinitialize (cfr. reloading logs).\nSIGINT typically gets triggered on system shutdown\nSIGUSR1 is typically a request to dump states to syslog\nSend signals from your script using posix_kill( $pid, $signal )\n
  80. \n
  81. \n
  82. Socket pairs provide a way to do bi-directional communication. It uses the socket_* functions in php.\n\nThe messaging functions may be used to send and receive messages to/from other processes. They provide a simple and effective means of exchanging data between processes, without the need for setting up an alternative using Unix domain sockets. \n\nmsg_* underneath semaphore functions in php docs.\n\n
  83. Socket pairs provide a way to do bi-directional communication. It uses the socket_* functions in php.\n\nThe messaging functions may be used to send and receive messages to/from other processes. They provide a simple and effective means of exchanging data between processes, without the need for setting up an alternative using Unix domain sockets. \n\nmsg_* underneath semaphore functions in php docs.\n\n
  84. http://www.thegeekstuff.com/2010/08/ipcs-command-examples/\n\nipcs is a UNIX / Linux command, which is used to list the information about the inter-process communication ipcs command provides a report on System V IPCS (Message queue, Semaphore, and Shared memory).\n\nShow:\n\nipcs -a : all facilities\nipcs -q : message queues\nipcs -m : memory segments\nipcs -s : semaphores\nipcs -m -i SHMID : detailed info for memory segment with SHMID\nipcs -l : lists system limits foreach ipc facility\nipcs -m -c : lists creator userid and groupid and owner userid and group id.\nipcs -m -p : displays creator id, and process id which accessed the corresponding ipc facility very recently.\n\n
  85. Socket pairs provide a way to do bi-directional communication. It uses the socket_* functions in php.\n\nThe messaging functions may be used to send and receive messages to/from other processes. They provide a simple and effective means of exchanging data between processes, without the need for setting up an alternative using Unix domain sockets. \n\nmsg_* underneath semaphore functions in php docs.\n\n
  86. http://www.thegeekstuff.com/2010/08/ipcs-command-examples/\n\nipcs is a UNIX / Linux command, which is used to list the information about the inter-process communication ipcs command provides a report on System V IPCS (Message queue, Semaphore, and Shared memory).\n\nShow:\n\nipcs -a : all facilities\nipcs -q : message queues\nipcs -m : memory segments\nipcs -s : semaphores\nipcs -m -i SHMID : detailed info for memory segment with SHMID\nipcs -l : lists system limits foreach ipc facility\nipcs -m -c : lists creator userid and groupid and owner userid and group id.\nipcs -m -p : displays creator id, and process id which accessed the corresponding ipc facility very recently.\n\n
  87. &amp;#x201C; memcached&amp;#xA0;is&amp;#xA0;a&amp;#xA0;high&amp;#xAD;performance,&amp;#xA0;distributed&amp;#xA0;\nmemory&amp;#xA0;object&amp;#xA0;caching&amp;#xA0;system,&amp;#xA0;generic in&amp;#xA0;nature,&amp;#xA0;but\nintended&amp;#xA0;for use in&amp;#xA0;speeding&amp;#xA0;up&amp;#xA0;dynamic&amp;#xA0;web&amp;#xA0;\napplications by alleviating&amp;#xA0;database load&amp;#x201D;.\n&amp;#x25CF; memcached&amp;#xA0;runs on every server in&amp;#xA0;the&amp;#xA0;web&amp;#xA0;server\nfarm.&amp;#xA0;It&amp;#xA0;is&amp;#xA0;CPU lightweight and&amp;#xA0;memory&amp;#xA0;&amp;#x201C; hungry&amp;#x201D;.\n\n\n
  88. Socket pairs provide a way to do bi-directional communication. It uses the socket_* functions in php.\n\nThe messaging functions may be used to send and receive messages to/from other processes. They provide a simple and effective means of exchanging data between processes, without the need for setting up an alternative using Unix domain sockets. \n\nmsg_* underneath semaphore functions in php docs.\n\n
  89. http://www.thegeekstuff.com/2010/08/ipcs-command-examples/\n\nipcs is a UNIX / Linux command, which is used to list the information about the inter-process communication ipcs command provides a report on System V IPCS (Message queue, Semaphore, and Shared memory).\n\nShow:\n\nipcs -a : all facilities\nipcs -q : message queues\nipcs -m : memory segments\nipcs -s : semaphores\nipcs -m -i SHMID : detailed info for memory segment with SHMID\nipcs -l : lists system limits foreach ipc facility\nipcs -m -c : lists creator userid and groupid and owner userid and group id.\nipcs -m -p : displays creator id, and process id which accessed the corresponding ipc facility very recently.\n\n
  90. \n
  91. \n
  92. http://www.thegeekstuff.com/2010/08/ipcs-command-examples/\n\nipcs is a UNIX / Linux command, which is used to list the information about the inter-process communication ipcs command provides a report on System V IPCS (Message queue, Semaphore, and Shared memory).\n\nShow:\n\nipcs -a : all facilities\nipcs -q : message queues\nipcs -m : memory segments\nipcs -s : semaphores\nipcs -m -i SHMID : detailed info for memory segment with SHMID\nipcs -l : lists system limits foreach ipc facility\nipcs -m -c : lists creator userid and groupid and owner userid and group id.\nipcs -m -p : displays creator id, and process id which accessed the corresponding ipc facility very recently.\n\n
  93. http://www.thegeekstuff.com/2010/08/ipcs-command-examples/\n\nipcs is a UNIX / Linux command, which is used to list the information about the inter-process communication ipcs command provides a report on System V IPCS (Message queue, Semaphore, and Shared memory).\n\nShow:\n\nipcs -a : all facilities\nipcs -q : message queues\nipcs -m : memory segments\nipcs -s : semaphores\nipcs -m -i SHMID : detailed info for memory segment with SHMID\nipcs -l : lists system limits foreach ipc facility\nipcs -m -c : lists creator userid and groupid and owner userid and group id.\nipcs -m -p : displays creator id, and process id which accessed the corresponding ipc facility very recently.\n\n
  94. http://www.thegeekstuff.com/2010/08/ipcs-command-examples/\n\nipcs is a UNIX / Linux command, which is used to list the information about the inter-process communication ipcs command provides a report on System V IPCS (Message queue, Semaphore, and Shared memory).\n\nShow:\n\nipcs -a : all \nipcs -q : message queues\nipcs -m : memory segments\nipcs -s : semaphores\nipcs -m -i SHMID : detailed info for memory segment with SHMID\nipcs -l : lists system limits foreach ipc facility\nipcs -m -c : lists creator userid and groupid and owner userid and group id.\nipcs -m -p : displays creator id, and process id which accessed the corresponding ipc facility very recently.\n\n
  95. http://www.thegeekstuff.com/2010/08/ipcs-command-examples/\n\nipcs is a UNIX / Linux command, which is used to list the information about the inter-process communication ipcs command provides a report on System V IPCS (Message queue, Semaphore, and Shared memory).\n\nShow:\n\nipcs -a : all facilities\nipcs -q : message queues\nipcs -m : memory segments\nipcs -s : semaphores\nipcs -m -i SHMID : detailed info for memory segment with SHMID\nipcs -l : lists system limits foreach ipc facility\nipcs -m -c : lists creator userid and groupid and owner userid and group id.\nipcs -m -p : displays creator id, and process id which accessed the corresponding ipc facility very recently.\n\n
  96. \n
  97. http://www.thegeekstuff.com/2010/08/ipcs-command-examples/\n\nipcs is a UNIX / Linux command, which is used to list the information about the inter-process communication ipcs command provides a report on System V IPCS (Message queue, Semaphore, and Shared memory).\n\nShow:\n\nipcs -a : all facilities\nipcs -q : message queues\nipcs -m : memory segments\nipcs -s : semaphores\nipcs -m -i SHMID : detailed info for memory segment with SHMID\nipcs -l : lists system limits foreach ipc facility\nipcs -m -c : lists creator userid and groupid and owner userid and group id.\nipcs -m -p : displays creator id, and process id which accessed the corresponding ipc facility very recently.\n\n
  98. \n
  99. \n
  100. \n
  101. The man/info page states that signal 0 is special and that the exit code from kill tells whether a signal could be sent to the specified process (or processes).\nSo kill -0 will not terminate the process, and the return status can be used to determine whether a process is running.\n\npcntl_exec &amp;#x2014; Executes specified program in current process space\n\n
  102. The man/info page states that signal 0 is special and that the exit code from kill tells whether a signal could be sent to the specified process (or processes).\nSo kill -0 will not terminate the process, and the return status can be used to determine whether a process is running.\n\npcntl_exec &amp;#x2014; Executes specified program in current process space\n\n
  103. The man/info page states that signal 0 is special and that the exit code from kill tells whether a signal could be sent to the specified process (or processes).\nSo kill -0 will not terminate the process, and the return status can be used to determine whether a process is running.\n\npcntl_exec &amp;#x2014; Executes specified program in current process space\n\n
  104. The man/info page states that signal 0 is special and that the exit code from kill tells whether a signal could be sent to the specified process (or processes).\nSo kill -0 will not terminate the process, and the return status can be used to determine whether a process is running.\n\npcntl_exec &amp;#x2014; Executes specified program in current process space\n\n
  105. The man/info page states that signal 0 is special and that the exit code from kill tells whether a signal could be sent to the specified process (or processes).\nSo kill -0 will not terminate the process, and the return status can be used to determine whether a process is running.\n\npcntl_exec &amp;#x2014; Executes specified program in current process space\n\n
  106. The man/info page states that signal 0 is special and that the exit code from kill tells whether a signal could be sent to the specified process (or processes).\nSo kill -0 will not terminate the process, and the return status can be used to determine whether a process is running.\n\npcntl_exec &amp;#x2014; Executes specified program in current process space\n\n
  107. The man/info page states that signal 0 is special and that the exit code from kill tells whether a signal could be sent to the specified process (or processes).\nSo kill -0 will not terminate the process, and the return status can be used to determine whether a process is running.\n\npcntl_exec &amp;#x2014; Executes specified program in current process space\n\n
  108. The man/info page states that signal 0 is special and that the exit code from kill tells whether a signal could be sent to the specified process (or processes).\nSo kill -0 will not terminate the process, and the return status can be used to determine whether a process is running.\n\npcntl_exec &amp;#x2014; Executes specified program in current process space\n\n
  109. The man/info page states that signal 0 is special and that the exit code from kill tells whether a signal could be sent to the specified process (or processes).\nSo kill -0 will not terminate the process, and the return status can be used to determine whether a process is running.\n\npcntl_exec &amp;#x2014; Executes specified program in current process space\n\n
  110. The man/info page states that signal 0 is special and that the exit code from kill tells whether a signal could be sent to the specified process (or processes).\nSo kill -0 will not terminate the process, and the return status can be used to determine whether a process is running.\n\npcntl_exec &amp;#x2014; Executes specified program in current process space\n\n
  111. The man/info page states that signal 0 is special and that the exit code from kill tells whether a signal could be sent to the specified process (or processes).\nSo kill -0 will not terminate the process, and the return status can be used to determine whether a process is running.\n\npcntl_exec &amp;#x2014; Executes specified program in current process space\n\n
  112. The man/info page states that signal 0 is special and that the exit code from kill tells whether a signal could be sent to the specified process (or processes).\nSo kill -0 will not terminate the process, and the return status can be used to determine whether a process is running.\n\npcntl_exec &amp;#x2014; Executes specified program in current process space\n\n
  113. The man/info page states that signal 0 is special and that the exit code from kill tells whether a signal could be sent to the specified process (or processes).\nSo kill -0 will not terminate the process, and the return status can be used to determine whether a process is running.\n\npcntl_exec &amp;#x2014; Executes specified program in current process space\n\n
  114. The man/info page states that signal 0 is special and that the exit code from kill tells whether a signal could be sent to the specified process (or processes).\nSo kill -0 will not terminate the process, and the return status can be used to determine whether a process is running.\n\npcntl_exec &amp;#x2014; Executes specified program in current process space\n\n
  115. The man/info page states that signal 0 is special and that the exit code from kill tells whether a signal could be sent to the specified process (or processes).\nSo kill -0 will not terminate the process, and the return status can be used to determine whether a process is running.\n\npcntl_exec &amp;#x2014; Executes specified program in current process space\n\n
  116. The man/info page states that signal 0 is special and that the exit code from kill tells whether a signal could be sent to the specified process (or processes).\nSo kill -0 will not terminate the process, and the return status can be used to determine whether a process is running.\n\npcntl_exec &amp;#x2014; Executes specified program in current process space\n\n
  117. The man/info page states that signal 0 is special and that the exit code from kill tells whether a signal could be sent to the specified process (or processes).\nSo kill -0 will not terminate the process, and the return status can be used to determine whether a process is running.\n\npcntl_exec &amp;#x2014; Executes specified program in current process space\n\n
  118. \n
  119. \n
  120. \n
  121. One of the cool things about the file descriptors is that after you have closed them, the system will reattach them to the firstly opened resources.\n\nThere is still little use to connect STDIN, so we point it to read from /dev/null.\n\nOn the other hand we reconnect the STDOUT &amp; STDERR to logfiles. Whenever you echo something to the screen, it will be written to the logfile.\n\n
  122. \n
  123. \n
  124. \n
  125. When a process ends, all of the memory and resources associated with it are deallocated so they can be used by other processes.\nA zombie process or defunct process is a process that has completed execution but still has an entry in the process table. This entry is still needed to allow the parent process to read the child&amp;#x2019;s exit status. The resources are not deallocated until the process is killed.\nThe parent can read the child&apos;s exit status by executing a wait system call, at which stage the zombie is removed. It is commonly executed in a SIGCHLD signal handler on the parent (SIGCHLD is received when a child has died).\nIf the parent explicitly ignores SIGCHLD by setting its handler to SIG_IGN, all child exit status information will be discarded and no zombie processes will be left\n
  126. -1 wait for any child process; this is the same behaviour that the wait function exhibits.\n pcntl_waitpid &amp;#x2014; Waits on or returns the status of a forked child\n WNOHANG return immediately if no child has exited.\n pcntl_wifexited &amp;#x2014; Checks if status code represents a normal exit\n
  127. Sometimes you need to do so much work that you could use an extra pair of hands. One of the way to do this is to start a script a number of times, but you loose some form of control. \n
  128. What you really want is a dynamic number of concurrent workers, that are managed by an overseer. This overseer can add new workers when he needs to, distribute work among on the workers, etc...\nSometimes people talk about &amp;#x201C;multi-threading&amp;#x201D; in php, well, this is what they mean. It is NOT multithreading, it&amp;#x2019;s parallel or concurrent processing.\nHow do you do this? You start of by daemonizing your overseer following the steps as we saw before. When that is done, you do another round of forking.\nYou fork of each worker. Important to note is that you don&amp;#x2019;t have to follow the steps we discussed earlier. One of the reasons we did, was that we were unsure of how the process was started. For the workers, we know and we are in full control.\nEspecially don&amp;#x2019;t change the session id, since you want all your workers to be in the same process group.\nLet&amp;#x2019;s have a very quick look at some code...\n
  129. \n
  130. \n
  131. Sometimes you need to do so much work that you could use an extra pair of hands. One of the way to do this is to start a script a number of times, but you loose some form of control. \n
  132. Gearman is a system to farm out work to other machines, dispatching function calls to machines that are better suited to do work, to do work in parallel, to load balance lots of function calls, or to call functions between languages.\n\n&amp;#xD8;MQ is a high-performance asynchronous messaging library aimed to use in scalable distributed or concurrent applications. It provides a message queue.\n\nThe Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using a simple programming model. It is designed to scale up from single servers to thousands of machines, each offering local computation and storage. Rather than rely on hardware to deliver high-avaiability, the library itself is designed to detect and handle failures at the application layer, so delivering a highly-availabile service on top of a cluster of computers, each of which may be prone to failures.\n
  133. Gearman is an application framework to farm out work to other machines, dispatching function calls to machines that are better suited to do work, to do work in parallel, to load balance lots of function calls, or to call functions between languages.\n\n&amp;#xD8;MQ is a high-performance asynchronous messaging library aimed to use in scalable distributed or concurrent applications. It provides a message queue.\n
  134. ZeroMq is a very lightweight messaging system specially designed for high throughput/low latency scenarios like the one you can find in the financial world. Zmq supports many advanced messaging scenarios but contrary to RabbitMQ, you&amp;#x2019;ll have to implement most of them yourself by combining various pieces of the framework (e.g : sockets and devices). Zmq is very flexible but you&amp;#x2019;ll have to study the 80 pages or so of the guide (which I recommend reading for anybody writing distributed system, even if you don&amp;#x2019;t use Zmq) before being able to do anything more complicated that sending messages between 2 peers.\n
  135. RabbitMQ implements a broker architecture, meaning that messages are queued on a central node before being sent to clients. This approach makes RabbitMQ very easy to use and deploy, because advanced scenarios like routing, load balancing or persistent message queuing are supported in just a few lines of code. However, it also makes it less scalable and &amp;#x201C;slower&amp;#x201D; because the central node adds latency and message envelopes are quite big.\n
  136. ActiveMQ is in the middle ground. Like Zmq, it can be deployed with both broker and P2P topologies. Like RabbitMQ, it&amp;#x2019;s easier to implement advanced scenarios but usually at the cost of raw performance. It&amp;#x2019;s the Swiss army knife of messaging\n
  137. The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using a simple programming model. It is designed to scale up from single servers to thousands of machines, each offering local computation and storage. Rather than rely on hardware to deliver high-avaiability, the library itself is designed to detect and handle failures at the application layer, so delivering a highly-availabile service on top of a cluster of computers, each of which may be prone to failures.\n
  138. Gearman is a system to farm out work to other machines, dispatching function calls to machines that are better suited to do work, to do work in parallel, to load balance lots of function calls, or to call functions between languages.\n\n&amp;#xD8;MQ is a high-performance asynchronous messaging library aimed to use in scalable distributed or concurrent applications. It provides a message queue.\n\nThe Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using a simple programming model. It is designed to scale up from single servers to thousands of machines, each offering local computation and storage. Rather than rely on hardware to deliver high-avaiability, the library itself is designed to detect and handle failures at the application layer, so delivering a highly-availabile service on top of a cluster of computers, each of which may be prone to failures.\n
  139. http://pleac.sourceforge.net/pleac_php/processmanagementetc.html\n