Long Live PHP Command Line as Daemon

General discussion on PHP

Long Live PHP Command Line as Daemon

Postby rampog on Fri Dec 28, 2012 2:40 am

Hi All,
anyone has been ever develop service might be for realtime email notification in command line & queueing in such as storage(db,file,mqueue).
sample architecture
while(true){
//do send mail
}
is there any concern that i've to consider for doing this,i prefer building this, instead of i build with OS/Linux facilities not long live which is
there is limitation timing max every one minute in scheduler could not be every second.
please advice
rampog
 
Posts: 56
Joined: Mon May 04, 2009 12:15 pm

Re: Long Live PHP Command Line as Daemon

Postby tedtiger on Fri Dec 28, 2012 9:53 am

Hi,

we used kevin von zonefelds script. Link is included in the source code.
The script spawns a main process with several childs (number can be adjusted but take ram usage in mind). Included in the example is how to open a socket connection to another server.
If you wanto to use a MQservervice there you should implement it...

Code: Select all
#!/usr/local/php5/bin/php -d memory_limit=512M
<?php
error_reporting( E_ALL ^ E_NOTICE ^ E_DEPRECATED );

ini_set( "track_errors", true );
chdir( dirname( __FILE__ ) ); // we're working relativly from the script


// Include Class
/// https: // github . com /kvz/system_daemon/blob/master/System/Daemon.php
include_once 'System/Daemon.php';

function testConnection( $str_dispatcher )
{
   $sock = socket_create( AF_INET, SOCK_STREAM, SOL_TCP );
   if ( $sock === false )
   {
      return - 1;
   }
   else
      if ( socket_connect( $sock, gethostbyname( $str_dispatcher ), 49510 ) )
      {
         return true;
      }
      else
      {
         socket_close( $sock );
         return false;
      }
}

$user = "apache";
$uid_name = posix_getpwnam( $user );
$uid_number = $uid_name[ 'uid' ];
$gid_number = $uid_name[ 'gid' ];

// Setup
$options = array(
   "usePEAR" => false,
   "appName" => "deamonsample",
   "appDir" => dirname( __FILE__ ),
   "appDescription" => "",
   "authorName" => "TD",
   "authorEmail" => "",
   "sysMaxExecutionTime" => "0",
   "sysMaxInputTime" => "0",
   "sysMemoryLimit" => "1024M",
   "appRunAsGID" => $gid_number,
   "appRunAsUID" => $uid_number
);

$is_daemon = true;
$int_maxChilds = 6;
$str_dispatcher = "yourqueueserver.lan";

// Scan command line attributes for allowed arguments
foreach ( $argv as $k => $arg )
{
   if ( preg_match( "/--(.*?)($|=('(.*)'|\"(.*)\"|(.*)))/", $arg ) == 1 )
   {
      $str_name = preg_replace( "/--(.*?)($|=(.*))/", "$1", $arg );
      $str_value = preg_replace( "/--.*?=('(.*)'|\"(.*)\"|(.*))/", "$2$3$4", $arg );
      if ( $str_value == $arg )
      {
         $str_value = null;
      }

      switch ( $str_name )
      {
         case 'name' :
            $frmstr_Client = $str_value ? $str_value : $frmstr_Client;
            break;
         case 'no-daemon' :
            $is_daemon = false;
            break;
         case 'dispatcher' :
            $str_dispatcher = $str_value;
            $result = testConnection( $str_dispatcher );
            if ( $result === - 1 )
            {
               echo "Could not create Socket.\n";
               exit( ) - 1;
            }
            else
               if ( $result === false )
               {
                  echo "Could not connect to dispatcher on '{$str_dispatcher}'\n";
                  exit( ) - 1;
               }
            break;
         case 'childs' :
            $int_maxChilds = is_numeric( $str_value ) && $str_value > 0 ? $str_value : $int_maxChilds;
            break;
      }
   }
}

System_Daemon::setOptions( $options );

$str_pidFile = "/var/run/{$options['appName']}/{$options['appName']}.pid";

