Issuing Commands From Web Pages

If you install a PHP web server on your RPi you can issue commands using the PHP system() function.

Examples:


//Echo some system status:
	echo '<pre>';
	system('netstat -a');
	echo '</pre>';
//Run an executable file:
	echo '<pre>';
	system("sudo /home/pi/projects/my_project.a");		//system() will echo the output of the executable, use shell_exec() instead if you don't want this
	echo '</pre>';

WARNING!! When allowing user-supplied data to be passed use escapeshellarg() or escapeshellcmd() to ensure that users cannot trick the system into executing arbitrary commands.

system()

Also echo's the output of the command to the web page

shell_exec()

Does not echo the output of the command and returns you all of the output

exec()

Does not echo the output of the command but returns only the last line of any output

 

If it doesn't work

Try adding this to the end of your command: 2>&1
For example: sudo fping -c1 -t750 192.168.1.1 2>&1
This will cause error text to be returned

Issuing commands in the background

You can't just add the '&' character to the end of commands In PHP, because all calls are always waiting for the command to return.  There's a good post in the issue here: http://phaq.phunsites.net/2012/01/18/run-command-in-background-from-php/

To fix it you need to direct the console output to a file instead and just adding this to the end of a command will do that:  > /dev/null 2>&1 & echo $!

The following example issues a reboot command after a 2 second delay (you need to add the command to sudoeres for it to work – see below) and does it in the background so that the page is loaded before the reboot is actioned:


<?php
	//----- DO THE REBOOT -----
		//THIS SUDO COMMAND HAS AUTHORISED FOR APACHE TO USE IN THE FILE: sudo nano /etc/sudoers
		//	# Special for this system - let apache run exes we use in the web interface
		//	www-data ALL=NOPASSWD: /sbin/reboot
	echo '<pre>';
	system("(sleep 2 ; sudo /sbin/reboot ) > /dev/null 2>&1 & echo $!");
	echo '</pre>';
?>
Issuing sudo commands

Apache will typically run using account www-data and this account is not permitted to use sudo.  If you need to use sudo you need to enable this, but you don't want to simply give www-data global sudo access. If a malicious script is uploaded to your web server and gets executed this opens a massive security risk. The more secure approach is to restrict it to only the commands that you actually use in your own scripts.

You can use this command to open the sudoers file:


sudo nano /etc/sudoers

BE VERY CAREFUL TO COPY THIS FILE BEFORE YOU CHANGE IT – IF YOU MAKE AN ERROR YOU CAN STOP YOURSELF BEING ABLE TO OPEN THE FILE USING SUDO (changes to it are instant)!

An example enabling it to run a single executible, add this to the end of the file:


www-data ALL=NOPASSWD: /home/pi/some_executable_name

An example enabling it to run several different executables, add this to the end of the file:


www-data ALL=NOPASSWD: /home/pi/some_executable_name, /home/pi/some_executable_name some_option, /home/pi/some_other_executable_name
Passing $_POST Data To A Running Application

There is a really useful way of using the PHP system function to pass data to a running application on your RPi (e.g. your own application doing something with the IO) if you create a FIFO within it.  Then you can use use a web page like this to pass it data from a form or $_POST input:


-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>My Page</title>
</head>
<body>
<?php
	if ($_POST['Command'])
	{
		$Command = trim($_POST['Command']);
		echo "Command received: $Command<br />";
		system("sudo sh -c 'echo \"". escapeshellarg($Command) . "\" > /tmp/my_fifo'");
	}
?>

<div align="center">
  <form id="form1" name="form1" method="post" action="">
    <p>
      <label for="Command">Command:</label>
      <input type="text" name="Command" id="Command" size="80" />
      <input type="submit" name="Send" id="Send" value="Send" />
    </p>
  </form>
</div>
</body>
</html>

Escaping user supplied data – IMPORTANT!

When allowing user-supplied data to be passed to the system() function, ensure you use escapeshellarg() or escapeshellcmd() so that users can't trick the system into executing arbitrary commands.

Confirming which user apache is running as


<?php
echo exec('whoami');
?>

 

 

 

 

USEFUL?
We benefit hugely from resources on the web so we decided we should try and give back some of our knowledge and resources to the community by opening up many of our company’s internal notes and libraries through mini sites like this. We hope you find the site helpful.
Please feel free to comment if you can add help to this page or point out issues and solutions you have found, but please note that we do not provide support on this site. If you need help with a problem please use one of the many online forums.