Integrating Bash with PHP

his article discusses how to install and configure three Bash distributions for Windows: the GNU BASH shell for Windows, the Win-Bash Windows port, and the Cygwin tool. It also demonstrates how to execute Bash scripts using PHP, how to send different types of arguments to a Bash script, how to use Bash functions from PHP, and how to save results to a text file. (For information about other Bash distributions, see the sidebar Bash Availability.)

Download and Configure GNU Bash Shell for Windows

First, download the GNU Bash shell for Windows. The tool is ready to use immediately after you extract the ZIP archive in your favorite location (for example, C:ash-2.03). To simplify calling Bash, you can add the bash.exe path to your CLASSPATH setting.

Here’s a standard HelloWorld Bash script:

   #!/bin/bash   echo "Hello World!"

Name this script test.txt (in Windows it’s most convenient to save Bash scripts as simple .txt files) and then open an MS-DOS command prompt. Navigate to the Bash home folder and type:

   >bash ${PATH_TO_SCRIPT}/test.txt
Author’s Note: Replace the PATH_TO_SCRIPT with the complete path to hello.txt):

If you get the “Hello World” message then you have successfully executed your first Bash script. Now you can go further and add PHP into the equation.

Call Bash Scripts from PHP Using the shell_exec Function

To execute a Bash script using PHP use the shell_exec function, which has the following prototype:

   string shell_exec ( string $cmd ):  Execute a command through       the shell and return the complete output as a string.       The $cmd parameter represents the command which will be executed.
Author’s Note: The shell_exec function is disabled when PHP is running in safe mode.

Here’s a more complete example. This PHP application calls the HelloWorld Bash script created earlier:

   

When you run this, the output is:

   Hello World!

Here’s a slightly more complex script that passes two integer values to a Bash script, which uses them to do some simple calculations, and then returns the results:

   

The preceding script sends two sample values, 2 and 4, to the Bash script values.txt, which contains the following code:

   #!/bin/bash      a=$1   b=$2   echo 'sum = '$((a+b))       echo 'product = '$((a*b))   echo 'average = '$(((a+b)/2))

The output is:

   sum = 6 product = 8 average = 3

You can send as many arguments as you like to a Bash script. Bash extracts them using positional arguments such as $1, $2?, $n. In the preceding example, when the script runs, $1 = 2 and $2 = 4.

PHP, HTML, and Bash

Bash scripts may be as complex as you like. For example, the next application generates a simple HTML document using a Bash script called from PHP. Here’s the PHP script, called bashPHP.php:

   

And here’s the Bash script that generates the HTML (bashHTML.txt):

   #!/bin/bash# our html codeecho ""echo "BASH-HTML"echo ""echo "

This page comes from Bash

"echo "Hello Everybody!"echo ""echo ""

The output that appears in the browser is:

   This page comes from Bash   Hello Everybody!
Author’s Note: You can download all the sample code for this article.

Mimic Bash Function Calls from PHP

In Bash, functions look like mini-scripts: they may accept arguments, they can use variables known only in the function’s body (using the local shell built-in), and they can return values to the calling entities. Within functions, arguments are treated in the same manner as arguments passed to the script.

The next application uses a recursive function to calculate a sum of 20 consecutive integer numbers. The Bash script function.txt containing the recursive function sum appears below:

   #!/bin/bash      # Define the recursive function    sum ()   {      # Declaring local variable      local num=$1;     if [ "$num" = 0 ] ; then       echo 0        return ;     fi;      # The recursive call of the sum function      echo $[ $num + $(sum $[ $num - 1 ])]   }      echo "Sum of 1+2+3+...+20 is ***"      # Call the recursive function sum   sum 20

The PHP script function.php, which calls the above Bash script (and should look familiar by now), is:

   

The output is:

   Sum of 1+2+3+...+20 is *** 210

Note that in the previous example, the PHP script calls the Bash script, NOT the Bash function itself. The function gets called from the last line of the Bash script. That’s all very well for Bash scripts that contain only one function, but when you have more than one function in the Bash script, you have to use a trick. For example, suppose that you have a Bash script containing two functions. The first function calculates the factorial of a given number and the second is the sum function from the previous example. The following functionsCall.txt script shows the code:

   #!/bin/bash        fact ()   {     local num=$1;                 if [ "$num" = 1 ] ; then       echo 1 # listing fact from 1       return ;     fi;     # The recursive call of the fact function     echo $[ $num * $(fact $[ $num - 1 ])]   }           sum ()   {      # Declaring local variable      local num=$1;     if [ "$num" = 0 ] ; then       echo 0        return ;     fi;      # The recursive call of the sum function      echo $[ $num + $(sum $[ $num - 1 ])]   }

