AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / ubuntu / 问题 / 1275668
Accepted
Philipp Claßen
Philipp Claßen
Asked: 2020-09-17 12:38:57 +0800 CST2020-09-17 12:38:57 +0800 CST 2020-09-17 12:38:57 +0800 CST

logrotate 在以 root 身份手动运行时成功,但在由 logrotate.service 运行时失败并显示“只读文件系统”

  • 772

我从以前的 Ubuntu 18.04 安装中获取了 OpenResty 的(以前工作的)logrotate 设置。然而 logrotate.service 现在失败并出现此错误......

error: error renaming /usr/local/openresty/nginx/logs/access.log.60.zst
to /usr/local/openresty/nginx/logs/access.log.61.zst: Read-only file system

...我很难理解为什么。新机器运行的是 Ubuntu 20.04,但我不明白为什么在这种情况下会有所作为。

首先,这是配置:

$ cat /etc/logrotate.d/custom-openresty

/usr/local/openresty/nginx/logs/access.log
/usr/local/openresty/nginx/logs/error.log
{
  daily
  rotate 60
  maxsize 1G
  missingok
  notifempty
  compress
  compresscmd /usr/bin/zstd
  uncompresscmd /usr/bin/unzstd
  compressoptions -9 --long -T1
  compressext .zst
  delaycompress
  sharedscripts
  postrotate
    test ! -f /usr/local/openresty/nginx/logs/nginx.pid || kill -USR1 `cat /usr/local/openresty/nginx/logs/nginx.pid`
 endscript
}

/etc/logrotate.conf没有改变,看起来像这样:


# see "man logrotate" for details
# rotate log files weekly
weekly

# use the adm group by default, since this is the owning group
# of /var/log/syslog.
su root adm

# keep 4 weeks worth of backlogs
rotate 4

# create new (empty) log files after rotating old ones
create

# use date as a suffix of the rotated file
#dateext

# uncomment this if you want your log files compressed
#compress

# packages drop log rotation information into this directory
include /etc/logrotate.d

# system-specific logs may be also be configured here.

这是我的文件的状态(我希望access.log.1在 logrotate 运行后得到):

$ ls -alhg /usr/local/openresty/nginx/logs/
total 10G
drwxr-xr-x  2 root 4.0K Sep 16 20:04 .
drwxr-xr-x 18 root 4.0K Sep 16 19:42 ..
-rw-r--r--  1 root  10G Sep 16 19:56 access.log
-rw-r--r--  1 root 5.5K Sep 16 19:56 error.log

但是,logrotate.service 失败并出现以下错误:

~$ systemctl status logrotate.service 
● logrotate.service - Rotate log files
     Loaded: loaded (/lib/systemd/system/logrotate.service; static; vendor preset: enabled)
     Active: failed (Result: exit-code) since Wed 2020-09-16 20:11:32 UTC; 4min 32s ago
TriggeredBy: ● logrotate.timer
       Docs: man:logrotate(8)
             man:logrotate.conf(5)
    Process: 27403 ExecStart=/usr/sbin/logrotate /etc/logrotate.conf (code=exited, status=1/FAILURE)
   Main PID: 27403 (code=exited, status=1/FAILURE)

$ sudo journalctl --unit logrotate.service

Sep 16 20:11:32 fetcher-scheduler systemd[1]: Starting Rotate log files...
Sep 16 20:11:32 fetcher-scheduler logrotate[27403]: error: error renaming /usr/local/openresty/nginx/logs/access.log.60.zst to /usr/local/openresty/nginx/logs/access.log.61.zst: Read-only file system
Sep 16 20:11:32 fetcher-scheduler systemd[1]: logrotate.service: Main process exited, code=exited, status=1/FAILURE
Sep 16 20:11:32 fetcher-scheduler systemd[1]: logrotate.service: Failed with result 'exit-code'.
Sep 16 20:11:32 fetcher-scheduler systemd[1]: Failed to start Rotate log files.

当我以 root 身份在调试模式下运行它(没有 systemd)时,我得到以下输出:

# logrotate -v -d /etc/logrotate.d/custom-openresty

reading config file /etc/logrotate.d/custom-openresty
compress_prog is now /usr/bin/zstd
uncompress_prog is now /usr/bin/unzstd
compress_options is now  -9 --long -T1
compress_ext is now .zst
Reading state from file: /var/lib/logrotate/status
Allocating hash table for state file, size 64 entries
Creating new state
Creating new state
...
Creating new state

Handling 1 logs

rotating pattern: /usr/local/openresty/nginx/logs/access.log
/usr/local/openresty/nginx/logs/error.log
 after 1 days (60 rotations)
empty log files are not rotated, log files >= 1073741824 are rotated earlier, old logs are removed
considering log /usr/local/openresty/nginx/logs/access.log
  Now: 2020-09-16 20:24
  Last rotated at 2020-09-16 20:11
  log needs rotating
