有几点值得注意:
该exec
函数的签名是
string exec ( string $command [, array &$output [, int &$return_var ]] )
要获得命令的完整输出,您必须像这样调用它:
$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;
您正在使用该exec
命令,就好像它是passthru
,在您的情况下可能值得一看:
命令结果的最后一行。如果您需要执行命令并将命令中的所有数据直接传回而不受任何干扰,请使用passthru() 函数。
重要的是,当您手动运行命令时,它可以访问您登录时加载的所有环境变量(以及在您的.profile
or.basrc
文件中设置的任何其他变量)。使用 crontab 或通过 ssh 运行命令时,情况并非如此。
也许,$PATH
环境变量已设置为您无权访问ip
其他命令。对此有简单的修复:
exech('/sbin/ip route');//if that's the correct path
或者,准备好第二个脚本,并将您的 PHP 脚本更改为:
if (!exec('which ip'))
{//ip command not found
return exec('helper.sh '.implode(' ', $argv));//helper script
}
辅助脚本如下所示:
#/bin/bash
source /home/user/.bashrc
$*
只是$*
再次调用原始 PHP 脚本,只是这一次,配置文件已加载。您可以将source
调用替换为export PATH=$PATH:/sbin
或其他内容,然后按照您需要的方式设置环境变量。
第三部分也是最后一部分使用管道和proc_open
. 这是加载配置文件并递归调用脚本的仅 PHP 方式:
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
这就是我解决我的一个老问题的方法,我遇到了未设置环境变量的困难
最后要注意的是:运行 crontab 的用户是否具有执行需要执行的操作所需的权限?