If you want to call only one of the two contained functions, then you must pass the Bash script the desired function name and the appropriate arguments. For example, from PHP you would call the fact function by passing the function name (“fact”) as the first argument, and following that with the arguments required by the function (in this case, 3):

   

You also have to add a chunk of code in the Bash script that’s dedicated to parsing the received arguments, extracting the function name that the caller wants to run:

   # Check what function was called from PHP    # and call that function   if [ "$1" = fact ] ; then      printf "The function -- $1 -- "      printf "was called from PHP and the result is : "             #Call the fact function using $2 as argument      fact $2      else       printf "The function -- $1 -- "      printf "was called from PHP and the result is : "          #Call the sum function using $2 as argument      sum $2   fi;

The output is:

   The function -- fact -- was called       from PHP and the result is : 6

To call the sum function instead, with the argument 20, all you need to do is replace the line that makes the call with:

   $result=shell_exec(      "C:ash-2.03ash.exe functionsCall.txt sum 20");

And the result will be:

   The function -- sum -- was called       from PHP and the result is: 210

You aren’t limited to passing single values as arguments; you can pass arrays to Bash as well.

Passing Arrays between PHP and Bash

Bash provides one-dimensional array variables that you declare using the form:

   Array_name=(value1 ... valuen). 

You can then reference any element of an array using the syntax ${name[subscript]}. There is no maximum limit on the size of an array. For example, you can pass a set of arguments to a Bash script that groups them into arrays. The following PHP script (array.php) sends a list of integers:

   

The arrayNumber.txt Bash script in Listing 1 extracts the arguments and creates two Bash arrays (the Bash script also provides a few basic array operations):

The code in Listing 1 stores output into an arrayNumberResult.txt file. When you run the example, the output is:

   First numeric array is: 10 2 13      Second numeric array is: 88 76 34       Length of first array is: 3      Length of second array is: 3      0 ---->     sum[0] = myArray1[0] + myArray2[0] *** 98       product[0] = myArray1[0] * myArray2[0] *** 880       average[0] = (myArray1[0] + myArray2[0])/2 *** 49   ------------       1 ---->     sum[1] = myArray1[1] + myArray2[1] *** 78    product[1] = myArray1[1] * myArray2[1] *** 152       average[1] = (myArray1[1] + myArray2[1])/2 *** 39   ------------       2 ---->     sum[2] = myArray1[2] + myArray2[2] *** 47       product[2] = myArray1[2] * myArray2[2] *** 442       average[2] = (myArray1[2] + myArray2[2])/2 *** 23   ------------       The sum of all elements of the first array is *** 25   ------------       The first array after deleting the second element is *** 10 13   ------------

Listing 2 contains a similar example that uses string arrays and demonstrates operations over strings (add, paste, display length, and so on). The PHP script (array.php) that runs the Bash script is:

   

When you run array.php script, the result stored in the arrayResult.txt file is:

   Length of first array is 2   Length of second array is 3   ------------    red <--> white    red <--> blue    red <--> pink    black <--> white    black <--> blue    black <--> pink    ------------    red    black    aqua    magenta    ------------    redwhite    blackblue    aquapink    magenta    ------------  

Passing True PHP Arrays

If you want to pass a PHP array to Bash instead of a list of arguments, convert the PHP array into a string and pass it as shown below (you can use any element separator you like):

      ';   echo $separated."

"; $result=shell_exec("C:ashash-2.03ash.exe arrayToBash.txt '".$separated."'"); …

Next, the Bash script will build an array from this string as follows:

   #!/bin/bash      string=$1      until [ "$token" =  "$string" ]   do     token=${string%%:*}        a[$i]=$token"BASH"               string=${string#*:}        ((i=i+1))   done      #echo "a[0]="${a[0]}   #echo "a[1]="${a[1]}   #echo "a[2]="${a[2]}   #echo "a[3]="${a[3]}   #echo "a[4]="${a[4]}      echo ${a[@]}

PHP may reconstruct the array from the Bash string using code like this:

   //convert from Bash string to PHP array   $pieces = explode(" ", $result);   echo "

Convert from Bash string to PHP array:
"; echo "pieces[0]=".$pieces[0]."
"; echo "pieces[1]=".$pieces[1]."
"; echo "pieces[2]=".$pieces[2]."
"; echo "pieces[3]=".$pieces[3]."
"; echo "pieces[4]=".$pieces[4]."
"; ?>