considering log /usr/local/openresty/nginx/logs/error.log
  Now: 2020-09-16 20:24
  Last rotated at 2020-09-16 19:00
  log does not need rotating (log has been rotated at 2020-9-16 19:0, that is not day ago yet)
rotating log /usr/local/openresty/nginx/logs/access.log, log->rotateCount is 60
dateext suffix '-20200916'
glob pattern '-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
previous log /usr/local/openresty/nginx/logs/access.log.1 does not exist
renaming /usr/local/openresty/nginx/logs/access.log.60.zst to /usr/local/openresty/nginx/logs/access.log.61.zst (rotatecount 60, logstart 1, i 60), 
renaming /usr/local/openresty/nginx/logs/access.log.59.zst to /usr/local/openresty/nginx/logs/access.log.60.zst (rotatecount 60, logstart 1, i 59), 
...
/logs/access.log.3.zst (rotatecount 60, logstart 1, i 2), 
renaming /usr/local/openresty/nginx/logs/access.log.1.zst to /usr/local/openresty/nginx/logs/access.log.2.zst (rotatecount 60, logstart 1, i 1), 
renaming /usr/local/openresty/nginx/logs/access.log.0.zst to /usr/local/openresty/nginx/logs/access.log.1.zst (rotatecount 60, logstart 1, i 0), 
log /usr/local/openresty/nginx/logs/access.log.61.zst doesn't exist -- won't try to dispose of it
renaming /usr/local/openresty/nginx/logs/access.log to /usr/local/openresty/nginx/logs/access.log.1
running postrotate script
running script with arg /usr/local/openresty/nginx/logs/access.log
/usr/local/openresty/nginx/logs/error.log
: "
    test ! -f /usr/local/openresty/nginx/logs/nginx.pid || kill -USR1 `cat /usr/local/openresty/nginx/logs/nginx.pid`
"

对我来说,一切看起来都很正常。如果我运行它,它也可以工作:

# logrotate -v /etc/logrotate.d/custom-openresty
reading config file /etc/logrotate.d/custom-openresty
compress_prog is now /usr/bin/zstd
uncompress_prog is now /usr/bin/unzstd
compress_options is now  -9 --long -T1
compress_ext is now .zst
Reading state from file: /var/lib/logrotate/status
Allocating hash table for state file, size 64 entries
Creating new state
...
Creating new state

Handling 1 logs

rotating pattern: /usr/local/openresty/nginx/logs/access.log
/usr/local/openresty/nginx/logs/error.log
 after 1 days (60 rotations)
empty log files are not rotated, log files >= 1073741824 are rotated earlier, old logs are removed
considering log /usr/local/openresty/nginx/logs/access.log
  Now: 2020-09-16 20:26
  Last rotated at 2020-09-16 20:11
  log needs rotating
considering log /usr/local/openresty/nginx/logs/error.log
  Now: 2020-09-16 20:26
  Last rotated at 2020-09-16 19:00
  log does not need rotating (log has been rotated at 2020-9-16 19:0, that is not day ago yet)
rotating log /usr/local/openresty/nginx/logs/access.log, log->rotateCount is 60
dateext suffix '-20200916'
glob pattern '-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
previous log /usr/local/openresty/nginx/logs/access.log.1 does not exist
renaming /usr/local/openresty/nginx/logs/access.log.60.zst to /usr/local/openresty/nginx/logs/access.log.61.zst (rotatecount 60, logstart 1, i 60), 
old log /usr/local/openresty/nginx/logs/access.log.60.zst does not exist
...
old log /usr/local/openresty/nginx/logs/access.log.2.zst does not exist
renaming /usr/local/openresty/nginx/logs/access.log.1.zst to /usr/local/openresty/nginx/logs/access.log.2.zst (rotatecount 60, logstart 1, i 1), 
old log /usr/local/openresty/nginx/logs/access.log.1.zst does not exist
renaming /usr/local/openresty/nginx/logs/access.log.0.zst to /usr/local/openresty/nginx/logs/access.log.1.zst (rotatecount 60, logstart 1, i 0), 
old log /usr/local/openresty/nginx/logs/access.log.0.zst does not exist
log /usr/local/openresty/nginx/logs/access.log.61.zst doesn't exist -- won't try to dispose of it
renaming /usr/local/openresty/nginx/logs/access.log to /usr/local/openresty/nginx/logs/access.log.1
running postrotate script

没有错误,最终access.log.1按预期创建:

# ls -algh /usr/local/openresty/nginx/logs/
total 10G
drwxr-xr-x  2 root 4.0K Sep 16 20:26 .
drwxr-xr-x 18 root 4.0K Sep 16 19:42 ..
-rw-r--r--  1 root  10G Sep 16 19:56 access.log.1
-rw-r--r--  1 root 5.5K Sep 16 19:56 error.log

请注意,它说...

log /usr/local/openresty/nginx/logs/access.log.61.zst
doesn't exist -- won't try to dispose of it

...而不是error renaming ... Read-only file system(就像logrotate.service那样)

为什么以root身份手动运行时它可以工作,但是当它被logrotate.service执行时却失败了?

