1

いくつかのシェル コマンドを実行する PHP スクリプトがあります。

手動で実行したら。とてもうまくいきました。

しかし、crontab を使用して実行した後、一部のシェル コマンドの結果が表示されません。

これらは 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

この問題についてのアイデアがあれば、よろしくお願いします。

4

2 に答える 2

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、あなたのケースでは一見の価値があるかもしれません:

コマンドの結果の最後の行。コマンドを実行する必要があり、コマンドからのすべてのデータを干渉なしで直接返す必要がある場合は、 passthru() 関数を使用します。

コマンドを手動で実行すると、ログイン時にロードされたすべての環境変数 (および.profileまたは.basrcファイルに設定された追加の変数) にアクセスできないことが重要です。これは、crontab または ssh を介してコマンドを実行する場合には当てはまりません。
おそらく、環境変数が設定されているため、他のコマンド$PATHにアクセスできません。ipこれには簡単な修正があります:

exech('/sbin/ip route');//if that's the correct path

または、2 つ目のスクリプトを用意して、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必要な方法で環境変数を設定するだけです。

3 番目の最後の部分では、パイプを使用し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 を実行しているユーザーは、実行する必要があることを実行するために必要なアクセス許可を持っているかということです。

于 2013-08-26T10:39:06.350 に答える
0

スクリプトを実行するユーザーに注意してください。ユーザー (crontab タスクを追加する) が十分な権限を持っていない可能性があります。

于 2013-08-26T10:21:15.107 に答える