2013-10-03 2 views
2

Я пишу сценарий оболочки, который должен контролировать некоторые файлы журналов и перенаправлять вывод в файл. Для этого я использую команду tail -f, но она, похоже, не работает. Вот мой сценарий.Как использовать tail -f в сценарии оболочки?

#!/bin/bash 

ssh -q sc-2 tail -f /home/logs/oam-2.log > /root/logs/file.log & 

echo "press return to strop the trace" 

read A 

kill `ps -ef| grep tail| grep sc-2| grep "\.log"| awk '{print $2}'` 2>/dev/null & 

Когда я запускаю сценарий, только 5 строк печатаются в file.log

+0

Зачем это делать? Не будут ли данные уже в файле журнала? – doctorlove

+0

Это может быть связано с 'ssh'. Можете ли вы воспроизвести проблему непосредственно на 'sc-2'? – bitmask

+0

sc-2 - имя хоста. это так странно, потому что, когда я использую tail -f в командной строке, он отлично работает, но затем, когда я использую его в своем скрипте, он отображает только 5 строк. –

ответ

1

Хотя вы отправляете ssh процесс в фоновом режиме с помощью &, его дескрипторы файлов все еще «прикреплены» к вашему Терминал. Демонстрация:

# Terminal 1 
$ ssh $host sleep 600 & 
[3] 14340 

# Terminal 2 
$ ls -l /proc/14340/fd 
lrwx------ 1 iscfrc iscfrc 64 Oct 3 10:30 0 -> /dev/pts/1 
lrwx------ 1 iscfrc iscfrc 64 Oct 3 10:30 1 -> /dev/pts/1 
lrwx------ 1 iscfrc iscfrc 64 Oct 3 10:30 2 -> /dev/pts/1 
lr-x------ 1 iscfrc iscfrc 64 Oct 3 10:30 3 -> socket:[125941180] 
lrwx------ 1 iscfrc iscfrc 64 Oct 3 10:31 4 -> /dev/pts/1 
lrwx------ 1 iscfrc iscfrc 64 Oct 3 10:31 5 -> /dev/pts/1 
lrwx------ 1 iscfrc iscfrc 64 Oct 3 10:31 6 -> /dev/pts/1 

Обратите внимание, как все ФД (минус сокет TCP) прикреплены к /dev/pts/1.

Итак, что происходит, когда ваш скрипт работает ssh, помещает его в фоновом режиме, но процесс ssh продолжает опрос терминала для ввода?

# Terminal 2 
$ sudo strace -p 14340 
Process 14340 attached - interrupt to quit 
select(7, [3 4], [], NULL, NULL 

# Terminal 1 
$ read 

# Terminal 2, output 
select(7, [3 4], [], NULL, NULL)  = 1 (in [4]) 
read(4, 0xbff1dbbc, 16384)    = ? ERESTARTSYS (To be restarted) 
--- SIGTTIN (Stopped (tty input)) @ 0 (0) --- 
--- SIGTTIN (Stopped (tty input)) @ 0 (0) --- 
# (infinite loop of the previous three lines) 

Он идет в панику при попытке read() ввода из дескриптора файла 4, который вы можете увидеть выше, терминал. (4 -> /dev/pts/1)

Решение состоит в том, чтобы отсоединить ssh от входа терминала; Я рекомендую использовать nohup:

nohup ssh -q sc-2 tail -f /home/logs/oam-2.log > /root/logs/file.log & 

Дополнительные предложения для рассмотрения:

  1. Добавьте -T аргумент в вашей команде ssh отключить выделение TTY на удаленном хосте. Поскольку вам не нужно взаимодействовать с командой tail, TTY не требуется.
  2. Сохраните PID команды ssh с переменной длиной в $!, чтобы сэкономить время на анализ данных ps.
  3. И чтобы быть еще более спартанским, вы можете сэкономить echo, используя read-p. (p для быстрой)

Объединяя все выше:

nohup ssh -qT sc-2 tail -f /home/logs/oam-2.log >/root/logs/file.log & 
sshpid=$! 
read -p $'press return to stop the trace\n' 
kill $sshpid 

Я тестировал выше (с моим собственным хост/файлов путей, заполненных) и баллотировался> 10 минут без остановка.

+0

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

+0

единственный вопрос, который у меня есть, даже с хвостом nohup, все еще не работает в фоновом режиме. –

+0

Вы использовали как термины script, так и функцию - вы говорите, что вам нужно написать два сценария, один для запуска процесса 'ssh' и другой, чтобы убить его позже? Если это так, вам нужно использовать 'nohup', чтобы запустить этот скрипт, а не использовать его внутри самого скрипта. Если это не так, я не уверен, почему это не будет происходить на заднем плане - пока '&' находится в конце строки 'nohup', она должна. – iscfrc

Смежные вопросы