The output is (notice that Bash script added the “BASH” text termination for every array element—this is just a flag to show that the Bash script worked):

   The PHP array converted in a string:    one:two:three:four:five      The Bash array elements:    oneBASH twoBASH threeBASH fourBASH fiveBASH       Convert from Bash string to PHP array:    pieces[0]=oneBASH    pieces[1]=twoBASH    pieces[2]=threeBASH    pieces[3]=fourBASH    pieces[4]=fiveBASH   Passing PHP objects to Bash

Passing PHP Object Members to Bash

Suppose you have the following SimpleClass PHP class, and you want to pass an instance’s members to a Bash script:

   displayVar();                                       ?>

Currently, Bash is not object-oriented, but you can use some tricks to pass PHP object members to Bash. One way is to pass the serialized version of an object, like this (obviously, in Bash you’d need to implement a de-serialize mechanism to extract the member names and values):

   ...   echo "BASH call ...
";      $result=shell_exec(      "C:ash-2.03ash.exe objectBash.txt ".      serialize($simpleClass);   echo($result);   ...

Another way is to pass the members explicitly, as shown below (items are separated by a colon):

   ...   echo "BASH call ...
";      $cmd =       "C:ash-2.03ash.exe objectBash.txt ".      $simpleClass->phone.":".      $simpleClass->name.":".      $simpleClass->surname;   $result=shell_exec($cmd);   echo($result);   ...

With explicit passing, the objectBash.txt Bash script would look like this:

   #!/bin/bash   echo $* | ( IFS=: ; read phone name surname; echo "Phone = "$phone)

Using Win-Bash

Win-Bash is a Windows port of the GNU Bash that doesn’t need any special environment or DLLs. The latest released version is Win-Bash 0.6. Installing Win-Bash is easy: just download the win-bash_0.6.zip archive and extract it to your hard drive. Then, to run Win-Bash, double-click the win-bash.exe file and you’ll see the window in Figure 1.

 
Figure 1. The Win-Bash Command Prompt: Here’s a typical Win-Bash command window.

To use Win-Bash into your PHP applications, set the path to the win-bash.exe file like this:

   ${WIN-BASH_HOME}win-bash.exe 

Then you can call a Win-Bash script as shown below:

   
Author’s Note: Replace “bash_script_name” in the preceding code with any Bash script you like.

Using Cygwin

Cygwin is a tool that allows you to use a Linux environment on Windows systems. Cygwin ships with a DLL (cygwin1.dll) that acts as a Linux API emulation layer. It provides substantial Linux API functionality and a collection of tools that provide Linux “look and feel,” and that conform to the official specification. When you download Cygwin, you get a setup.exe file that guides you through the installation process. You can choose to install Cygwin directly from the Internet or download it and install it later from a local directory. After you select and install the Cygwin packages you need, you can run Cygwin at the command prompt by double-clicking on the Cygwin.bat file. You’ll see a window similar to Figure 2:

 
Figure 2. The Cygwin Command Prompt: When you launch Cygwin, you get a command-prompt window.

You can use Cygwin to run shell command scripts, login remotely to any PC, or fix problems within a Posize/Linux/UNIX shell on any Windows machine. If you like to use sophisticated shell command scripts you may use the standard shells: sed or awk.

To use Cygwin from PHP, simply set the path to the bash.exe file, for example:

   ${CYGWIN_HOME}inash.exe

A PHP script that executes a Cygwin Bash script will then look like this:

   

Again, remember to replace “bash_script_name” with whatever Bash script you need.

At this point, you should have the basic principles for calling Bash from PHP firmly in hand. You’ve seen examples showing how to call Bash scripts both with and without arguments of different types, how to call individual Bash functions from PHP, how to generate output in text files or in HTML, and how to parse and interpret Bash output in PHP. All that’s left is to use your imagination when adding Bash to your PHP applications.

Share the Post:
Share on facebook
Share on twitter
Share on linkedin

Overview

The Latest

Top 5 B2B SaaS Marketing Agencies for 2023

In recent years, the software-as-a-service (SaaS) sector has experienced exponential growth as more and more companies choose cloud-based solutions. Any SaaS company hoping to stay ahead of the curve in this quickly changing industry needs to invest in effective marketing. So selecting the best marketing agency can mean the difference

technology leadership

Why the World Needs More Technology Leadership

As a fact, technology has touched every single aspect of our lives. And there are some technology giants in today’s world which have been frequently opined to have a strong influence on recent overall technological influence. Moreover, those tech giants have popular technology leaders leading the companies toward achieving greatness.

iOS app development

The Future of iOS App Development: Trends to Watch

When it launched in 2008, the Apple App Store only had 500 apps available. By the first quarter of 2022, the store had about 2.18 million iOS-exclusive apps. Average monthly app releases for the platform reached 34,000 in the first half of 2022, indicating rapid growth in iOS app development.