apache – Executing a shell script from a PHP script-ThrowExceptions

Exception or error:

I want to execute a Bash script present on the system from a PHP script. I have two scripts present on the system. One of them is a PHP script called client.php present at /var/www/html and the other is a Bash script called testscript present at /home/testuser.

My client.php script looks like

  $message=shell_exec("/home/testuser/testscript 2>&1");

My testscript looks like

echo "Testscript run succesful"

When i do the following on terminal

php client.php

I get the following output on terminal

Testscript run successful

But when i open the page at


I get the following output

sh: /home/testuser/testscript: Permission denied 

I get this error even after I did chmod +x testscript.
How do I get it to work from the browser? Please help.

How to solve:

I would have a directory somewhere called scripts under the WWW folder so that it’s not reachable from the web but is reachable by PHP.

e.g. /var/www/scripts/testscript

Make sure the user/group for your testscript is the same as your webfiles. For instance if your client.php is owned by apache:apache, change the bash script to the same user/group using chown. You can find out what your client.php and web files are owned by doing ls -al.

Then run

      $message=shell_exec("/var/www/scripts/testscript 2>&1");


If you really want to run a file as root from a webserver you can try this binary wrapper below. Check out this solution for the same thing you want to do.

Execute root commands via PHP


Without really knowing the complexity of the setup, I like the sudo route.
First, you must configure sudo to permit your webserver to sudo run the given command as root. Then, you need to have the script that the webserver shell_exec’s(testscript) run the command with sudo.

For A Debian box with Apache and sudo:

  1. Configure sudo:

    • As root, run the following to edit a new/dedicated configuration file for sudo:

      visudo -f /etc/sudoers.d/Webserver

      (or whatever you want to call your file in /etc/sudoers.d/)

    • Add the following to the file:

      www-data ALL = (root) NOPASSWD: <executable_file_path>

      where <executable_file_path> is the command that you need to be able to run as root with the full path in its name(say /bin/chown for the chown executable). If the executable will be run with the same arguments every time, you can add its arguments right after the executable file’s name to further restrict its use.

      For example, say we always want to copy the same file in the /root/ directory, we would write the following:

      www-data ALL = (root) NOPASSWD: /bin/cp /root/test1 /root/test2
  2. Modify the script(testscript):

    Edit your script such that sudo appears before the command that requires root privileges(say sudo /bin/chown ... or sudo /bin/cp /root/test1 /root/test2). Make sure that the arguments specified in the sudo configuration file exactly match the arguments used with the executable in this file.
    So, for our example above, we would have the following in the script:

    sudo /bin/cp /root/test1 /root/test2

If you are still getting permission denied, the script file and it’s parent directories’ permissions may not allow the webserver to execute the script itself.
Thus, you need to move the script to a more appropriate directory and/or change the script and parent directory’s permissions to allow execution by www-data(user or group), which is beyond the scope of this tutorial.

Keep in mind:

When configuring sudo, the objective is to permit the command in it’s most restricted form. For example, instead of permitting the general use of the cp command, you only allow the cp command if the arguments are, say, /root/test1 /root/test2. This means that cp‘s arguments(and cp’s functionality cannot be altered).


I was struggling with this exact issue for three days. I had set permissions on the script to 755. I had been calling my script as follows.

   $outcome = shell_exec('/tmp/clearUp.sh');
   echo $outcome;

My script was as follows.

find . -maxdepth 1 -name "search*.csv" -mmin +0 -exec rm {} \;

I was getting no output or feedback. The change I made to get the script to run was to add a cd to tmp inside the script:

cd /tmp;
find . -maxdepth 1 -name "search*.csv" -mmin +0 -exec rm {} \;

This was more by luck than judgement but it is now working perfectly. I hope this helps.


It’s a simple problem. When you are running from terminal, you are running the php file from terminal as a privileged user. When you go to the php from your web browser, the php script is being run as the web server user which does not have permissions to execute files in your home directory. In Ubuntu, the www-data user is the apache web server user. If you’re on ubuntu you would have to do the following:
chown yourusername:www-data /home/testuser/testscript
chmod g+x /home/testuser/testscript

what the above does is transfers user ownership of the file to you, and gives the webserver group ownership of it. the next command gives the group executable permission to the file. Now the next time you go ahead and do it from the browser, it should work.

Leave a Reply

Your email address will not be published. Required fields are marked *