switch ( $argv[ $argc - 1 ] )
{
   case 'force-start' :
      if ( file_exists( $str_pidFile ) )
      {
         unlink( $str_pidFile );
      }
      $argv[ $argc - 1 ] = 'start';
   case 'start' :
      if ( file_exists( $str_pidFile ) )
      {
         echo "Deamonsample allready running!\n";
         exit( 0 );
      }
      else
         if ( $is_daemon )
         {
            System_Daemon::start( );
         }
      break;
   case 'stop' :
      if ( file_exists( $str_pidFile ) )
      {
         exec( "kill -KILL `cat {$str_pidFile}`" );
         unlink( $str_pidFile );
      }
      exit( 0 );
      break;
   case 'restart' :
      $str_pidFile = "/var/run/{$options['appName']}/{$options['appName']}.pid";
      if ( file_exists( $str_pidFile ) )
      {
         exec( "kill -KILL `cat {$str_pidFile}`" );
         unlink( $str_pidFile );
      }
      if ( $is_daemon )
      {
         System_Daemon::start( );
      }
      break;
   case 'help' :
   default :
      echo "Deamonsample\n";
      echo "\n";
      echo "usage: deamonsample.php [options] (start|force-start|restart|stop|help)\n";
      echo "\n";
      echo "Arguments:\n";
      echo "   --name=NAME         Sets the name for the service.\n";
      echo "   --childs=NUMBER      Defines how many childs will be created.\n";
      echo "   --no-daemon         Runs the service in the foreground.\n";
      echo "   --dispatcher=DOMAIN         Domain of the dispatcher.\n";
      exit( 0 );
      break;
}

if ( $argv[ $argc - 1 ] != 'start' && $argv[ $argc - 1 ] != 'restart' )
{
   exit( 0 );
}

$int_actChilds = 0;
$children = Array();
$runningOkay = true;

$int_startTime = time( );

function getNextinQueue( $str_dispatcher )
{
   $sock = socket_create( AF_INET, SOCK_STREAM, SOL_TCP );
   if ( $sock === false )
   {
      return - 1;
   }
   else
      if ( socket_connect( $sock, gethostbyname( $str_dispatcher ), 49510 ) )
      {
         @socket_write( $sock, "whateveryouneedtoget\n" );
         $result = @socket_read( $sock, 2048 );
         $result = trim( $result );
         socket_close( $sock );
         $result = is_numeric( $result ) ? $result : - 1;
         return $result;
      }
      else
      {
         socket_close( $sock );
         return - 1;
      }
}

while ( ! System_Daemon::isDying( ) && $runningOkay )
{

   while ( pcntl_wait( $status, WNOHANG or WUNTRACED ) > 0 )
   {
      usleep( 5000 );
   }
   while ( list( $key, $val ) = each( $children ) )
   {
      if ( ! posix_kill( $val, 0 ) )
      {
         unset( $children[ $key ] );
         $int_actChilds --;
      }
   }
   $children = array_values( $children );

   $int_waitTime = 5;

   if ( $int_actChilds < $int_maxChilds )
   {
      $int_journalId = getNextinQueue( $str_dispatcher );
      if ( $int_journalId > 0 )
      {

         $int_actChilds ++;
         $pid = pcntl_fork( );
         if ( $pid == - 1 )
         {
            exit( 0 );
         }
         else
            if ( $pid )
            {
               $children[] = $pid;
               $int_waitTime = 1;
            }
            else
            {
               // DO PROCESS CODE IN HERE
               mysql_connect( $gblstr_Site, $gblstr_UserName, $gblstr_PassWord, true );
               mysql_select_db( $gblstr_dbName );

               $sql_Job = "SELECT SQL_NO_CACHE * FROM foo";
               $sqr_Job = mysql_query( $sql_slideShowJob );
               $sqw_Job = mysql_fetch_assoc( $sqr_slideShowJob );

               exit( );
            }
      }
   }
   System_Daemon::iterate( $int_waitTime );
}
System_Daemon::stop( );
tedtiger
 
Posts: 118
Joined: Thu Mar 05, 2009 4:59 pm
Location: Germany

Re: Long Live PHP Command Line as Daemon

Postby rampog on Mon Dec 31, 2012 1:07 pm

Hi tedtiger,
that is awesome tips could you please explain differences with "php-cli simpleDaemon.php &" execute as root,
what's the benefit of using pcntl ?
rampog
 
Posts: 56
Joined: Mon May 04, 2009 12:15 pm

Re: Long Live PHP Command Line as Daemon

Postby tedtiger on Tue Jan 01, 2013 8:26 pm

For security reasons I wouldn't even consider running a script as the root user. pcntl is simply for process control. Your PHP script behaves like a normal Linux background deamon.
http : // php net /manual/en/intro.pcntl.php
tedtiger
 
Posts: 118
Joined: Thu Mar 05, 2009 4:59 pm
Location: Germany


Return to PHP

Who is online

Users browsing this forum: No registered users and 3 guests

cron