Как остановить команду хвоста в script

Что я хочу сделать - Начните записывать CHANGES в файл журнала с помощью пользовательского кода клиента ssh ***. Через некоторое время (которое не является фиксированным значением и основано на событиях), выпустите команду, чтобы остановить хвост. Это команда, которую я использую для записи последних изменений в файл журнала - tail -f logfile.txt

Я хочу иметь возможность закончить его чем-то вроде :q, который я могу выпустить из script. Мне не нужны команды клавиатуры, например ctrl + c.

*** Псевдокод для моего пользовательского кода клиента ssh (написанный на языке oop)

include ssh-api
ssh = getSSHConnection();
cmd = 'cd to folder';
ssh.command(cmd);
cmd = 'tail -f log.txt';
ssh.command(cmd);
wait for special event to occur...
cmd = 'stop the tail now!'
out = ssh.command(cmd);
print "the changes made to log file were\n"  + out;

У меня нет доступа для записи на сервер, на котором находится файл журнала.

Что я пробовал - http://www.linuxquestions.org/info/red-hat-31/how-to-stop-tail-f-in-scipt-529419/

Я не могу понять решение там (его в сообщении 2). Может кто-нибудь объяснить это решение или предложить другой способ сделать это?

Спасибо.

Ответ 1

Внутри script вы можете использовать переменную $!.

# run tail -f in background
tail -f /var/log/sample.log > out 2>&1 &

# process id of tail command
tailpid=$!

# wait for sometime
sleep 10

# now kill the tail process
kill $tailpid

$! Расширяется до идентификатора процесса последней выполненной фоновой (асинхронной) команды.

Ответ 2

Некоторые способы использования tail -f, используя .

Ожидание конкретного ввода:

Я часто использую это:

sed -une '
    /DHCPOFFER/{
        s/^\(.*\) [^ ]\+ dhcpd: DHCPOFFER on \([0-9.]\+\) to \([0-9a-f:]\+\) .*$/\1 \3 -> \2/p;
        q;
    }' < <(
      tail -f /var/log/syslog
    )

С помощью этой команды я могу подождать следующего клиента dhcp и получить время события, адрес и IP-адрес.

В script:

#!/bin/bash

read rMac rIp rDate < <(
  sed -une '
    /DHCPOFFER/{
      s/^\(.*\) [^ ]\+ dhcpd: DHCPOFFER on \([0-9.]\+\) to \([0-9a-f:]\+\) .*$/\3 \2 \1/p;
      q;
    }' < <(
      tail -n0 -f /var/log/syslog
))

printf "Date:\t%s\nMac:\t%s\nIP:\t%s\n" "$rDate" $rMac $rIp

Для удаленной остановки script:

Путь fifo:

mkfifo /tmp/holder
tail -f /var/log/syslog &
TailPid=$!
cat >/dev/null /tmp/holder
kill -9 $TailPid

... Тогда из elswhere:

echo >/tmp/holder

завершает команду хвоста.

Заблокированный путь

#!/bin/bash

[ -e /tmp/lockfile ] && exit
echo $$ >/tmp/lockfile
[ $(</tmp/lockfile) -ne $$ ] && exit
cd /var/log
tail -f syslog &
export tPid=$!
trap "kill $tPid;rm /tmp/lockfile;exit 0" 12
wait $tPid

Тогда из elswhere:

kill -USR2 $(</tmp/lockfile)

Через SSH

Второй метод отлично работает через ssh:

ssh -T [email protected] /bin/bash <<"eocmd"
    [ -e /tmp/lockfile ] && exit
    echo $$ >/tmp/lockfile
    [ $(</tmp/lockfile) -ne $$ ] && exit
    cd /var/log
    tail -f syslog &
    export tPid=$!
    trap "kill $tPid;rm /tmp/lockfile;exit 0" 12
    wait $tPid
eocmd

(обратите внимание на двойную кавычку вокруг встроенного тега script)

Тогда из elswhere:

ssh [email protected] '/bin/bash -c "kill -USR2 $(</tmp/lockfile)"'

(обратите внимание на цитату и двойную кавычку в этом порядке)

Замечание о соображениях безопасности. Это не заботится о проблемах безопасности! Наличие такого файла блокировки, расположенного в /tmp, может быть плохой идеей...

Ответ 3

Вы можете выполнить хвост в фоновом режиме, перенаправляя его вывод в другой файл (например, /tmp/mylog) и записывая pid процесса где-нибудь в файле pid (например, ~/mytail.pid):

tail -f logfile > /tmp/mylog & echo $! > ~/mytail.pid

Затем, когда вы хотите остановить его, просто выполните:

kill `cat ~/mytail.pid`

Затем вы можете увидеть содержимое журнала, который вы собрали за это время (также рекомендуется удалить его позже):

cat /tmp/mylog
rm /tmp/mylog # just don't forget it there

Ответ 4

Сообщение # 2, о котором вы говорите, делает следующее: имеет правильный ответ.

В нем говорится:

tail -f /etc/httpd/logs/access_log & # This starts tailing the file in background (see & at the end)
kill `ps | grep tail | awk '{print $1;}'` # This finds the process running above tail command and kills it

Возможно, вы захотите ввести sleep 100 или что-то в зависимости от вашей потребности, в противном случае две вышеприведенные команды приведут к сокращению только на долю времени, прежде чем убить его.

Ответ 5

Согласно вашему комментарию к @psmears, вы можете использовать CTRL+C

@psmears - конечно. это тоже сработает. Все, что я хочу сделать, это сказать unix, чтобы зачеркнуть файл, остановить его хвост, когда захочу, и получить результат между запуском и завершением хвоста. Благодарю. - Борат Сагдиев 2 дня назад

Итак, вы можете просто запустить свою команду в параметре ssh.

 ssh [email protected] tail -f /var/log/remotelog.txt | tee result.log

И когда вы закончите, нажмите CTRL+C

В предыдущей команде я использовал команду tee, чтобы увидеть в моем терминале новые строки и сохранить их в файле.

Если вы хотите, чтобы это было возможно для сценариев

Вы можете сделать следующее:

 ## store result to file
 FILE=result.log

 ## launch tail remote log, and store result to result.log
 ssh -n [email protected] tail -f /path/to/remote.log > $FILE &

 ## store pid
 SSHPID=$!

 ## wait for ":q" command
 while [ "$cmd" != ":q" ]; do
    echo -ne "\n$ "
    read -n 2 cmd
 done

 ## kill ssh when you've enough
 kill $SSHPID

 ## read result
 echo "the changes made to log file were\n"
 cat $FILE

Обратите внимание, что если вы хотите разделить сценарии запуска и остановки, вам просто нужно сохранить SSHPID в файле в script

 echo $SSHPID > ~/.sshpid

и извлеките его из второго

 SSHPID=`cat ~/.sshpid`

Ответ 6

Лучше, чем убить, правильно разрешить хвост:

tail -n0 --pid=$(($BASHPID+1)) -F logfile | sed '/special event string in the log/q'

При конвейеризации PID являются последовательными, поэтому pid хвоста будет $BASHPID, а pid sed будет $BASHPID + 1. Переключатель -pid приведет к выходу хвоста (правильно!), Когда команда sed завершит работу. Очевидно, это багизм.