Linuxサーバーを運用していると、放置したログファイルがディスクを圧迫して障害につながることがあります。「ネットで調べればすぐ分かる」と思って検索しても、断片的な情報ばかりで結局うまく動かない、そんな経験はないでしょうか。
この記事では、logrotate(ログローテーション)の仕組みから設定ファイルの書き方、手動テスト、トラブル対処まで体系的に解説します。
この記事を読めば、ログ管理の不安を解消し、安定したサーバー運用ができるようになります。
実行環境:RHEL 9.4 / Ubuntu 24.04 LTSで動作確認済み
この記事のポイント
・logrotate は /etc/logrotate.conf と /etc/logrotate.d/ を読み込み、cronまたはsystemdタイマーで1日1回自動実行される
・daily / weekly・rotate N・compress の設定を押さえれば実務の9割に対応できる
・logrotate -d(ドライラン)で設定ミスを本番反映前に検出し、-f で強制実行できる
・postrotate を忘れると、ローテーション後もアプリが古いファイルに書き続けるため必ず動作確認する
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
なぜlogrotateが必要なのか
Linuxサーバーは稼働している限り、ログファイルを生成し続けます。Webサーバーのアクセスログ、メールサーバーのログ、認証ログなど、放置すれば際限なく肥大化します。ログが肥大化すると、以下の問題が発生します。
・ディスク容量の逼迫:/var/log が100%になるとサービスが停止する
・ログ解析の困難:数GBのファイルをgrepするのは現実的ではない
・バックアップの肥大化:不要な古いログまで毎回バックアップされる
logrotateは、これらの問題を自動的に解決する仕組みです。現在のログファイルをリネームして退避し、新しい空のファイルに書き込みを継続させます。世代数を超えた古いファイルは自動で削除されます。
たとえば /var/log/messages を毎週ローテーションする設定(rotate 4)にした場合、ファイルは以下のような状態になります。
# ローテーション前 /var/log/messages ← 現在書き込み中 # ローテーション後(compress + dateext + rotate 4 の設定例) /var/log/messages ← 新しい空ファイル /var/log/messages-20260518.gz ← 今週のログ(圧縮) /var/log/messages-20260511.gz ← 1週間前のログ /var/log/messages-20260504.gz ← 2週間前のログ /var/log/messages-20260427.gz ← 3週間前(次回ローテーションで削除)
logrotateの仕組み(cronとの関係)
logrotateは常駐プロセス(デーモン)ではありません。cron(定期実行の仕組み)によって1日1回呼び出されて動作します。具体的な流れは以下のとおりです。
・cronが毎日 /etc/cron.daily/logrotate を実行する
・logrotateが /etc/logrotate.conf を読み込む
・/etc/logrotate.conf の中で /etc/logrotate.d/ 配下の個別設定を読み込む(include)
・各設定ファイルの条件に従ってローテーションを実行する
・実行結果を /var/lib/logrotate/logrotate.status に記録する
RHEL/CentOS 7以降では、cronではなくsystemdタイマー(logrotate.timer)で実行される場合もあります。以下のコマンドで確認できます。
# logrotateがインストールされているか確認する [root@web01 ~]# which logrotate /usr/sbin/logrotate # バージョンを確認する [root@web01 ~]# logrotate --version logrotate 3.21.0 # systemdタイマーの状態を確認する(RHEL 9 / Ubuntu 20.04以降) [root@web01 ~]# systemctl status logrotate.timer * logrotate.timer - Daily rotation of log files Loaded: loaded (/usr/lib/systemd/system/logrotate.timer; enabled; preset: enabled) Active: active (waiting) since Tue 2026-06-10 00:00:01 JST; 10h ago Trigger: Wed 2026-06-11 00:00:00 JST; 13h left Triggers: * logrotate.service # 次回のlogrotate実行時刻を確認する [root@web01 ~]# systemctl list-timers | grep logrotate Tue 2026-06-11 00:00:00 JST 13h left Tue 2026-06-10 00:00:01 JST 10h ago logrotate.timer logrotate.service # 従来のcronで動いているか確認する [root@web01 ~]# ls -la /etc/cron.daily/logrotate -rwx------. 1 root root 130 Apr 1 2026 /etc/cron.daily/logrotate # cronからの呼び出し設定を確認する(RHEL系) [root@web01 ~]# cat /etc/cron.daily/logrotate #!/bin/sh /usr/sbin/logrotate -s /var/lib/logrotate/logrotate.status /etc/logrotate.conf EXITVALUE=0 if [ != 0 ]; then /usr/bin/logger -t logrotate "ALERT exited abnormally with []" fi exit
loggerコマンドでシステムログに「ALERT exited abnormally with [1]」と記録されます。これがcron経由で管理者メールに届く「ALERTメール」の発生源です。なお、systemdタイマーで管理されている場合は
Persistent=true が設定されているため、サーバーが停止していた期間があっても次回起動時に自動でlogrotateが実行されます。cronとsystemdタイマー、どちらの方法でも設定ファイルの書き方は同じです。
基本的な設定方法
1. 設定ファイルの場所を確認する
logrotateの設定ファイルは2つの場所にあります。・/etc/logrotate.conf:全体のデフォルト設定ファイル
・/etc/logrotate.d/:サービスごとの個別設定ファイルを格納するディレクトリ
まずは /etc/logrotate.conf の中身を確認してみましょう。
[root@web01 ~]# cat /etc/logrotate.conf # ローテーション周期(weekly = 週1回) weekly # 保持する世代数(4世代分を残す) rotate 4 # ローテーション後に新しい空ファイルを作成する create # ローテーション後のファイル名に日付を付ける dateext # 個別設定ファイルを読み込む include /etc/logrotate.d
/etc/logrotate.d/ には、RPMパッケージがインストール時に自動的に設定ファイルを配置します。
[root@web01 ~]# ls /etc/logrotate.d/ btmp chrony dnf firewalld rsyslog syslog wtmp # rsyslogの設定例を確認する [root@web01 ~]# cat /etc/logrotate.d/rsyslog /var/log/messages /var/log/secure /var/log/maillog /var/log/spooler /var/log/cron { missingok sharedscripts postrotate /usr/bin/systemctl kill -s HUP rsyslog.service >/dev/null 2>&1 || true endscript }
2. 個別の設定ファイルを作成する
独自のアプリケーションログなど、自分で設定を追加したい場合は /etc/logrotate.d/ に新しいファイルを作成します。以下は、/var/log/myapp/ 配下のログを管理する設定例です。
# /etc/logrotate.d/myapp の設定例 /var/log/myapp/*.log { daily rotate 14 compress delaycompress missingok notifempty create 0640 myapp myapp }
【重要】設定ファイルのパーミッションは644にする
/etc/logrotate.d/ 配下に置くファイルは、グループや他ユーザーに書き込み権限があると logrotate が読み込みを拒否します。必ず644(root:root)に設定してください。
# 設定ファイルのパーミッションを確認する [root@web01 ~]# ls -la /etc/logrotate.d/myapp -rw-rw-r-- 1 myapp myapp 120 Apr 11 10:00 /etc/logrotate.d/myapp # グループ書き込み権限があると以下のエラーが出る error: Ignoring /etc/logrotate.d/myapp because it is writable by group or world. # 644 (root:root) に修正する [root@web01 ~]# chmod 644 /etc/logrotate.d/myapp [root@web01 ~]# chown root:root /etc/logrotate.d/myapp
・パスにはワイルドカードが使える:/var/log/myapp/*.log のように指定すれば、ディレクトリ内の全.logファイルが対象になる
・createのパーミッションとオーナーはアプリに合わせる:アプリケーションがログを書き込むユーザー・グループに設定しないと、ローテーション後にログが書けなくなる
・postrotateが必要かどうかを確認する:アプリケーションがログファイルを開き直す仕組みを持っているかで判断する。copytruncateを使う方法もある(後述)
3. 主要なディレクティブを理解する
設定ファイルで使う主要なディレクティブ(設定項目)をまとめます。| ディレクティブ | 説明 |
|---|---|
daily / weekly / monthly | ローテーションの間隔。アクセスログは daily、変化の少ないログは weekly が適切 |
rotate 数値 | 保持する世代数。rotate 7 なら7世代分を保持し、それより古いものは削除 |
size サイズ | 指定サイズを超えた場合のみローテーション(例: size 100M)。daily/weeklyより優先 |
maxsize サイズ | daily/weeklyと併用し、指定サイズ超えなら間隔を待たずにローテーション |
minsize サイズ | daily/weeklyと併用し、指定サイズ未満ならローテーションしない |
compress | ローテーション後のログをgzip圧縮する |
delaycompress | 圧縮を1世代遅らせる。実務ではcompressとセットで使うのが定番 |
compresscmd コマンド | 圧縮コマンドを変更する(デフォルトはgzip。bzip2やxzも指定可能) |
compressext 拡張子 | 圧縮後のファイル拡張子を指定(例: .bz2 や .xz) |
create モード オーナー グループ | ローテーション後に指定した権限で新しい空ファイルを作成する |
missingok | ログファイルが存在しなくてもエラーにしない |
notifempty | ログファイルが空ならローテーションしない |
maxage 日数 | 指定日数より古いログファイルを削除する |
dateext | ローテーション後ファイルのサフィックスを連番ではなく日付にする |
sharedscripts | ワイルドカードで複数ファイルがマッチしてもpostrotateを1回だけ実行する |
su ユーザー グループ | ローテーションをroot以外のユーザー権限で実行する |
ローテーション間隔
アクセスログのように増加が速いログは daily、変化の少ないログは weekly や monthly が適切です。
圧縮
compress と delaycompress はセットで使うのが定番です。delaycompress があると直前のログは圧縮されず素のテキストで残るため、直近のトラブル調査がしやすくなります。「今日のアクセスログをgrepしたい」という場面でも、
access.log.1 をそのままgrepできます。エラー制御
missingok と notifempty は、ほぼすべての設定に入れておくことを推奨します。アプリが一時停止してログが出ないタイミングでエラーが起きることを防げます。
4. dateextでファイル名に日付を付ける
dateextを指定すると、ローテーション後のファイル名に日付が付きます。連番(.1、.2、.3...)より直感的にわかりやすくなります。/var/log/myapp/app.log { daily rotate 30 compress dateext dateformat -%Y%m%d missingok notifempty }
# dateext有効時のファイル名の例 [root@web01 ~]# ls -la /var/log/myapp/ -rw-r----- 1 root root 245760 Apr 11 09:15 app.log -rw-r----- 1 root root 18432 Apr 10 23:59 app.log-20260410.gz -rw-r----- 1 root root 17920 Apr 9 23:59 app.log-20260409.gz -rw-r----- 1 root root 19456 Apr 8 23:59 app.log-20260408.gz
5. 手動でローテーションをテストする
設定ファイルを作成したら、いきなり本番で動かすのではなく、必ずテストしましょう。デバッグモード(-d オプション):実際にはローテーションせず、何が実行されるかを表示します。
# ドライラン(実際にはローテーションしない) [root@web01 ~]# logrotate -d /etc/logrotate.d/myapp WARNING: logrotate in debug mode does nothing except printing debug messages! Consider using verbose mode (-v) instead if this is not what you want. reading config file /etc/logrotate.d/myapp Handling 1 logs rotating pattern: /var/log/myapp/*.log after 1 days (30 rotations) empty log files are not rotated, old logs are removed considering log /var/log/myapp/app.log log needs rotating rotating log /var/log/myapp/app.log, log->rotateCount is 30 dateext suffix '-20260621' dest: /var/log/myapp/app.log-20260621 compressing log with: /bin/gzip
強制実行(-f オプション):条件に関係なく即座にローテーションを実行します。
# 特定の設定ファイルを強制実行する [root@web01 ~]# logrotate -f /etc/logrotate.d/myapp # 実行後にローテーションされたか確認する [root@web01 ~]# ls -la /var/log/myapp/ -rw-r----- 1 myapp myapp 0 Apr 11 15:30 app.log -rw-r----- 1 myapp myapp 245760 Apr 11 15:30 app.log-20260411
詳細出力(-v オプション):-f と組み合わせると、実行中の詳細な情報が表示されます。
# 詳細情報を表示しながら強制ローテーション(-v + -f の組み合わせが便利) [root@web01 ~]# logrotate -vf /etc/logrotate.d/myapp rotating log /var/log/myapp/app.log, log->rotateCount is 30 dateext suffix '-20260621' glob pattern '-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]' renaming /var/log/myapp/app.log to /var/log/myapp/app.log-20260621 creating new /var/log/myapp/app.log mode = 0640 uid = 1001 gid = 1001 running postrotate script
強制ローテーション後、実際にファイルが正しく作成されているか
ls -lh で目視確認してください。
# ローテーション後のファイル構成を確認する [root@web01 ~]# ls -lh /var/log/myapp/ -rw-r----- 1 myapp myapp 0 Jun 21 15:30 app.log -rw-r----- 1 myapp myapp 240K Jun 21 15:30 app.log-20260621.gz -rw-r----- 1 myapp myapp 210K Jun 20 23:59 app.log-20260620.gz -rw-r----- 1 myapp myapp 198K Jun 19 23:59 app.log-20260619.gz
6. ステータスファイルでローテーション履歴を確認する
logrotateは最後にローテーションした日時をステータスファイルに記録しています。「本当にローテーションが実行されているのか」を確認するときに使います。# ステータスファイルを確認する [root@web01 ~]# cat /var/lib/logrotate/logrotate.status logrotate state -- version 2 "/var/log/messages" 2026-4-11-3:0:0 "/var/log/secure" 2026-4-11-3:0:0 "/var/log/maillog" 2026-4-11-3:0:0 "/var/log/cron" 2026-4-11-3:0:0 "/var/log/myapp/app.log" 2026-4-11-15:30:0
journalctl -u crond でcronの実行ログを確認してください。なお、「前回実行済みになっているため今すぐローテーションできない」という場面では、ステータスファイルから該当行を削除することでリセットできます。
# 特定ログのローテーション記録をリセットしたい場合 # ステータスファイルの該当行を削除してから通常実行する [root@web01 ~]# grep -v 'myapp' /var/lib/logrotate/logrotate.status > /tmp/logrotate.status.new [root@web01 ~]# mv /tmp/logrotate.status.new /var/lib/logrotate/logrotate.status # または -f で強制ローテーションする(ステータスを無視して実行) [root@web01 ~]# logrotate -f /etc/logrotate.d/myapp
応用・実務Tips
postrotateでサービスを再読み込みする
ログファイルをローテーションした後、サービスに「新しいログファイルに書き込んでくれ」と通知する必要がある場合があります。たとえばApache(httpd)は、起動時にログファイルを開いたまま書き込み続けます。ファイル名が変わっても古いファイルディスクリプタ(ファイルの参照情報)を使い続けるため、postrotateでサービスを再読み込みする必要があります。
注意:postrotateを書き忘れると、ローテーション後もアプリが古いファイルにログを書き続けます。ディスクを解放したつもりでも古いファイルが使われ続けるため、実務では必ず動作確認してください。
# /etc/logrotate.d/httpd の設定例 /var/log/httpd/*log { daily rotate 14 compress delaycompress missingok notifempty sharedscripts postrotate /bin/systemctl reload httpd.service > /dev/null 2>/dev/null || true endscript }
sharedscriptsは重要なディレクティブです。ワイルドカードで複数のログファイルがマッチした場合、sharedscriptsがないとファイルごとにpostrotateが実行されてしまいます。sharedscriptsを指定すると、全ファイルのローテーション完了後に1回だけ実行されます。
Nginxの場合、
systemctl reload を使う方法と、PIDファイルからプロセスIDを取得してUSR1シグナルを直接送る方法があります。USR1シグナルは既存コネクションを切らずにログファイルを切り替えるため、高トラフィック環境では後者が推奨されます。
# Nginx設定例(systemctl reloadを使う方法) /var/log/nginx/*.log { daily rotate 14 compress delaycompress missingok notifempty create 0640 nginx adm sharedscripts postrotate /usr/bin/systemctl reload nginx >/dev/null 2>&1 || true endscript } # USR1シグナルを直接送る方法(PIDファイルを使う) # PIDファイルが存在するかチェックしてからシグナルを送ることで # Nginxが停止中でもエラーにならない /var/log/nginx/*.log { daily rotate 14 compress delaycompress missingok notifempty create 0640 nginx adm sharedscripts postrotate if [ -f /run/nginx.pid ]; then kill -USR1 $(cat /run/nginx.pid) fi endscript }
copytruncateを使う場面
postrotateでサービスを再読み込みできない場合や、アプリケーション側にログファイルを開き直す仕組みがない場合は、copytruncateが有効です。# copytruncateを使う設定例 /var/log/myapp/app.log { daily rotate 7 compress delaycompress missingok notifempty copytruncate }
1. 元のログファイルをコピーしてバックアップを作成する
2. 元のログファイルの中身を空にする(truncate)
ファイル名やiノード(ファイルの識別番号)が変わらないため、アプリケーション側の対応は不要です。
ただし、コピーとtruncateの間に書き込まれたログが失われる可能性がゼロではありません。ミッションクリティカルなログには使わず、postrotateでの再読み込みを優先してください。
圧縮形式を変更する(bzip2 / xz)
デフォルトの圧縮形式はgzipですが、大量のテキストログが出るシステムでは、より圧縮率の高いbzip2やxzに変更することでディスク消費を抑えられます。compresscmd と compressext を組み合わせて圧縮形式を切り替えます。
# bzip2圧縮に変更する設定例 /var/log/bigapp/*.log { daily rotate 7 compresscmd /usr/bin/bzip2 compressext .bz2 compress notifempty missingok create 0644 root root } # xz圧縮に変更する設定例(さらに圧縮率が高い) /var/log/bigapp/*.log { daily rotate 7 compresscmd /usr/bin/xz compressext .xz compress notifempty missingok create 0644 root root }
bzcat・xzcat で解凍せずに直接閲覧できます。
サイズベースでローテーションする
周期ではなくファイルサイズでローテーションしたい場合は、size ディレクティブを使います。/var/log/myapp/app.log { size 100M rotate 10 compress dateext missingok notifempty copytruncate }
maxageで古いログを日数指定で削除する
rotate は世代数で管理しますが、maxage は日数で管理します。「30日以上前のログは削除する」といった運用に使います。/var/log/myapp/app.log { daily rotate 90 maxage 30 compress dateext missingok notifempty }
ログの保存先を変えてディスクを分離する
ローテーション後のログファイルを別のディレクトリに保存したい場合は、olddir ディレクティブを使います。/var/log/myapp/app.log { daily rotate 30 compress dateext olddir /var/log/myapp/archive createolddir 0750 myapp myapp missingok notifempty }
・createolddir:移動先ディレクトリが存在しない場合に自動作成する(パーミッションとオーナーを指定)
dfコマンドで/var/logのディスク使用率が高い場合、olddirで別パーティションに退避させる運用が有効です。
独自アプリケーションのログをローテーションする
自作のアプリケーションやバッチ処理のログをlogrotateで管理する場合の設定例を紹介します。# /etc/logrotate.d/myapp-batch /var/log/myapp/batch_*.log { weekly rotate 12 compress delaycompress missingok notifempty create 0644 appuser appuser olddir /var/log/myapp/archive dateext dateformat -%Y%m%d }
ワイルドカードで複数ファイルをまとめて管理する
複数のアプリケーションやモジュールがそれぞれログを生成する場合、ワイルドカードとsharedscriptsを組み合わせて一括管理できます。# 複数のログファイルをまとめて設定する例 /var/log/myapp/module_*.log { weekly rotate 8 compress delaycompress missingok notifempty su myapp myapp create 0640 myapp myapp sharedscripts postrotate systemctl reload myapp > /dev/null 2>&1 || true endscript }
複数のログファイルパスを一つの設定にまとめる
ワイルドカードでは対象にしにくい複数のログファイルを、同じポリシーで管理したい場合があります。そのようなときは、スペース区切りで複数のパスを1つのブロックに書けます。# スペース区切りで複数のパスを1つのブロックにまとめる例 /var/log/myapp/error.log /var/log/myapp/access.log { daily rotate 14 compress missingok notifempty }
firstaction / lastactionでローテーション前後に一度だけ処理する
postrotate はファイルごとに実行されますが(sharedscripts を付けた場合は1回)、lastaction はすべてのファイルのローテーション完了後に必ず1回だけ実行されます。ローテーション結果のログ記録や外部通知処理に使います。/var/log/myapp/*.log { daily rotate 7 compress missingok notifempty sharedscripts lastaction echo "$(date): logrotate completed" >> /var/log/logrotate-history.log endscript }
・lastaction ~ endscript:すべてのファイルのローテーション完了後に1回だけ実行する
prerotate / postrotate と組み合わせることもできます。実行順序は「firstaction → prerotate →(ローテーション)→ postrotate → lastaction」の順です。複数モジュールのログを一括ローテーションした後にまとめて通知したい場合などに重宝します。
トラブルシュート・エラー対処
「error: skipping」が出た時の対処法
logrotateを実行した際に以下のようなエラーが出ることがあります。error: skipping "/var/log/myapp/app.log" because parent directory has insecure permissions
対処法1:ディレクトリの権限を修正する
# 親ディレクトリの権限を確認 [root@web01 ~]# ls -ld /var/log/myapp/ # 権限を修正(他ユーザーの書き込みを禁止) [root@web01 ~]# chmod 755 /var/log/myapp/
アプリケーション専用のディレクトリで、あえてroot以外の権限にしている場合は、設定ファイルにsuディレクティブを追加します。
# suディレクティブで実行ユーザーとグループを指定 /var/log/myapp/*.log { su myapp myapp daily rotate 7 compress missingok notifempty }
「error: Ignoring ... because it is writable by group」が表示された場合
/etc/logrotate.d/ 配下に置いた設定ファイル自体のパーミッションが原因のエラーです。グループや他ユーザーへの書き込み権限があると、logrotateはセキュリティ上の理由でその設定ファイルを無視します。# エラーメッセージの例 error: Ignoring /etc/logrotate.d/myapp because it is writable by group or world. # 設定ファイルの権限を確認する [root@web01 ~]# ls -la /etc/logrotate.d/myapp -rw-rw-r-- 1 myapp myapp 120 Apr 11 10:00 /etc/logrotate.d/myapp # 644 (root:root) に修正する [root@web01 ~]# chmod 644 /etc/logrotate.d/myapp [root@web01 ~]# chown root:root /etc/logrotate.d/myapp # 確認する [root@web01 ~]# ls -la /etc/logrotate.d/myapp -rw-r--r-- 1 root root 120 Apr 11 10:05 /etc/logrotate.d/myapp
「error: skipping - log entry is not a file」が表示された場合
指定したパスがファイルではない(ディレクトリやシンボリックリンクの場合など)ときに発生します。[root@web01 ~]# logrotate -d /etc/logrotate.d/myapp error: skipping "/var/log/myapp/app.log" because it is not a regular file. # ファイルの種類を確認する [root@web01 ~]# file /var/log/myapp/app.log /var/log/myapp/app.log: symbolic link to /dev/null # 正しいログファイルのパスを確認して設定を修正する
Permission deniedエラーが出た場合
root権限でlogrotateを実行しているにもかかわらず Permission denied が出るケースがあります。error: error opening /var/log/myapp/app.log: Permission denied
SELinuxが有効な環境ではコンテキストの不一致が原因になることもあります。
# SELinuxの拒否ログを確認する [root@web01 ~]# ausearch -m avc -ts recent | grep logrotate # SELinuxの状態を確認する [root@web01 ~]# getenforce Enforcing
ローテーション後にアプリケーションがログを書き込めなくなった場合
createディレクティブのパーミッションやオーナーが正しいか確認してください。# ローテーション後のファイルのパーミッションを確認する [root@web01 ~]# ls -la /var/log/myapp/ -rw-r----- 1 root root 0 Apr 11 03:00 app.log -rw-r----- 1 myapp myapp 245760 Apr 11 03:00 app.log-20260411 # create行のオーナーが間違っている場合 # create 0640 root root ← rootで作成されているためmyappユーザーが書き込めない # create 0640 myapp myapp ← 正しい設定
ローテーション後もアプリが古いファイルにログを書き続けている場合(postrotateのシグナル送信が失敗している等)は、lsofで確認できます。
# ローテーション済みファイルを開いているプロセスを確認する [root@web01 ~]# lsof | grep deleted nginx 1234 nginx 4w REG 253,1 102400 12345 /var/log/nginx/access.log-20260410 (deleted) # または特定のファイルを指定して確認する [root@web01 ~]# lsof /var/log/nginx/access.log-20260410 # 対処:postrotateでUSR1シグナルを送りnginxにログを再オープンさせる postrotate /bin/kill -USR1 $(cat /run/nginx.pid 2>/dev/null) 2>/dev/null || true endscript
ログがローテーションされない時の確認手順
「設定したのにログがローテーションされない」場合は、以下の手順で原因を切り分けてください。手順1:ステータスファイルを確認する
logrotateは前回の実行日時を /var/lib/logrotate/logrotate.status(ディストリビューションによっては /var/lib/logrotate.status)に記録しています。
# ステータスファイルで前回の実行日時を確認 [root@web01 ~]# cat /var/lib/logrotate/logrotate.status | grep myapp
手順2:デバッグモードで設定を検証する
# 設定ファイルの構文エラーを確認 [root@web01 ~]# logrotate -d /etc/logrotate.d/myapp
手順3:cronまたはsystemdタイマーが動いているか確認する
# 1. cronデーモンが動いているか確認する [root@web01 ~]# systemctl status crond Active: active (running) # 2. cronのログでlogrotateが実際に呼ばれているか確認する(RHEL系) [root@web01 ~]# grep logrotate /var/log/cron Jun 21 03:00:01 web01 CROND[12345]: (root) CMD (run-parts /etc/cron.daily) # Ubuntu系の場合はjournalctlで確認する [root@web01 ~]# journalctl -u cron | grep logrotate # 3. /etc/cron.daily/logrotate が存在するか確認する [root@web01 ~]# ls -la /etc/cron.daily/logrotate -rwx------. 1 root root 130 Apr 1 2026 /etc/cron.daily/logrotate # 4. 実行権限があるか確認する(xがないと実行されない) [root@web01 ~]# chmod +x /etc/cron.daily/logrotate # systemdタイマーの場合 [root@web01 ~]# systemctl status logrotate.timer [root@web01 ~]# systemctl list-timers | grep logrotate
logrotate.timerが inactive になっていたり、/etc/cron.daily/logrotate が存在しない場合は、logrotate自体が定期実行されていません。
手順4:ディスク容量を確認する
ディスクが100%の状態では、ローテーション(新しいファイルの作成や圧縮)が失敗します。
# ディスク使用量を確認 [root@web01 ~]# df -h /var/log/
手順5:手動で実行してエラーが出ないか確認する
# 手動で実行してエラーが出ないか確認する [root@web01 ~]# /usr/sbin/logrotate -s /var/lib/logrotate/logrotate.status /etc/logrotate.conf
compress / delaycompressの世代数がわかりにくい場合
rotate の数値は「圧縮ファイルを含むバックアップ世代数の上限」です。delaycompress を使っている場合、最新1世代は非圧縮のまま残り、それ以降が圧縮されます。「世代数を設定したのにファイルが想定より多い」と感じるのは、現在書き込み中のログ(世代数の外)も含めて数えているためです。# rotate 7 + daily + compress + delaycompress 設定時のファイル例 /var/log/httpd/access_log ← 現在のログ(書き込み中・世代数の外) /var/log/httpd/access_log.1 ← 1世代前(非圧縮・delaycompress対象) /var/log/httpd/access_log.2.gz ← 2世代前(gzip圧縮済み) /var/log/httpd/access_log.3.gz ← 3世代前(gzip圧縮済み) /var/log/httpd/access_log.4.gz ← 4世代前(gzip圧縮済み) /var/log/httpd/access_log.5.gz ← 5世代前(gzip圧縮済み) /var/log/httpd/access_log.6.gz ← 6世代前(gzip圧縮済み) /var/log/httpd/access_log.7.gz ← 7世代前(次回ローテーションで削除)
「logrotate: ALERT exited abnormally with [1]」がメールに届く場合
cronからlogrotateを実行したときに終了コードが1になると、/etc/cron.daily/logrotate の logger コマンドが「ALERT exited abnormally with [1]」とシステムログに記録し、それがcronのメール通知として管理者に届きます。-v オプションで詳細を出力しながら手動実行すると、エラー箇所が特定できます。
# 詳細出力でエラー箇所を特定する [root@web01 ~]# logrotate -v /etc/logrotate.conf 2>&1 | grep -E "(error|warning|ALERT)" # 特定の設定ファイルを絞って確認する [root@web01 ~]# logrotate -v /etc/logrotate.d/myapp 2>&1 # よくある原因: # 1. missingok が抜けていてログファイルが存在しない # 2. postrotate スクリプトの終了コードが0でない(|| true が抜けている) # 3. create で指定したユーザー・グループが存在しない # 4. /etc/logrotate.d/ 配下の設定ファイルのパーミッションがグループ書き込み可能
|| true を忘れると、シグナル送信が失敗したとき(サービスが停止中など)に終了コード1が返り、毎日ALERTメールが届き続けます。|| true を付けておくと、シグナル送信に失敗してもローテーション自体は成功扱いになります。postrotate内で
systemctl 等のコマンドを絶対パスで指定していない場合、cronの環境(PATH が最小限)ではコマンドが見つからずにエラーになることもあります。which systemctl で絶対パスを確認し、/usr/bin/systemctl reload サービス名 のように書くと確実です。
本記事のまとめ
logrotateの設定方法とトラブル対処のポイントを整理します。| やりたいこと | コマンド・設定 |
|---|---|
| デフォルト設定を確認する | cat /etc/logrotate.conf |
| 個別設定ファイルの一覧を確認する | ls /etc/logrotate.d/ |
| 設定をテストする(実行しない) | logrotate -d /etc/logrotate.d/設定名 |
| 強制的にローテーションを実行する | logrotate -f /etc/logrotate.d/設定名 |
| 詳細表示で強制ローテーションする | logrotate -vf /etc/logrotate.d/設定名 |
| 前回の実行日時を確認する | cat /var/lib/logrotate/logrotate.status |
| ローテーション記録をリセットする | ステータスファイルの該当行を削除または -f で強制実行 |
| ファイル名に日付を付ける | dateext + dateformat -%Y%m%d |
| サイズベースでローテーションする | size 100M |
| 古いログを日数指定で削除する | maxage 30 |
| ローテーション後のファイルを別ディレクトリに移動する | olddir /var/log/myapp/archive |
| 複数パスを一つの設定ブロックにまとめる | スペース区切りでパスを並べる |
| ローテーション完了後に一度だけ処理する | lastaction ~ endscript で設定 |
| systemdタイマーの状態を確認する | systemctl status logrotate.timer |
| 次回実行時刻を確認する | systemctl list-timers | grep logrotate |
| cronのログでlogrotateの実行を確認する | grep logrotate /var/log/cron |
| ローテーション後にサービスを再読み込みする | postrotate ~ endscript で設定 |
| アプリ側の対応なしでローテーションする | copytruncate ディレクティブで設定 |
| 圧縮形式をbzip2/xzに変更する | compresscmd /usr/bin/bzip2 + compressext .bz2 |
| 複数ファイルをまとめて管理する | ワイルドカード + sharedscripts |
| パーミッションエラーを回避する | su ユーザー グループ ディレクティブで設定 |
| 設定ファイル自体のパーミッションを修正する | chmod 644 /etc/logrotate.d/設定名 |
| ALERTメールのエラー箇所を特定する | logrotate -v /etc/logrotate.conf 2>&1 | grep error |
logrotateは「設定して放置」で動くツールですが、設定ミスに気づかないまま放置すると、ディスク満杯による障害を引き起こします。
新しいアプリケーションを導入したら /etc/logrotate.d/ に設定を追加し、
logrotate -d で動作確認するところまでをセットにしてください。関連するログ管理の記事も参考にしてください。
・crontabコマンドの設定と書き方|動かない時のログ確認まで
・dfコマンドでディスクの空き容量を確認する方法
ログが溢れて深夜に叩き起こされた経験はありませんか?
logrotateの設定を覚えても、「本番サーバーの運用設計をどう組み立てるか」は断片的な情報だけでは身につきません。現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。
「独学の時間がもったいない」「プロから直接、現場の技術を最短で学びたい」という本気の方には、2日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
登録10秒/合わなければ解除3秒 / 詳細はこちら
- 次のページへ:touchコマンドでファイルを作成・タイムスタンプを変更する方法|空ファイルや日付変更も
- 前のページへ:exportコマンドで環境変数を設定する方法|PATHの永続化とトラブル対処
- この記事の属するカテゴリ:Linuxtipsへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は1分、解除もいつでも可。
登録無料・いつでも解除できます