【问题标题】:Logrotate script not runningLogrotate 脚本未运行
【发布时间】:2019-09-13 06:20:49
【问题描述】:

我有以下 logrotate 脚本

/path/to/folder {
   daily
   rotate 30
   notifempty
   sharedscripts
   copytruncate
   compress
   dateext


   preremove
     if file --mime-type "$1" | grep -q gzip$; then
          mkdir -p /path/to/archive/folder && cp $1 $_
     fi
   endscript
}

  • 我想要达到的目标:-

    在保留 30 天后删除日志文件之前,将其复制到另一个文件夹。

我在调试模式下运行这个 logstash 配置

logrotate -d $CONFIG_FILE

从日志看,轮换工作正常,但它甚至没有运行preremove 脚本。 我还没有在现场运行这个配置,因为我想在这样做之前对其进行测试。

logrotate 3.8.6 版

【问题讨论】:

  • 请注意preremove 运行/bin/sh,您可能没有可用的$_(至少POSIX sh 似乎不需要它)。另外,请确保在任何地方引用"$1",并单引号'gzip$'。尝试添加调试输出,如 echo blah >> /tmp/debug 以查看脚本是否运行。
  • @BenjaminW。我尝试用path/to/archived/folder 替换$_ - 仍然没有用。我还在 preremove 脚本中尝试了echo "testing"。它似乎没有运行。
  • 我不确定logrotate 的标准输出在哪里——您是否尝试将其重定向到echo 调试语句的文件?
  • @BenjaminW。它似乎没有进入preremove 脚本。在preremove 块之外放置回声会引发错误unknown option 'echo'。但是当它在 preremove 块内时,它不会抛出该错误。
  • 老实说,我不确定。我会尝试在一些测试文件而不是真实日志上以非调试模式运行它。

标签: linux bash unix logging logrotate


【解决方案1】:

我不确定您是在问为什么 preremove 没有运行,还是您的脚本看起来是否正常。

Preremove,以及如何测试

如果 logrotate 不删除文件,我不相信它会运行 preremove 脚本(根据 -d)。我设置了一个测试用例并在strace 下运行它。 logrotate -d 找到了需要删除的文件并写道它会删除它们,但没有运行 preremove 代码。老实说,这对我来说是有意义的,也是我所期望的,因为 preremove 可能会造成与删除本身一样具有破坏性的事情。

要执行测试,我认为您需要在另一个目录中重现您的实时环境并实际运行它。不要使用完整大小的文件,只需使用几行的虚拟文件。创建一个脚本来构建您的测试文件夹,这样您就可以轻松地重现测试。使用touch 设置时间戳。例如:

for n in $(seq 1 30); do
    cp test.log test.log.$n
    gzip test.log.$n
    touch -d "now - $n day" test.log.$n.gz
done

脚本本身

  • grep -q gzip$ 是错误的。 $ 将在 shell 解析中消失。您需要用单引号将其括起来。
  • 正如其他人所写,我不希望$_ 工作。重复目录名称,或在脚本中使用变量。
  • 我认为您不需要按照建议在 EOL 使用 \ 转义。
  • 您可能想要cp -p,正如有人建议的那样。
  • 如果您的文件很大,cp 会很慢。如果您的存档位于同一文件系统上,请考虑改用ln(而不是ln -s!)。这将是即时的。
  • 使用file --mime-type 可能工作正常,但坦率地说,在这种情况下我只是基于文件名,因为logrotate 会可靠地将.gz 附加到file 将返回gzip 的任何文件上。 expr "$1" : '.*gz$' 将为任何以.gz 结尾的$1 提供一个非零数字作为标准输出。它将准确地给出数字 0 作为不以 .gz 结尾的文件名的标准输出。

【讨论】:

    【解决方案2】:

    您可能缺少在some examples 中看到的行继续转义

    preremove
        # debug line
        systemd-cat -t "rot-pre-rm" echo "preremove block, file: $1"
        if file --mime-type "$1" | grep -q gzip$; then \
            cp -p "$1" /path/to/archive/syslog/; \
        fi; \
    endscript
    

    【讨论】:

    • -d 模式下运行它们似乎不起作用
    • 你也可以把代码变成一个shell脚本并调用它。
    • 似乎preremove 块甚至没有运行。我尝试在preremove 中调用sn-p,将其放入另一个带有echo 的shell 脚本。似乎没有运行。
    • 添加systemd-cat echo "preremove block" outside if-else,然后检查journalctl。如果您的主机上没有 systemd,请仅使用 echo。可能是if条件不满足。
    【解决方案3】:

    我认为您的条件本身不会true您可以在 preremove 之前放置 echo 以进行调试。尝试手动执行您的 if 条件并查看。

    # file --mime-type * | grep -i *.1
    audit.log.1: text/plain
    # file --mime-type * | grep -i *.1$
    # file --mime-type * | grep -q *.1$
    # file --mime-type * | grep -q *.1
    

    【讨论】:

      猜你喜欢
      • 2017-04-26
      • 2012-10-19
      • 2018-01-05
      • 1970-01-01
      • 2019-04-14
      • 2013-11-06
      • 2021-12-18
      • 2015-05-27
      • 1970-01-01
      相关资源
      最近更新 更多