如何在脚本中停止tail命令

时间:2015-02-19 06:59:04

标签: linux bash unix

我想做什么 - 使用自定义ssh客户端代码***开始捕获CHANGES到日志文件。经过一段时间(不是固定值并且基于事件),发出命令以停止拖尾。这是我用来捕获日志文件的最新更改的命令 - tail -f logfile.txt

我希望能够以:q之类的内容结束它,我可以从脚本中发出这些内容。我不想要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/questions/red-hat-31/how-to-stop-tail-f-in-scipt-529419/

我无法理解那里的解决方案(在第2篇中)。有人可以解释解决方案或建议采用不同的方法吗?

谢谢。

6 个答案:

答案 0 :(得分:20)

在您的脚本中,您可以使用$!变量。

# 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

$!扩展到最近执行的后台(异步)命令的进程ID。

答案 1 :(得分:4)

我使用

使用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 ) 的一些方法

等待特定的入侵:

我经常使用它:

#!/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

使用此命令,我可以等待下一个 dhcp客户端并获取事件,mac地址和提供的IP的时间。

在剧本中:

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

用于远程停止脚本:

十五路:

echo >/tmp/holder

......然后从elswhere:

#!/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

将终止tail命令。

锁定方式

kill -USR2 $(</tmp/lockfile)

然后,从elswhere:

ssh -T root@remoteMachine /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

通过SSH

第二种方法可以通过ssh正常工作:

ssh root@remoteMachine '/bin/bash -c "kill -USR2 $(</tmp/lockfile)"'

(关心内联脚本标记的双引号)

然后,从elswhere:

/tmp

(关注报价和双引号,按此顺序)

关于安全考虑的注意事项:这不关心安全问题!在{{1}}中使用这种 lockfile 可能是一个坏主意......

答案 2 :(得分:3)

您可以在后台执行tail,同时将其输出重定向到另一个文件(例如/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

答案 3 :(得分:1)

您所指的帖子#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或其他内容,否则,上述两个命令会导致在杀死它之前拖尾一小部分时间。

答案 4 :(得分:1)

根据您对@psmears的评论,您可以使用CTRL+C

  

@psmears--当然。那也行。我想要做的就是告诉unix拖尾文件,不管我想要什么时候停止它,并在开始和结束拖尾之间得到输出。谢谢。 - Borat Sagdiyev 2天前

因此,您只需在ssh参数中启动命令即可。

 ssh username@remotehost 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 username@remote-host 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存储在脚本中的文件中

 echo $SSHPID > ~/.sshpid

并从第二个

中检索它
 SSHPID=`cat ~/.sshpid`

答案 5 :(得分:0)

比杀人更好的是让尾巴正确退出:

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

当管道时,PID是顺序的,因此尾部的pid将是$ BASHPID,而sed的pid将是$ BASHPID + 1。当sed命令退出时, - pid开关将导致tail退出(正确!)。显然这是一种基础。