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
효율성을 높이기 위해 루프 없이 한 번만 호출 하는 방법에 대한 terdon의 답변을 참조하세요 .
그러나 이 접근 방식의 문제점은 작업 중인 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