このコードは、Apache がログに出力をパイプするシェル スクリプトにあります。
declare -a values=( $taintRequestVals )
for item in ${!values[@]}
do
cat $apacheLog | sed "s/${values[$item]}=[^&\t\n]*/${values[$item]}=***/g" | /bin/grep ${values[$item]}=
done
しかし、これは非常に非効率的です。数秒以内に、 はaccess.log
指数関数的に 4 倍になり、サーバーのルート スライスがいっぱいになりました。Apache が に書き込んでいる間に、パスワードなどの機密データを難読化するより良い方法を探していますaccess.log
。
答え1
ここでの問題は、Apache ログからの読み取りと書き込みを同時に行っていることです。ログに追加したものは、呼び出しを通じてパイプラインにも戻されますcat
(言葉遊びではありません :) )。これにより、ファイルシステムがいっぱいになるまで機能し続ける厄介な正のフィードバックループが作成されます。この質問なぜこのようなことが起こるのか、あなたにとって興味深いかもしれません。
では、どうすればよいでしょうか? 単純な解決策としては、次のようにファイルをその場で変更することです。
for item in ${!values[@]};do
sed -i "..." "$apacheLog" #cat isn't needed here
done
出力をどこにもパイプしないでください。スクリプト自体がファイルを変更します。現地でsed
効率を向上させるために、呼び出しを 1 回だけ (ループなしで)行う方法については、terdon の回答も参照してください。
ただし、この方法の問題点は、作業中にライブ Apache サーバーがファイルにログを記録する可能性が高く、奇妙なことが起きる可能性があることです。よりよい解決策は、ログから機密情報を排除する方法を Apache のドキュメントで調べることです。
ちなみに、あなたがやっていることはログをサニタイズすることさえありません。サニタイズされた行を(まだ汚染された)ログ ファイルに追加し直すだけです。
答え2
現状では、改善できる点がいろいろあります。まず、あまり重要ではないのですが、猫の無駄使い。さらに重要なのは、複数回実行しsed
、そのたびにファイル全体を印刷することです。 で何をしているのかよくわかりませんがgrep
、特定の変数を含む行だけを印刷しようとしているのでしょうか?
sed
とにかく、物事をより良く行う方法の 1 つは、一度実行してすべての置換を実行することです。次のようになります。
replace=""
for item in ${!values[@]}
do
## build the sed line
replace="s/${values[$item]}=[^&\t\n]*/${values[$item]}=***/g;$replace"
done
### run the replacement using sed's -i option so it
### changes the original file
eval sed -i \""$replace"\" $apacheLog