Sanitize файлы журнала доступа Apache?

У нас есть этот код в сценарии оболочки, который выводит данные для 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 .

Проблема здесь в том, что вы читаете из журнала Apache и записываете ее одновременно. Независимо от того, что вы добавили в журнал, он снова возвращается в конвейер через cat вызов (для него не предусмотрено никакого текстового слова :)). Это создает неприятный положительный цикл обратной связи, который будет работать до тех пор, пока ваша файловая система не заполнится. Ответ на этот вопрос может быть интересным для вас, почему это происходит.

Как вам тогда это заняться? Наивным решением было бы изменить файл на месте так:

 for item in ${!values[@]};do sed -i "..." "$apacheLog" #cat isn't needed here done 

и не выворачивайте вывод в любом месте: сам скрипт будет изменять файл на месте . Также см. Ответ Тердона о том, как сделать вызов sed только один раз (без цикла), чтобы повысить эффективность.

Проблема с этим подходом, однако, заключается в том, что живой сервер Apache, скорее всего, будет записывать файлы в файл, когда вы работаете над ним, и могут начаться странные вещи. Лучшим решением было бы посмотреть в документации Apache способы сохранения конфиденциальной информации из журналов.

Кстати, то, что вы делаете, даже не дезинфицирует журналы: оно добавляет очищенные строки обратно в файл журнала (все еще испорченный).

В его нынешнем виде есть различные улучшения, которые вы можете сделать. Во-первых, и, что менее важно, у вас бесполезное использование кошки . Что гораздо важнее, так это то, что вы запускаете 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