Showing posts with label PHP CLI. Show all posts
Showing posts with label PHP CLI. Show all posts

Tuesday, 18 September 2018

Command line arguments with a PHP CLI script

PHP has the getopt() function for getting options or command line arguments from a CLI PHP script. This provides a simple way to get values from the command line like e.g. "-a foo". This post looks at how to do this. More details can be found in the PHP getopt() manual page.

$_SERVER['argv']

The command itself (i.e. your script filename) and the command line arguments are stored in an array in the $_SERVER variables called 'argv'. It is possible to access the command line arguments from here but it's easier to getopt() because you can then access the arguments by flag and in any order. Running the command "php myscript.php foo bar" and then doing print_r($_SERVER['argv']) would output this:
Array
(
    [0] => myscript.php
    [1] => foo
    [2] => bar
)

getopt() function

The getopt() function returns the list of command line arguments in an associative array. It returns the arguments passed in based on the parameters passed to it. For example, to get the values for the flags -a -b and -c you would do this:
$arguments = getopt("a:b:c:");
If you called the script like this (the first example has spaces between the flag and the value, the second has no spaces but both will return the values):
php myscript.php -a foo -b bar -c baz
OR
php myscript.php -afoo -bbar -cbaz
Then doing print_r($arguments) would return this:
Array
(
    [a] => foo
    [b] => bar
    [c] => baz
)
Note that the colons after the value are required; if you don't use them and a flag is passed on the command line with that letter then it won't be returned in the array.
Another thing to note is that if it one of the values you are looking for is not passed on the command line, then it won't be added to the array return from getopt(). Calling the same $arguments = getopt("a:b:c:") script as in the above example, calling the script like so:
php myscript.php -a foo
and then doing print_r($arguments) would show this:
Array
(
    [a] => foo
)

Version used for this post

The version I used for testing with this post was PHP 5.1.6 on CentOS 5.0. According to the PHP manual page for getopt() on versions of PHP prior to 5.3 did not work. There is also an "optional" parameters option from 5.3 which doesn't work as expected in the version 5.1.6 that I used, and a second parameter to the getopt() function for long options (in the style --name=value or --name value) which is not widely available prior to 5.3. On the CentOS system I was using, attempting to use the second paameter for long options resulted in this error message:
PHP Warning:  getopt(): No support for long options in this build in ...
Therefore if you are targeting systems with PHP installations prior to 5.3 you are best to stick with the short options only.

Related posts:

Command line arguments for the PHP CLI

The PHP command line interface or CLI allows you to run PHP scripts from the command line. It also has a number of flags that can be passed to it which allow you to see which modules are available, do a syntax check on a file, view PHP information etc. This post gives a basic list of the command line arguments available for the PHP CLI and in later posts I will look at some of the options in more detail.
To show all the options that are available, do this:
php --help
This will return a list of all the options available that can be passed to the PHP CLI. The following output comes from a default PHP install on a CentOS 5.0 machine:
Usage: php [options] [-f] <file> [--] [args...]
       php [options] -r <code> [--] [args...]
       php [options] [-B <begin_code>] -R <code> [-E <end_code>] [--] [args...]
       php [options] [-B <begin_code>] -F <file> [-E <end_code>] [--] [args...]
       php [options] -- [args...]
       php [options] -a

  -a               Run interactively
  -c <path>|<file> Look for php.ini file in this directory
  -n               No php.ini file will be used
  -d foo[=bar]     Define INI entry foo with value 'bar'
  -e               Generate extended information for debugger/profiler
  -f <file>        Parse <file>.
  -h               This help
  -i               PHP information
  -l               Syntax check only (lint)
  -m               Show compiled in modules
  -r <code>        Run PHP <code> without using script tags <?..?>
  -B <begin_code>  Run PHP <begin_code> before processing input lines
  -R <code>        Run PHP <code> for every input line
  -F <file>        Parse and execute <file> for every input line
  -E <end_code>    Run PHP <end_code> after processing all input lines
  -H               Hide any passed arguments from external tools.
  -s               Display colour syntax highlighted source.
  -v               Version number
  -w               Display source with stripped comments and whitespace.
  -z <file>        Load Zend extension <file>.

  args...          Arguments passed to script. Use -- args when first argument
                   starts with - or script is read from stdin

  --rf <name>      Show information about function <name>.
  --rc <name>      Show information about class <name>.
  --re <name>      Show information about extension <name>.
