Mixing PHP and shell scripting (under Linux)

Line Break

Author: Mohannad Hussain (9 Articles)

Hello, my name is Mohannad! I am a Zend certified PHP 5 engineer, but I am also interested in Javascript, Java, mobile development (native & web), Linux & shell scripting plus User experience & interface.

PHP plays very well with command line. On one hand, you can execute PHP from the command line using the, wait for it, “php” command! On the other hand, inside PHP you have many options for executing commands on the command line, which is the one I want to focus on here.

Before you proceed reading this article and get all excited about PHP and command line having babies together, I must warn you that I find most hosting companies don’t allow their users to access command line from within PHP. So, you might want to check on that first!

First example is the one I use the most. At work I maintain close to a hundred deployments of this one product, so when I need to run quick deployments, I can do this:
$sites = explode("\n",trim(`ls -1d /var/www/*`));

Note the tick character (`) in PHP means execute this string in shell. Also one thing people always confuse are the flags I am passing to the command “ls” (list, aka dir), the first is a digit one (1) and it means one column containing names only, the second, means return directories only.

At the end of the day, this will give me an array of all folders under /var/www, which I loop through in PHP, connect to the database to do some work and/or perform tasks in the file system. You could get fancier using a more advanced command to look up your targets such as find.

The second example is very useful for people who work with audio and/or video files. You can take advantage of awesome Linux commands such as ffmpeg and mencoder to allow your users to upload pretty much any kind of audio/video and convert it with ease into the format you prefer for playback and storage. The best part is, you can run the conversion command in the background so it doesn’t hold the page from loading (asynchronously, like AJAX). Here’s one example:

$cmd = 'nice lame -q 9 --resample 44100 '.escapeshellarg($source_file).' '.escapeshellarg($dest_file)." &\r\n";
$handle = popen($cmd,'r');
pclose($handle);

Nice is a prefixing command (like sudo), which basically sets a lower priority on this process not to lock up your server. Lame is the popular mp3 encoder. escapeshellarg() escpaes arguments for the command line interface (important!). The ampersand (&) puts this as a background process. Note that you could not use exec(), which is why I am opening up a pipe using popen(). Last but not least, the carriage return and new line characters (\r and \n) simulate hitting enter after a command when you are typing in a shell session, which is what the pipe does.

I will stop here since this post is getting too long. I should mention that the only limitation I know of with working with shell in PHP, is that you can never work with interactive prompts (e.g. being asked for a password when executing a command like ssh, scp, rsync or even svn update). However, there are ways to work around most of those scenarios (certificates, authentication caching…etc), which may not be best practices, but are available none the less if you really need to.

On the other hand, if you are building a PHP CLI solution (e.g. interactive installer the command line), you can make use of interactive prompts using existing shell libraries for PHP.