Intereting Posts
Wi-Fi не подключается, хотя он показывает все ssid Sparc Solaris – установить оптимизированный GCC 4.9, 32/64 бит? безопасная конфигурация xorg nohup отправляет eof (или некоторые другие данные) информацию о моем приложении при работе рекурсивно. Как остановить или вообще не отправлять? Является ли лучшей практикой не использовать заглавные буквы в именах файлов? Может ли Xorg-Server и Wayland-Compositor запускаться одновременно в Linux? как добавить устройство loop на Fedora 23 с помощью losetup? Очистка хром-файлов cookie с сайта при загрузке? force rsync, чтобы перезаписать файлы в пункте назначения, даже если они новее Как отформатировать последние 3 столбца файла, начиная с 30-й вкладки или 88-го пробела Как запустить grep в файлах epub / mobi? Контейнер LXC получает два назначенных ему IP-адреса Не удалось удалить папку, даже с `–force`, sudo не требуется Есть ли способ обойти .zshrc при входе в систему? определить (в скрипте), если команда запускается в терминале (из файла рабочего стола?)

uniq и bash для цикла, не записывающего в stdout перед закрытием stdin (для системы уведомлений посетителей в одной строке)

Я пытаюсь вызвать звуковой сигнал на динамике ПК для каждого уникального посетителя веб-сайта.

После некоторого «мозгового штурма» это казалось возможным с одной строкой:

for e in `ssh me@mymachine "tail -n 1 -f /var/log/apache2/test.log | awk '{print $1}' | uniq"`; do beep; done 

Однако uniq ничего не выводит, пока stdin открыт (кажется, ждет EOF). То же самое касается цикла for. Если я удалю uniq из цепочки, я все равно не получаю выход с хвостом, удерживающим трубу открытым.

Кажется, это не из-за буферизации. Даже если я пишу> 100.000 строк в тестовый файл при запуске этой команды, на другом конце нет выхода.

Есть ли способ получить эту работу без полного уничтожения красоты (простоты) решения?

Обновить

Я решил первую часть. uniq разблокируется путем префикса команды tail с помощью stdbuf -oL -eL (см. https://unix.stackexchange.com/a/25378/109296 ). То же самое не работает для цикла.

Обновление 2

Я получил его работу, но не совсем по моей спецификации и с двумя строками:

 while [ 1 -eq 1 ]; do ssh root@speedy "stdbuf -oL -eL tail -n 1 -f /var/log/apache2/www.access.log | stdbuf -oL -eL grep 'GET / '"; sleep 60; done > www.log 

awk '{print $1}' отсутствует, потому что он не работал внутри этой конструкции (просто прошел через всю строку). Я не знаю почему. Но я могу жить без, потому что в любом случае uniq оказался не очень полезным, потому что он смотрит только на смежные строки, а это значит, что шаблоны запросов ip1, ip2, ip1 все равно позволят ip1 через два раза. uniq -u будет делать то, что я ожидаю, но имеет ту же проблему, что и sort : не выводит ничего, пока stdin открыт (даже при использовании stdbuf -oL .

Эта команда просто записывает все запросы для базового URL (/) в другой файл. Я завернул его в цикл (и подождал), чтобы он автоматически повторил, если по какой-либо причине прерывается соединение или соединение.

while inotifywait -e modify www.log; do beep -f 250; done while inotifywait -e modify www.log; do beep -f 250; done делает звук! Я не мог заставить bash for loop обрабатывать строки за строкой без буферизации, а также пытался while read с тем же результатом. Таким образом, я сдался и продолжил с inotifywait который, однако, означает, что мне нужен промежуточный файл (возможно, именованный канал также работал бы, не пытался. На самом деле для меня это не имеет значения).

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

Это будет приятным сюрпризом для членов моей команды, когда они вернутся в офис 🙂

Я планирую расширить эту систему уведомлений, чтобы отслеживать несколько событий, используя разные звуковые частоты. Это лучшая работа, которую я нашел до сих пор для старого сервера, собирающего пыль …

Думаю, я понимаю, чего вы пытаетесь достичь:

  1. Для каждого попадания на веб-сайт, который регистрируется веб-сервером:
  2. Если визит является «уникальным» (как вы это определяете?), Запишите запись и отправьте звуковое уведомление.

Трюк заключается в том, как вы определяете «уникальный». Это по URL-адресу, по IP-адресу, cookie? Ваш подход с awk был, вероятно, правильным путем, но вы были обмануты правилами оболочки.

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

 while true; do ssh root@speedy remote-log-capturing-script done > unique-visits.log 

Используйте превосходное предложение mikeserv о MAILFILE. Сценарий на скорости должен выглядеть так:

 #!/bin/sh tail -1f /var/log/apache2/www.access.log | awk '$(NF-1) == 200' | grep --line-buffered -o '"GET [^"]*"' | awk '!url[$1]{ print; url[$1]=1 }' 

Awk всегда буферизируется по строке. Первый awk гарантирует, что вы получите фактические успешные хиты, а не кешированные хиты или 404s. Grep -o выводит только соответствующую часть ввода, в данном случае, URL. (Это GNU grep, который, как я полагаю, вы используете. Если нет, используйте трюк stdbuf.) Следующий awk использует небольшое выражение, чтобы условно распечатать строку ввода – только если эта строка ввода никогда не просматривалась.

Вы также можете сделать это с помощью perl для достижения большей сложности в одной вилке:

 #!/bin/sh tail -1f /var/log/apache2/www.access.log | perl -lane '$|=1;' \ -e 'if ($F[$#F-1] eq "200" and ' \ -e ' /\s"GET\s([^"]*)"\s/ and !$url{$1}) { '\ -e ' print $1;$url{$1}=undef; }' 

Теперь обе они будут печатать только уникальные URL-адреса. Что делать, если два веб-клиента из разных IP-адресов попадают на одну страницу? Вы получаете только один результат. Чтобы изменить это, с помощью решений perl это легко: измените ключ, который входит в URL-адрес.

  $url{$F[0],$1} 

При использовании perl -a, $ F [0] представляет собой первое поле ввода с пробелом, как и awk $ 1 – то есть, имя хоста / IP-адреса соединения. И perl $ 1 представляет собой первое сопоставление подвыражения регулярного выражения /\s"GET\s([^"]*)"\s/ , т. Е. Только самого URL. Критический $F[$#F-1] означает второе-последнее поле входной строки.

Это то, что я, наконец, пришел, благодаря аккуратной команде Perl, внесенной JJoao:

 # убить все по завершении
 ловушка "убить 0" SIGINT SIGTERM
 # Удостоверьтесь, что удаленные процессы были убиты при выходе, см. Http://unix.stackexchange.com/questions/103699/kill-process-spawned-by-ssh-when-ssh-dies
 shopt -s huponexit
 (while [1 -eq 1]; do ssh -t -t root @ speedy "stdbuf -oL -eL tail -n 1 -f /var/log/apache2/www.access.log | stdbuf -oL -eL grep ' GET / '| stdbuf -oL -eL perl -naE' ($ a {$ F [0]} ++ == 0) и скажем $ F [0] '"; sleep 60; done> www.log) &
 (while inotifywait -e modify www.log; do beep -f 250; done) &