To run a PHP script you would simply call "php" followed by the script name, e.g.:
php myscript.php
To get the PHP version you would do this:
php -v
which will output something along the lines of this:
PHP 5.1.6 (cli) (built: Sep 20 2007 10:16:10)
Copyright (c) 1997-2006 The PHP Group
Zend Engine v2.1.0, Copyright (c) 1998-2006 Zend Technologies
That's all for this post. In future posts I will examine some of the other flags in more detail.

Related posts:

Monday, 17 September 2018

PHP CLI counter for long running processes

I've been doing a reasonable amount of PHP CLI (command line interface) programming recently for getting stuff from log files and converting large numbers of images. Some of these processes can some quite a while to run, sometimes as long as several hours, so it can be useful to know roughly how far through the process it is. This post looks at how to output a counter to the command line from PHP which replaces itself on each iteration.
The important thing with outputting counter information like this is we don't want a big scrolling screen of numbers flying past because it's little messy... this is what would happen if you echo the number out and then follow it with a line break \n
Instead, follow the counter value with a carriage return only \r and each time the value is written out it will replace the line, so you end up with an incrementing value which is always on the same line. This is illustrated in the following example.
for($i = 0; $i < $count; $i++) {
    ... your code here ...
    echo ($i+1), "/$count\r";
}
echo "\n";
This will show e.g. 1/10000, 2/10000, 3/10000 etc always on the same line in your console. At the end we output a final \n newline break so the last line is always displayed.
Running something like this can slow your process down marginally but it's really not going to affect it much if your process is fairly intensive on each loop iteration.

Related posts:

Wednesday, 12 September 2018

Determine whether PHP is being run via HTTP or CLI

PHP can be run as a webserver module, as a CGI application or from the command line as a CLI script. There is both a function and a PHP constant which allows you to determine whether PHP is being run via HTTP or CLI. This post looks at the function and constant and the possible values, as determined in the PHP 5.2.5 source code.

Function

The PHP function php_sapi_name() takes no arguments returns the interface as a lower case string.
Example usage:
echo php_sapi_name()
This will echo e.g. "apache"

Constant

The PHP_SAPI constant provides the same value as the php_sapi_name() function.
Example usage:
echo PHP_SAPI
This will echo e.g. "apache"

Return values

The values returned by php_sapi_name() and PHP_SAPI can be found in the source code. Unfortunately they are not documented in the PHP documentation, other than in a user comment. To work out all the possible current values I downloaded the latest PHP source code (5.2.5 as at the time of this post) and had a look.
There is a structure called sapi_module_struct which contains, among other things, the name. This can be found referenced throughout the PHP source code as sapi_module.name, and is set by the code in the "sapi" directory of the source code. There are several sub-directories, one for each module/interface type and only one of these will be compiled into PHP depending on the compile time settings.
Looking through this, I worked out the possible current values are:
  • aolserver
  • apache
  • apache2filter
  • apache2handler
  • caudium
  • cgi
  • cgi-fcgi
  • cli
  • Continuity
  • embed
  • isapi
  • milter
  • nsapi
  • phttpd
  • pi3web
  • roxen
  • thttpd
  • tux
  • webjames
These can be found as in the following example for apache/mod_php5.c:
static sapi_module_struct apache_sapi_module = {
  "apache",  /* name */
  "Apache",  /* pretty name */
  ...

How to determine if PHP is being run as a CLI

If PHP is being run as a CLI (command line interface) application, then the value returned by php_sapi_name() and PHP_SAPI will be "cli". So you could do something like this:
if(PHP_SAPI == 'cli') {
  do_something();
}
else {
  do_something_else();
}
or
if(php_sapi_name() == 'cli') {
  do_something();
}
else {
  do_something_else();
}
So if you needed to do something different depening whether PHP is being run via a web server or from the command line, you would use the php_sapi_name() or PHP_SAPI constant as shown in the above examples.

Related posts: