2013-08-26 32 views
1

我有一個執行一些shell命令的PHP腳本。結果格式crontab與手動執行不一樣嗎?

一旦我手動執行它。它工作得很好。

但我用crontab來執行後,一些shell命令的結果丟失。

這些是2個命令。

  • ip route
  • iptables -t nat -L | grep 8800

這裏是一個示例PHP代碼。

#!/usr/bin/php -q 
<? 
    $route = exec('ip route'); 
    $iptable = exec('iptables -t nat -L | grep 8800'); 
    echo $route; 
    echo $iptables; 
?> 

上面的代碼在手動執行而不是crontab的情況下運行良好。

我發現有些命令既行之有效。例如

  • ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'
  • cat /tmp/example | grep test

對於這個問題的任何想法,並預先感謝您。

回答

0

注意哪些用戶運行該腳本。可能是用戶(您添加crontab任務)沒有足夠的權限。

+0

用戶已經有權限。 – Guilgamos

+0

@Guilgamos:也許,但是哪個用戶正在運行腳本?它屬於哪個組?它需要'sudo'來運行網絡相關的命令嗎?在* NIX系統上,這不是不可能的,畢竟如果在命令行中運行腳本, –

+0

之後,腳本將以當前用戶權限運行。如果腳本通過crontab運行 - 具有crontab文件所屬用戶的權限。使用crontab -l -u用戶名爲某用戶顯示crontab文件 –

4

幾件事情值得一提:

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,這可能是值得你的情況看:

從命令的結果的最後一行。如果您需要執行命令並將命令中的所有數據直接傳回而不受任何干擾,請使用the passthru() function

這是不那麼重要,當你手動運行該命令,它可以訪問所有的環境變量,當您登錄加載(和你的.profile.basrc文件中設置任何附加VAR)。使用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腳本,只有這一次,配置文件已被加載。您可以用export PATH=$PATH:/sbin或其他東西代替source調用,只需按照需要的方式設置環境變量即可。

第三,最後一部分使用管道,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 

這是我如何解決an old question of mine在那裏我遇到了未設置

最後一點要注意的是環境變量的困難:是否運行crontab的用戶擁有需要執行什麼操作的權限?

相關問題