Как остановить команду хвоста в 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
, используя bash.
Ожидание конкретного ввода:
Я часто использую это:
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 завершит работу. Очевидно, это багизм.