Intereting Posts
Какие параметры сети необходимо изменить, чтобы получить доступ к моей гостевой оракуле Linux с встроенной виртуальной машиной с моего хоста? Невозможность подключения клиента NIS Debian к серверу OpenSuse 12.1 В zsh, как я могу быстрее отказаться от процесса переднего плана? Не удается найти linux-заголовки-4.3.0-kali-amd64 В чем разница между «и» – и когда использовать его? Почему «sshd Bad prime description» ошибки? Может ли кто-нибудь удалить папку «/ bin» в Linux? Как установить Octave без GUI в Ubuntu 16.04? Дубликаты в истории bash Как получится, когда x = abc, ] && echo yes || эхо не возвращается? Мультипликации псевдонимов для одной команды Безопасно ли делиться / дома между Ubuntu и Fedora? Как установить скорость повторения клавиатуры USB с помощью udev? Совместное использование псевдонимов и настроек PATH между zsh и bash Любые проблемы с использованием высоких номеров UID (3000+) на RHEL5 +?

Периодически получать новые строки из файла, возможно, зависания

Я ищу довольно простой способ (никакого развития не было – я мог бы написать это на Python, но я надеюсь, что есть что-то уже там).

У меня есть файл журнала (в моем случае написан rsyslogd). Для целей аналитики я хочу читать его каждые 1 минуту и ​​вычислять показатели за последнюю минуту, например, сколько страниц попадает на мой HTTP-сервер. Мои 2 требования:

1) Я только хочу посмотреть строки, которые были добавлены с момента последнего чтения файла. (Мне нужна только последняя минута или около того, и файл слишком большой, чтобы перечитывать и фильтровать каждую минуту).

2) Один раз в день файл получает logrorate'd. В первый раз после вращения журнала мне нужны все строки из предыдущего файла, который я еще не читал, плюс все строки из нового файла.

Я полагаю, что теперь я единственный, у кого такие требования – что делают другие?

Предполагая, что your-filter читает данные из stdin:

 while your-filter; do sleep 60 done < file.log 

Это предполагает, что your-filter просто считывает данные и, например, не пытается просмотреть его.

Теперь, чтобы решить проблему вращения журнала, если в Linux (где, вопреки большинству других систем, /dev/fd/n являются символическими ссылками на фактические файлы), с помощью ksh , bash , zsh , dash , yash (большинство оболочек POSIX, кроме самые педантичные POSIX, такие как posh как -ef , не POSIX):

 while your-filter; do if [ file.log -ef /dev/stdin ]; then sleep 60 else exec < file.log fi done < file.log 

При вращении журнала, который будет вызывать your-filter дважды, если вы хотите, чтобы его вызывали один раз с конкатенацией старого и нового:

 while if [ file.log -ef /dev/stdin ]; then your-filter else exec 3<&0 < file.log (cat <&3; cat) | your-filter && exec 3<&- fi do sleep 60 done < file.log 

Теперь при вращении журнала может быть время, когда старый файл.log был переименован, но новый file.log не создан, и в этом случае вышеуказанное не будет выполнено, если оно выполнено exec < file.log при этом момент. Тогда вы можете исправить это с помощью:

 while if [ file.log -ef /dev/stdin ] || ! command exec 3< file.log; then your-filter else (cat; cat <&3) | your-filter && exec <&3 3<&- fi do sleep 60 done < file.log 

Поэтому он продолжает чтение старого файла, пока не появится новый.

command необходима, чтобы избежать выполнения exec чтобы заставить оболочку выйти, когда она терпит неудачу (как требует POSIX). Это не нужно с zsh или bash когда он не находится в режиме sh .

Теперь мы спим в течение 60 секунд в цикле, и your-filter может занять несколько секунд. Если важно, чтобы your-filter запускался каждую минуту в среднем, с ksh , bash или zsh , вы могли бы изменить его на:

 t=$SECONDS while if [ file.log -ef /dev/stdin ] || ! command exec 3< file.log; then your-filter else (cat; cat <&3) | your-filter && exec <&3 3<&- fi do t=$(($t + 60)) sleep "$((t - SECONDS))" done < file.log 

С ksh93 и zsh , и если ваш sleep принимает аргументы с плавающей запятой, вы можете запустить typeset -F SECONDS .