我没有对logrotate.service. 为了完整起见,这里是单元文件:

$ systemctl cat logrotate.service
# /lib/systemd/system/logrotate.service
[Unit]
Description=Rotate log files
Documentation=man:logrotate(8) man:logrotate.conf(5)
ConditionACPower=true

[Service]
Type=oneshot
ExecStart=/usr/sbin/logrotate /etc/logrotate.conf

# performance options
Nice=19
IOSchedulingClass=best-effort
IOSchedulingPriority=7

# hardening options
#  details: https://www.freedesktop.org/software/systemd/man/systemd.exec.html
#  no ProtectHome for userdir logs
#  no PrivateNetwork for mail deliviery
#  no ProtectKernelTunables for working SELinux with systemd older than 235
#  no MemoryDenyWriteExecute for gzip on i686
PrivateDevices=true
PrivateTmp=true
ProtectControlGroups=true
ProtectKernelModules=true
ProtectSystem=full
RestrictRealtime=true

现在我的选择已经不多了。非常感谢您对解决问题的任何帮助。

systemd logrotate 20.04
  • 2 2 个回答
  • 4977 Views

2 个回答

  • Voted
  1. Best Answer
    Philipp Claßen
    2020-09-17T13:04:00+08:002020-09-17T13:04:00+08:00

    我想,我找到了。logrotate 文件不是问题。

    相反,它是由 systemd 单元文件中的强化特性引起的。在我禁用ProtectSystem=full强化选项后,它起作用了。原因是 logrotate 必须/usr在我的情况下对目录进行操作,如果启用该选项,则该目录是只读的。

    从文档上ProtectSystem=

    采用布尔参数或特殊值“full”或“strict”。如果为 true,则为本单元调用的进程以只读方式挂载 /usr 和引导加载程序目录(/boot 和 /efi)。如果设置为“full”,则 /etc 目录也以只读方式挂载。如果设置为“strict”,则整个文件系统层次结构以只读方式挂载,API 文件系统子树 /dev、/proc 和 /sys 除外(使用 PrivateDevices=、ProtectKernelTunables=、ProtectControlGroups= 保护这些目录)。此设置确保禁止对服务进行任何修改供应商提供的操作系统(以及可选的配置和本地安装)。建议对所有长时间运行的服务启用此设置,除非它们涉及系统更新或需要通过其他方式修改操作系统。如果使用此选项,则可以使用 ReadWritePaths= 将特定目录排除在只读状态之外。如果设置了 DynamicUser=,则隐含此设置。此设置不能确保在所有情况下都得到保护。一般来说,它与 ReadOnlyPaths= 具有相同的限制,见下文。默认为关闭。

    为了正确修复它,我现在将以下行添加到/lib/systemd/system/logrotate.service:

    ReadWritePaths=/usr/local/openresty/nginx/logs
    

    然后ProtectSystem=full将除了日志所在的目录之外的所有内容都挂载为只读。现在,只读错误消失了:

    # systemctl daemon-reload && systemctl start logrotate
    (completed successfully without output)
    

    我想,我从来没有在 Ubuntu 18.04 上遇到过这个问题,因为强化选项还不是默认值。Ubuntu 20.04 现在有它,但我不知道它们是在哪个 Ubuntu 版本中首次引入的。

    • 4
  2. user1137190
    2020-10-14T00:44:25+08:002020-10-14T00:44:25+08:00

    很高兴找到我看到的同样问题。编辑 nginx.conf 以登录到不同的目录(例如,常见的 /var/log/nginx)也是一种可行的替代方法。

    • 1

相关问题

  • 命令列出启动时启动的服务?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何运行 .sh 脚本?

    • 16 个回答
  • Marko Smith

    如何安装 .tar.gz(或 .tar.bz2)文件?

    • 14 个回答
  • Marko Smith

    如何列出所有已安装的软件包

    • 24 个回答
  • Marko Smith

    无法锁定管理目录 (/var/lib/dpkg/) 是另一个进程在使用它吗?

    • 25 个回答
  • Martin Hope
    Flimm 如何在没有 sudo 的情况下使用 docker? 2014-06-07 00:17:43 +0800 CST
  • Martin Hope
    Ivan 如何列出所有已安装的软件包 2010-12-17 18:08:49 +0800 CST
  • Martin Hope
    La Ode Adam Saputra 无法锁定管理目录 (/var/lib/dpkg/) 是另一个进程在使用它吗? 2010-11-30 18:12:48 +0800 CST
  • Martin Hope
    David Barry 如何从命令行确定目录(文件夹)的总大小? 2010-08-06 10:20:23 +0800 CST
  • Martin Hope
    jfoucher “以下软件包已被保留:”为什么以及如何解决? 2010-08-01 13:59:22 +0800 CST
  • Martin Hope
    David Ashford 如何删除 PPA? 2010-07-30 01:09:42 +0800 CST

热门标签

10.10 10.04 gnome networking server command-line package-management software-recommendation sound xorg

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve