writing command line scripts in php: part 1; args, preflighting and more
php has a lot of strengths as a web language, but it is also perfectly serviceable for general-purpose scripting. in this series of posts we’re going to go over building command line scripts in php. this is part one.
why even do this?
- reuse of existing code: if you have a php web application and you wish to write a command line interface to leverage some or all of its functionality, it makes much more sense to use php for your script and re-use your existing code, rather than rewrite everything from scratch in, say, python.
- available skills: if you or your team is long on php skills and short on python or bash, it often makes sense to just play to your strengths.
- the language itself: php is actually a pretty powerful language for command scripting. not only does it provide all the standard features, but it also gives us access to things like handling signals, forking processes and even semaphores if we need it.
assumptions
we’re going to be looking at writing command line scripts for unix-like operating systems. all the examples here were built on ubuntu 20.04 using php 7.4.9.
the flyover
in this installment, we’re going to go over:
- making our php script runnable on the command line
- preflighting our environment to ensure our script runs right
- parsing common command line argument strucutres, and finally
- giving our script a nice name that ps recognizes
first, make it runnable
traditionally, when running a php script on the command line, you invoke the php command and pass the script as an argument, ie php /path/to/my/script.php . this works, but is ugly.
to fix this, we’ll be putting a shebang at the top of our php script. the shebang is a specially-formatted first line that informs the operating system which interpreter to use when executing the script. if you’ve done any shell scripting, you’re probably familiar with #!/bin/bash . that’s a shebang.
let’s open our sample script ourfancyscript.php in the editor of our choice and add:
one thing that we notice about this shebang is that it calls env . normally, in shell scripting, we reference the direct path to bash with #!/bin/bash . but, here, we’ll be calling env so that the operating system searches the user’s $PATH to find the php intepreter. this is important since, while bash is almost always in /bin , we have no guarantee that we know where the php interpreter lives. using env in our shebang helps increase the portability of our script across different systems. that’s a good thing.
now that we have our shebang, we’ll set our script to be executable. we’ll use the standard permssions set for this:
chmod 755 ourfancyscript.php
once we have the execution permissions set, we can run the script simply by calling it:
of course, the script does nothing, but it actually does do that nothing. so that’s progress.
preflight
when we write php for a web application, we generally have a good idea of the environment it will run in. we provisioned the web server, after all.
command line scripts, however, are a different story. we have no control over the environment. it’s someone else’s computer.
with that in mind, it’s good idea to always start your script with a call to a ‘preflight’ function that confirms the system has everything necessary to run the script. if any of our preflight tests do not pass, we can halt the script with an appropriate error instead of just barging ahead and making a mess.
common things we can check for in our preflight include:
minimum php version: of course we’re writing for the lowest possible php version we can (portability and all!), but we should still check that we meet the minimum version. keep in mind that a three year-old amazon linux ec2 runs php 5.3 by default!
checking the php version is as straightforward as a call to the built-in phpversion() command.
necessary extensions are loaded: if our script calls for an extension, we should make sure that it’s actually loaded before we start. we can do this with the built-in command extension_loaded(). so, for instance, if we want to confirm php has ‘imagick’ available, we could test that in our ‘preflight’ function like so:
if (!extension_loaded('imagick')) die('imagick extension required. exiting.'); >
file access: we may want to read files or write to files or directories. it’s a good idea to confirm that the user running our script has permissions to do that before starting. php has a number of built-in commands to accomplish this:
- file_exists to confirm if the file exists
- is_dir to determine if the file is a directory
- is_writable() to test if the user has write access to the file or directory
let’s put all of that together into a short sample preflight function:
#!/usr/bin/env php /** * Confirm system can run script */ function preflight() $phpversion_array = explode('.', phpversion()); if ((int)$phpversion_array[0].$phpversion_array[1] 56) die('minimum php required is 5.6. exiting'); > if(!extension_loaded('posix')) die('posix required. exiting'); > if(!is_writable('/tmp')) die('must be able to write to /tmp to continue. exiting.'); > if(!file_exists(posix_getpwuid(posix_getuid())['dir'].'/.aws/credentials')) die('an aws credentials file is required. exiting'); > >
in the first if block of this function we check the php version is at least 5.6. we do a little clumsy casting here to accomplish this as we only care about the major and minor numbers.
next, we confirm that the posix extension is loaded. posix is basically a set of standard ways to interface with the host operating system. definitely something we will want for our script.
we then do a fast confirmation that we can write to the /tmp directory and, finally, determine that the user has an aws credentials file.
one thing to note is in the last if block, we used a couple of those posix commands to get the running user’s home directory. the ‘~/’ construction will not work here. instead, we get the user’s id number with posix_getuid() and then pass that to posix_getpwuid() to get an array of information about the user, including their home directory, from the /etc/passwd file.
parse command line arguments
handling command line arguments and switches is something most scripts need to do, so we’re going to write a short function that takes the arguments passed to our script and processes them into an array that we can reference later when determining what functionality to provide.
this function handles four basic types of arguments:
switches
these are single letter arguments that are preceded by a dash, think the -a argument to ls to show hidden files.
long switches
these are the same as switches except. longer. an example would be curl accepting —silent as a synonym for -s . long switches are preceded by two dashes.
asignments
this is for passing data into our script. assignment arguments take two dashes and use an equal sign to indicate the value, ie. —outfile=/path/to/file or mysql’s horrifying —password=mynothiddenpassword .
positional arguments
these are arguments without any preceding dashes; their usage is determined entirely by their position. think the linux ‘move’ command mv /path/to/origin /path/to/destination . there are two positional arguments here, and we know which value is assigned to the origin and which to the destination by the order they are written in.
with that in mind, we can add this function to our command line scripts to parse arguments for us:
#!/usr/bin/env php /** * Parses command line args and returns array of args and their values * * @param Array $args The array from $argv * @return Array */ function parseargs($args) $parsed_args = []; $args = array_slice($args, 1); for ($i=0;$icount($args);$i++) switch (substr_count($args[$i], "-", 0, 2)) case 1: foreach (str_split(ltrim($args[$i], "-")) as $a) $parsed_args[$a] = isset($parsed_args[$a]) ? $parsed_args[$a] + 1 : 1; > break; case 2: $parsed_args[ltrim(preg_replace("/=.*/", '', $args[$i]), '-')] = strpos($args[$i], '=') !== false ? substr($args[$i], strpos($args[$i], '=') + 1) : 1; break; default: $parsed_args['positional'][] = $args[$i]; > > return $parsed_args; >
we can then call that function in our script with
$our_parsed_args = parseargs($argv);
How to execute PHP code using command line ?
PHP Installation for Windows Users: Follow the steps to install PHP on the Windows operating system.
- Step 1: First, we have to download PHP from it’s official website. We have to download the .zip file from the respective section depending upon on our system architecture(x86 or x64).
- Step 2: Extract the .zip file to your preferred location. It is recommended to choose the Boot Drive(C Drive) inside a folder named php (ie. C:\php).
- Step 3: Now we have to add the folder (C:\php) to the Environment Variable Path so that it becomes accessible from the command line. To do so, we have to right click on My Computer or This PC icon, then Choose Properties from the context menu. Then click the Advanced system settings link, and then click Environment Variables. In the section System Variables, we have to find the PATH environment variable and then select and Edit it. If the PATH environment variable does not exist, we have to click New. In the Edit System Variable (or New System Variable) window, we have to specify the value of the PATH environment variable (C:\php or the location of our extracted php files). After that, we have to click OK and close all remaining windows by clicking OK.
PHP Installation for Linux Users:
apt-get install php5-common libapache2-mod-php5 php5-cli
PHP Installation for Mac Users:
- Mac users can install php using the following command.
curl -s https://php-osx.liip.ch/install.sh | bash -s 7.3
After installation of PHP, we are ready to run PHP code through command line. You just follow the steps to run PHP program using command line.
- Open terminal or command line window.
- Goto the specified folder or directory where php files are present.
- Then we can run php code using the following command:
We can also start server for testing the php code using the command line by the following command:
php -S localhost:port -t your_folder/
Note: While using the PHP built-in server, the name of the PHP file inside the root folder must be index.php, and all other PHP files can be hyperlinked through the main index page.
PHP is a server-side scripting language designed specifically for web development. You can learn PHP from the ground up by following this PHP Tutorial and PHP Examples.