如同这个问题在 Linux tcsh 中,我想跟踪日志文件,并且当我匹配正则表达式时,我想执行任意命令。我该怎么做?
答案1
在发帖人的注释中,这个问题中的一条评论引出了一篇关于使用管道时禁用自动缓冲. 解决方案是使用解除缓冲(从预计),例如:
$ unbuffer tail -f foo | find-and-run "findwhat" "runwhat"
wfaulk 的回答(加上 ayrnieu 的清理)为我们提供了脚本 find-and-run:
#!/usr/bin/perl
# run: find-and-run "regex-to-find" "commandtorun"
die "usage: $0 <regex> <exec-this> [exec-this-arg1 ...]\n"
unless @ARGV >= 2;
my ($re, @run) = @ARGV;
while (<>) {
last if /$re/;
}
exec { $run[0] } @run;
注 1:在 Debian lenny 上,您需要安装“expect-dev”包;unbuffer 安装为“expect_unbuffer”。
注2:这是完全未经测试的并且完全有点幼稚。为了安全起见,请不要使用它。如果你确实使用了它,你可能需要用单引号括住你的正则表达式以避免shell替换/扩展。
注3:非常感谢ayrnieu完成并清理脚本。
答案2
这似乎适合一个简短的 perl 脚本:
#!/usr/bin/perl
while (<>) {
last if /regex/;
}
system("ls");
如果您想要提供一个模式和一个带有标记参数的命令,请参阅 上的文档perldoc Getopt::Std
。
答案3
在我的例子中(在 RHEL 上,我想tail -n 0 -f file | grep -m 1 pattern
在增长文件中出现模式时立即终止),简单的使用解除缓冲由于某种原因,Expect 包中的实用程序未能解决问题。
但根据一篇博客文章(http://www.smop.co.uk/blog/index.php/2006/06/26/tail-f-and-awk/)我发现,重定向从子 shell 中启动的 tail 的输入可以达到这样的效果:
grep -m 1 pattern <(tail -n 0 -f file)
但事情没那么简单。在交互式 shell 中工作时,使用 SSH 远程运行相同的命令时,仍然像往常一样冻结:
ssh login@hostname 'grep -m 1 pattern <(tail -n 0 -f file)'
我发现在这种情况下,必须使用解除缓冲来自 Expect 的实用程序:
ssh login@hostname 'grep -m 1 pattern <(unbuffer -p tail -n 0 -f file)'
这一定不在交互式 shell 中使用 - 取消缓冲将导致ioctl(raw): I/O error
!
因此,给您的建议是,如果提出的解决方案不起作用,请尝试tail -f
在子 shell 中启动,如果您想在脚本或非交互式 shell 中执行此操作,则可能需要使用unbuffer
或。unbuffer -p
顺便说一句,请参阅本文以详细解释输出缓冲问题:http://www.pixelbeat.org/programming/stdio_buffering/
答案4
另一种方法是使用类似样本。Swatch 的设计目的正是实现您所说的这些功能,此外还能够实现其他十几种功能。