如何使用给定的模式tail -f最新的日志文件

11

我使用一些日志系统,每小时都会创建一个日志文件,例如下面的示例:

SoftwareLog.2010-08-01-08
SoftwareLog.2010-08-01-09
SoftwareLog.2010-08-01-10

我正在尝试使用tail命令跟踪最新的日志文件,给定一个模式(例如SoftwareLog*),我意识到有:

tail -F (tail --follow=name --retry)

但是那只能跟踪一个具体的名称 - 而这些名称随日期和时间而异。我尝试过类似于这样的东西:

tail --follow=name --retry SoftwareLog*(.om[1])  

但是通配符语句在传递给tail之前就已经被解析了,并且不会在每次tail重试时重新执行。

有什么建议吗?

6个回答

13

我相信最简单的解决方案如下:

tail -f `ls -tr | tail -n 1`

如果您的目录中包含其他日志文件,比如"SystemLog",而您只想要最新的"SoftwareLog"文件,那么您可以简单地添加一个grep命令,如下所示:

tail -f `ls -tr | grep SoftwareLog | tail -n 1`

7
可以使用头部而不是尾部,使事情变得更简单 =) ls -t | head -1 | xargs tail -F - Matthew Lowe
或者可以使用:tail -f SoftwareLog.`date +'%Y-%m-%d-%H'` - Archit Jain

7
< p >【编辑:快速搜索工具后】

你可能想试试multitail - http://www.vanheusden.com/multitail/

如果你想坚持使用Dennis Williamson的答案(我已经+1了他),这里为你填好了空白。

在你的shell中,运行以下脚本(或它的zsh等效脚本,我在看到zsh标签之前用bash编写了这个脚本):

#!/bin/bash

TARGET_DIR="some/logfiles/"
SYMLINK_FILE="SoftwareLog.latest"
SYMLINK_PATH="$TARGET_DIR/$SYMLINK_FILE"

function getLastModifiedFile {
    echo $(ls -t "$TARGET_DIR" | grep -v "$SYMLINK_FILE" | head -1)
}

function getCurrentlySymlinkedFile {
    if [[ -h $SYMLINK_PATH ]]
    then
        echo $(ls -l $SYMLINK_PATH | awk '{print $NF}')
    else
        echo ""
    fi
}

symlinkedFile=$(getCurrentlySymlinkedFile)
while true
do
    sleep 10
    lastModified=$(getLastModifiedFile)
    if [[ $symlinkedFile != $lastModified ]]
    then
        ln -nsf $lastModified $SYMLINK_PATH
        symlinkedFile=$lastModified
    fi
done

使用正常方法处理的背景(再次说明,我不知道zsh,所以可能会有所不同)...

./updateSymlink.sh 2>&1 > /dev/null

然后使用tail -F $SYMLINK_PATH,这样尾部就可以处理符号链接的更改或文件的旋转。

这有点复杂,但我不知道用tail还有其他方法来做到这一点。如果有人知道另一个可以处理这个问题的实用工具,请站出来,因为我也很想看看 - 像Jetty这样的应用程序默认是以这种方式记录日志的,我总是编写一个符号链接脚本在cron上运行来弥补它。

[编辑:从一行末尾删除了一个错误的“j”。您还有一个错误的变量名“lastModifiedFile”不存在,正确设置的名称是“lastModified”]


谢谢,我可能需要这样做。我研究了multitail,但不幸的是它只能交互式使用,这意味着我无法将其输出导向其他地方。我会尝试一下,看看能否解决问题。问题在于我希望它仅在tail运行时运行,并在tail退出时退出,但我不确定如何实现。 - Axiverse
谢谢!这基本上是我喜欢的唯一解决方案(我为此搜索了很多)。 - bruno.braga
修复了一个错误,它在第一次运行时无法工作,因为getCurrentlySymlinkedFile返回了一个空字符串,并且打字错误的lastModifiedDate也评估为空字符串。太好了。 - funroll

3

我没有测试过这个方法,但一个可行的方法是运行一个后台进程来创建和更新到最新日志文件的符号链接,然后你可以使用tail -f(或tail -F)命令跟踪该符号链接。


1
#!/bin/bash

PATTERN="$1"

# Try to make sure sub-shells exit when we do.
trap "kill -9 -- -$BASHPID" SIGINT SIGTERM EXIT

PID=0
OLD_FILES=""
while true; do
  FILES="$(echo $PATTERN)"
  if test "$FILES" != "$OLD_FILES"; then
    if test "$PID" != "0"; then
      kill $PID
      PID=0
    fi
    if test "$FILES" != "$PATTERN" || test -f "$PATTERN"; then
      tail --pid=$$ -n 0 -F $PATTERN &
      PID=$!
    fi
  fi
  OLD_FILES="$FILES"
  sleep 1
done

然后运行它: tail.sh 'SoftwareLog*'

如果日志在检查之间被写入,脚本将会丢失一些日志行。但至少它是一个单独的脚本,不需要符号链接。


0

我们有每日轮换的日志文件,例如:/var/log/grails/customer-2020-01-03.log。为了查看最新的日志,以下命令对我来说效果很好:

tail -f /var/log/grails/customer-`date +'%Y-%m-%d'`.log

(注意:表达式中+符号后面不要加空格)

因此,如果您在日志所在的同一目录中,以下内容应该可行:

tail -f SoftwareLog.`date +'%Y-%m-%d-%H'`

0

我相信最简单的方法是使用taillshead,尝试像这样:

tail -f `ls -t SoftwareLog* | head -1`

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接