我们在 shell 脚本中包含此代码,该脚本通过管道输出供 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
呈指数级增长了四倍,直至服务器的根切片被填满。寻找一种更好的方法,在 Apache 写入access.log
.
答案1
这里的问题是,您正在读取 Apache 日志并同时写入。无论您添加到日志中的是什么,也会通过调用将其返回到管道中cat
(没有双关语的意图:))。这会创建一个令人讨厌的正反馈循环,该循环将继续工作,直到您的文件系统填满为止。答案是这个问题您可能对为什么会发生这种情况感兴趣。
那你该怎么办呢?一个简单的解决方案是像这样修改文件:
for item in ${!values[@]};do
sed -i "..." "$apacheLog" #cat isn't needed here
done
并且不要将输出传送到任何地方:脚本本身将修改文件就地。另请参阅terdon的答案,了解如何sed
仅调用一次(不循环)以提高效率。
然而,这种方法的问题在于,当您处理文件时,实时 Apache 服务器可能会将内容记录到文件中,并且可能会开始发生奇怪的事情。更好的解决方案是在 Apache 文档中查找将敏感信息排除在日志之外的方法。
顺便说一句,您正在做的事情甚至没有清理日志:它将清理后的行附加回(仍然受污染的)日志文件中。
答案2
就目前情况而言,您可以进行各种改进。首先,也是最不重要的,你有一个对猫的无用利用。更重要的是,您运行了sed
多次,每次都会打印出整个文件。我不太确定你在做什么grep
,你是否试图只打印那些包含特定变量的行?
不管怎样,一种做得更好的方法是运行sed
一次并让它完成所有替换。就像是:
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