- Executing a PHP Script from the CLI
- Determining Whether or Not a Script Ran from the Command-line
- Command-line Options
- Exit Codes
- Final Thoughts
I’ve been working on a PHP project that provides for execution via either the web-browser or the command-line (CLI). I wanted my program to be able to accept a command-line option. I also wanted to be able to use it inside a Bash script. This meant that it needed to be able to exit meaningfully, so that the Bash script could “know” whether or not its execution was successful.
The majority of the PHP code I write runs from the web-browser via the CGI. So I was unfamiliar with some of the subtleties of designing for CLI execution. I thought I’d better make some notes about what I have learned.
Executing a PHP Script from the CLI
The most common way of executing a PHP script from the command-line is to pass the path of the script to the PHP interpreter:
php /path/to/my_script.php
Now I started my career as a web-developer writing Perl applications. The first line of most Perl scripts usually looks something like this:
#!/usr/bin/perl
That’s known as the shebang line, it tells the operating system to load the interpreter at /usr/bin/perl
and execute the script using that interpreter. The shebang is available to all the major scripting languages and PHP is no exception.
This means that we can have, as the first line of a PHP script, the following:
#!/usr/bin/env php
If we then make our script executable:
chmod a+x /path/to/my_script.php
we can run the script without having to pass it as an argument to the PHP binary:
/path/to/my_script.php
At this point, depending on the utility of the script, we could move it into one of the system’s $PATH directories, or add its directory to the $PATH
. Doing so enables us to execute the script, from any directory, just by typing its filename: my_script.php
Alternatively, we can simply add an alias to our ~/.bash_profile
, which would achieve the same thing:
alias my_script="/path/to/my_script.php"
Determining Whether or Not a Script Ran from the Command-line
In your PHP script, you can determine whether or not the script is running from the command-line with the following code:
<?php
if (php_sapi_name() === 'cli') {
echo 'Running from the command line!';
} else {
echo 'Running from the browser!';
}
?>
Command-line Options
How about if you want to set some command-line options as you execute the script? You can access these in PHP with the getopt() function:
<?php
$options = getopt('a:b:');
var_dump($options);
?>
Running the above script like this: php my_script.php -aCat -bDog
will result in the following output:
array(2) {
["a"] => string(3) "Cat"
["b"] => string(3) "Dog"
}
PHP allows you to configure required, optional and no-value command-line options via the getopt()
function. You can also configure your script to accept long options as input, i.e.:
php my_script.php --firstanimal=Cat --secondanimal=Dog
Exit Codes
When our PHP script exits we should set an exit code so that we can meaningfully determine whether or not it terminated normally, or with an error.
According to the Bash Bible, otherwise know as the Advanced Bash-Scripting Guide, an exit code should be a value between 0-255 inclusive.
Bash reserves some codes for specific conditions. 0, for example, is generally used to indicated that a script completed successfully. The Advanced Bash-Scripting Guide also lists these:
Exit Code | Meaning | Example | Comments |
---|---|---|---|
1 | Catchall for general errors | let “var1 = 1/0” | Miscellaneous errors, such as “divide by zero” and other impermissible operations |
2 | Misuse of shell built-ins (according to Bash documentation) | empty_function() {} | Missing keyword or command |
126 | Command invoked cannot execute | /dev/null | Permission problem or command is not an executable |
127 | Command not found | illegal_command | Possible problem with $PATH or a typo |
128 | Invalid argument to exit | exit 3.14159 | exit takes only integer args in the range 0-255 |
128+n | Fatal error signal ‘n’ | kill -9 $PPID of script | $? returns 137 (128 + 9) |
130 | Script terminated by Control-C | Ctrl-C | Control-C is fatal error signal 2, (130 = 128 + 2, see above) |
255* | Exit status out of range | exit -1 | exit takes only integer args in the range 0-255 |
The author of the Advanced Bash-Scripting Guide proposes restricting user-defined exit codes to the range 64-113 (in addition to 0, for success), to conform with the C/C++ standard. This means that we’ve got 50 exit codes available to us, which should be more than enough for expressing the outcome of most scripts.
So how do we use them? With PHP’s exit()
command of course:
<?php
echo 'Exiting now!';
exit(0);
?>
These exit codes are then available to us in Bash by querying the variable $?
. For example:
echo $?
Or, if we want the exit status of our PHP script to determine the flow of the Bash script that called it:
#!/bin/bash
php my_script.php
if [ $? -eq 0 ];
then
# exited successfully, do something
else
# exited with errors, do something else
fi
Final Thoughts
As a general purpose language PHP is ideal for writing concise scripts that can accomplish significant tasks. Being able to configure those scripts so that they can run from and interact with the CLI is cool. Command-line tools are useful within automation, system administration and system maintenance roles. PHP, with its extensive lexicon of file-system, text-processing, networking and database commands, is the ideal scripting language for building such tools.
So what are you waiting for? Fire up your editor and get scripting!