У меня есть (ранее работал) настройка логротата для OpenResty, который я взял из предыдущей установки Ubuntu 18.04. Тем не менее, сервис 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.log.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.
Когда я запускаю его (без systemd) в отладочном режиме от имени root, я получаю следующий вывод:
# 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
... вместо ошибки переименования ... Файловая система только для чтения
(как это делает 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
Сейчас у меня заканчиваются опции. Любая помощь в устранении неполадок очень ценится.
Думаю, я нашел его. Файл logrotate не является проблемой.
Вместо этого, это вызвано функциями защиты в файле модуля systemd. После того как я отключил параметры защиты ProtectSystem = full
, все заработало. Причина в том, что logrotate в моем случае должен работать с каталогом / usr
, который доступен только для чтения, если эта опция включена.
Из документации на ProtectSystem =
Принимает логический аргумент или специальные значения «полный» или «строгий». Если 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 они были впервые представлены.
Хорошая находка для той же проблемы, которую я видел. Редактирование nginx.conf для входа в другой каталог (например, общий / var / log / nginx) является альтернативой, которая также работает.