У вашего кода много проблем:
- он запускает новую копию
awk
для каждой выбранной строки (awk
вообще не требуется); - пытается запустить первый l oop несколько раз (один раз для каждого элемента
"$BADWORDS"
) - первый l oop никогда не завершится (из-за
tail -F
), и поэтому iptables
l oop никогда не запускается - команда
iptables
добавляет новое правило, даже если IP был замечен до - , проще написать
i<entries
, чем i<=entries-1
, и еще проще просто используйте for setBadword in "${BADWORDS[@]}"; do ...
Если вы действительно хотите постоянно l oop читать журнал, с помощью утилит GNU вы можете сделать что-то вроде:
#!/bin/sh
log=/var/log/apache2/access.log
words=/my/list/of/badwords/one/per/line
banned=/my/list/of/already/banned/ips
tail -F "$log" |\
grep --line-buffered -Ff "$words" |\
while read ip junk; do
grep -qxF $ip "$banned" || (
iptables -A INPUT -s $ip -j DROP
echo $ip >> "$banned"
)
done
# we never get here because "tail -F" never finishes
To просто обработайте лог-файл один раз, а затем, наконец, sh, вы можете напрямую подавать grep
из "$log"
:
grep --line-buffered -Ff "$words" "$log" | ...
, но, вероятно, менее подвержен ошибкам, просто используйте fail2ban
, который специально разработан для такого рода задач.