0

私は bash の初心者で、大きな syslog ファイルを最初から最後まで読み取る bash スクリプトを作成し、特定の分 (最後の 1 分前) に属するエントリを探し、それぞれの発生回数をカウントします。与えられたパターンはその分に持っています。PHP/Python から実行すると機能しませんが、次のように直接呼び出すと機能します。

sh /path/to/logparser.sh /path/to/big.log '2013-09-23T08:38' '2013-09-23T08:37' 'MySQL has gone away' 'Unhandled Error timed out'

以下はのコードですlogparser.sh

logfile=$1
echo $logfile
shift
minute=$1
echo $minute
shift
minute_before=$1
echo $minute_before
shift
command="tac $logfile | sed -n -e '/$minute/p' -e '/$minute_before/q'"
echo $command
if [ -f $logfile ]; then
    buffer=$(eval $command)
    echo "buffer complete"
    exit 1
fi

補足:

  • コマンドラインでもハングアップするbuffer=$(eval $command)ので使っていますbuffer=$(tac $logfile | sed -n -e '/$minute/p' -e '/$minute_before/q')
  • -e '/$minute_before/q'`-e '/$minute/!q' を動作させることができなかったので、sed で使用しました

しかし、PHP 経由pasthru()または Python 経由subprocess.Popen().communicate()で実行すると、ハングします。プロセスを確認すると、まだ実行されていることがps -ef rわかります。tac

bash スクリプトを呼び出す PHP コードは次のとおりです。

$env           = $argv[1];
$service_name  = $argv[2];
$logfile       = $argv[3];
$minute        = $argv[4];
$minute_before = $argv[5];

$command = 'sh '.dirname(__FILE__).'/logparser.sh ';

$n = count($argv);
for($i=3; $i<$n; $i++){
    $command .= ' ' . escapeshellarg($argv[$i]);
}
$command .= "\n";
echo "\npassthru {$command}";
passthru($command, $out);
var_dump($out);
exit();

bash スクリプトを呼び出す Python コードは次のとおりです。

env           = sys.argv[1]
service_name  = sys.argv[2]
logfile       = sys.argv[3]
minute        = sys.argv[4]
minute_before = sys.argv[5]

args = ['sh', '%s/logparser.sh' % os.getcwd()]

for i in range(3, len(sys.argv)):
    args.append(sys.argv[i])

print args
output = subprocess.Popen(args, stdout=subprocess.PIPE).communicate()
print output

私が除外した他のもの:

  • exec 権限: PHP と Python の両方を実行して、次のような Linux コマンドの結果を取得できます。whoami
  • ファイルのアクセス許可: PHP と Python の両方が、単純な bash スクリプト (例: dateliunx コマンドを含むファイル) に対して完全に実行されます。ログファイルにはすべての読み取り権限があります
  • 悪いパラメーター: PHP/Python によって送信されるパラメーターと、コマンド ライン経由で送信されるパラメーターを bash スクリプトで比較しましたが、それらは同一です。

PHP/Python から呼び出されるようにするにはどうすればよいですか?

4

1 に答える 1

2

どのコードもログファイルをシェル スクリプトに渡していないようです。代わりに標準入力からの tac 待機入力を作成するシェルで logfile 変数が設定されていません。

Python コードと同様に、おそらく次のようにする必要があります。

for i in range(1, len(sys.argv)):
    args.append(sys.argv[i])

同様にあなたのphpコードで:

$n = count($argv);
for($i=1; $i<$n; $i++){
    $command .= ' ' . escapeshellarg($argv[$i]);
}

ログファイルのパスがシェル スクリプトに渡されない実際の原因は異なる場合がありますが、一般的にはそれがスクリプトがハングする基本的な理由です。

于 2013-09-23T10:25:12.913 に答える