A couple of things worth noting:
The exec
function's signature is
string exec ( string $command [, array &$output [, int &$return_var ]] )
To get the full output of a command you'll have to call it like so:
$output = array();//declare in advance is best because:
$lastLine = exec('ip route', $status, $output);//signature shows reference expected
print_r($output);//full output, array, each index === new line
echo PHP_EOL, 'The command finished ', $status === 0 ? 'well' : 'With errors: '.$status;
You're using the exec
command as though it were passthru
, which might be worth a look in your case:
The last line from the result of the command. If you need to execute a command and have all the data from the command passed directly back without any interference, use the passthru() function.
It's important to not that, when you run the command manually, it has access to all your environment variables, loaded when you log in (and any additional vars set in your .profile
or .basrc
file). This is not the case when running a command using crontab or over ssh.
Perhaps, the $PATH
environment variable is set so, that you don't have access to ip
and other commands. There are easy fixes for this:
exech('/sbin/ip route');//if that's the correct path
Or, have a second script at the ready, and change your PHP script to:
if (!exec('which ip'))
{//ip command not found
return exec('helper.sh '.implode(' ', $argv));//helper script
}
With the helper script looking like this:
#/bin/bash
source /home/user/.bashrc
$*
Where $*
merely calls the original PHP script again, only this time, the profile has been loaded. You could replace the source
call with export PATH=$PATH:/sbin
or something, and just set the environment variables up the way you need them.
The third, and final part uses pipes, and proc_open
. It's a PHP-only way of loading the profile and calling the script recursively:
if(!$_SERVER['FOO'])
{//where FOO is an environment variable that is loaded in the .profile/.bashrc file
$d = array(array('pipe','r'),array('pipe','w'));
$p = proc_open('ksh',$d,$pipes);
if(!is_resource($p) || end($argv) === 'CalledFromSelf')
{//if the last argument is calledFromSelf, we've been here before, and it didn't work
die('FFS');//this is to prevent deadlock due to infinite recursive self-calling
}
fwrite($pipes[0],'source /home/user/.profile'."\n");
fwrite($pipes[0],implode(' ',$argv).' CalledFromSelf'."\n");
fclose($pipes[0]);
usleep(15);//as long as you need
echo stream_get_contents($pipes[1]);
fclose($pipes[1]);
proc_close($p);
exit();
}
echo $_SERVER['FOO'].PHP_EOL;//actual script goes here, we can use the FOO env var
This is how I solved an old question of mine where I encountered difficulties with environment variables not being set
Last thing to note is: Does the user running crontab have the permissions required to do what needs to be done?