Файл журнала хвоста на нескольких машинах через ssh

37

Я пытаюсь tailзаписать файл журнала на несколько удаленных компьютеров и переслать вывод на мою локальную рабочую станцию. Я хочу, чтобы соединения закрывались при нажатии Ctrl- C.

На данный момент у меня есть следующая функция, которая почти работает как задумано.

function dogfight_tail() {
 logfile=/var/log/server.log
 pids=""
 for box in 02 03; do
   ssh server-$box tail -f $logfile | grep $1 &
   pids="$pids $!"
 done
 trap 'kill -9 $pids' SIGINT
 trap  wait
}

Соединения закрываются, и я получаю вывод от tail. НО, происходит какая-то буферизация, потому что выходные данные идут партиями.

И вот самое интересное…

Я могу видеть такое же поведение буферизации при выполнении следующего и добавляю «test» к файлу /var/log/server.logна удаленных машинах 4-5 раз…

ssh server-01 "tail -f /var/log/server.log | grep test"

... и нашел два способа его отключения ...

  1. Добавьте флаг -t в ssh.

    ssh -t server-01 "tail -f /var/log/server.log | grep test"
  2. Удалить цитату из удаленной команды.

    ssh server-01 tail -f /var/log/server.log | grep test

Однако ни один из этих подходов не работает для функции, которая выполняется на нескольких машинах, упомянутых выше.

Я пробовал dsh, которые имеют такое же поведение буферизации при выполнении.

dsh -m server-01,server-02 -c "tail -f /var/log/server.log | grep test"

То же самое и здесь, если я уберу цитату, буферизация исчезнет, ​​и все будет нормально.

dsh -m server-01,server-02 -c tail -f /var/log/server.log | grep test

Также попробовал, parallel-sshкоторый работает точно так же, как dsh. Может кто-нибудь объяснить, что здесь происходит?

Как мне решить эту проблему? Было бы идеальным, чтобы пойти с прямой, sshесли это возможно.

PS Я не хочу использовать multitailили подобное, так как я хочу иметь возможность выполнять произвольные команды.

deephacks
источник
Вы можете оформить заказ dbitailи скачать его отсюда .

Ответы:

36

То, что вы видите, является эффектом стандартного буфера stdout, grepпредоставленного Glibc. Лучшее решение - отключить его с помощью --line-buffered(GNU grep, я не уверен, какие другие реализации могут его поддерживать или что-то подобное).

Что касается того, почему это происходит только в некоторых случаях:

ssh server "tail -f /var/log/server.log | grep test"

запускает всю команду в кавычках на сервере - таким образом grepждет заполнения своего буфера.

ssh server tail -f /var/log/server.log | grep test

работает grepна вашем локальном компьютере на выходе, tailотправленном через канал ssh.

Ключевой частью здесь является то, что он grepрегулирует свое поведение в зависимости от того, stdinявляется ли он терминалом или нет. Когда вы запускаете ssh -t, удаленная команда работает с управляющим терминалом, и, таким образом, удаленный grepведет себя как ваш локальный.

peterph
источник
Большое спасибо за подробное объяснение. Теперь это имеет смысл для меня, и скрипт работает, как и ожидалось, с --line-buffered.
Deephacks
@deephacks В этом случае, пожалуйста, подумайте о принятии ответа - он дает подсказку другим, имеющим ту же проблему.
Петер
1
Буферизация grep / glibc зависит от его стандартного вывода . ssh tail | grepвыходы на локальный терминал, небуферизованные. ssh -t "tail|grep"выводит в pty, небуферизованный. ssh "tail|grep"вывод на канал (до sshd), буферизированный (если не --line-buffered).
dave_thompson_085
2

Проверь это: multitail

MultiTail позволяет отслеживать журналы и вывод команд в нескольких окнах в терминале, раскрашивать, фильтровать и объединять.

Для привязки журналов на нескольких серверах используйте:

multitail -l 'ssh user@host1 "tail -f /path/to/log/file"' -l 'ssh user@host2 "tail -f /path/to/log/file"'
LeoChu
источник
3
Но это не позволяет вам делать это через ssh, что является условием этого вопроса. (И, кроме того, вопрос конкретно гласит: «Не хочу использовать многоярусный».)
епископ
1
@bishop: Я думаю, что эта критика несправедлива отчасти потому, что, хотя в вопросе, возможно, указывалось, что не используется многоходовая сеть, похоже, это связано с недоразумением. В приведенном выше примере показано, как использовать произвольные команды, и обычные расширения оболочки также работают - multitail <(ssh …) <(ssh …)что позволяет получить желаемый результат, даже если они не думали, что на этот вопрос можно было ответить.
Крис Адамс
0

Вы можете оформить заказ в личном журнале.

Я создал инструмент Java, способный читать локальные и удаленные файлы журналов, используя SSH. Это довольно просто в использовании.

Еще несколько объяснений: https://github.com/pschweitz/insidelog/wiki

Просто загрузите версию, соответствующую вашей операционной системе, с собственным исполняемым файлом jar release в вашей среде выполнения Java (требуется java 8_40 или выше):

https://github.com/pschweitz/insidelog/releases

Вы можете найти полную документацию (в том числе и на странице Github)

Филипп Швейцер
источник