Ubuntu に nginx をインストールした際の logrotate のデフォルト設定が間違ってる！


## 前書き

私の環境では、 fluentd で `/var/log/nginx/access.log` や `/var/log/nginx/error.log` を tail し収集するようにしています。
しかし、 Ubuntu 14.04 に PPA を追加し nginx をインストールした際に tail 出来なくなってしまいました。  
※ Ubuntu 14.04 に PPA を追加せず nginx をインストールした際は tail 出来ていました。

ログファイルを確認したところ、 `/var/log/nginx/access.log` に出力されるべきログが `/var/log/nginx/access.log.1` に、そして `/var/log/nginx/error.log` に出力されるべきログが `/var/log/nginx/error.log.1` になってました。
調査を行ったところ、 PPA を追加し nginx をインストールした際の logrotate のデフォルト設定が間違っているようでした。

## 環境

```vim:/etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.5 LTS"
```

## nginx のバージョン

`ppa:nginx/stable` を追加し nginx をインストールしました。

```shell:nginx
$ nginx -v
nginx version: nginx/1.10.1
```

## logrotate のデフォルト設定がどう間違っているのか

### デフォルト設定

nginx インストールした際の logrotate デフォルト設定は以下の通りです。

```vim:/etc/logrotate.d/nginx
/var/log/nginx/*.log {
        daily
        missingok
        rotate 14
        compress
        delaycompress
        notifempty
        create 0640 www-data adm
        sharedscripts
        prerotate
                if [ -d /etc/logrotate.d/httpd-prerotate ]; then \
                        run-parts /etc/logrotate.d/httpd-prerotate; \
                fi \
        endscript
        postrotate
                invoke-rc.d nginx rotate >/dev/null 2>&1
        endscript
}
```

### デフォルト設定の解説

プロパティ | 役割
------------|--------------
`daily` | ログローテーションを日毎に行う。
`missingok` | ログファイルが見つからなくてもエラーにしない。
`rotate n` | n 世代までログをローテート。それ以上は削除。
`compress` | ローテートしてログを圧縮。
`delaycompress` | 1つ前のファイルはまだ圧縮しない。それ以外を圧縮。
`notifempty` | ログファイルが空ならローテーションしない。
`create` | ローテーション後、新たにログファイルを作成する。権限、ユーザ、グループを指定。
`sharedscripts` | スクリプト宣言文。以降に記述された処理をワイルドカードの指定に関わらず、１度だけ実行する。
`postrotate` | ログローテーション実施後に実行される部分。

### どこが間違っているのか

デフォルト設定の `postrotate` に設定されているコマンドが間違っています。

```
postrotate
        invoke-rc.d nginx rotate >/dev/null 2>&1
endscript
```

ログをローテートしても、 nginx のログ出力先のファイルは変更されません。
`access.log` をロテートし、`access.log.1` とリネームされたところでログの出力先は `access.log.1` のままです。
そのため、 `postrotate` で新規の `access.log` に出力先を変更するよう設定する必要があります。

しかし、上記で設定されているコマンドは実行時以下のようにエラーが発生してしまいます。

```
$ invoke-rc.d nginx rotate
initctl: invalid command: rotate
Try `initctl --help' for more information.
invoke-rc.d: initscript nginx, action "rotate" failed.
```

```
$ initctl --help
Usage: initctl [OPTION]... COMMAND [OPTION]... [ARG]...

Options:
      --session               use existing D-Bus session bus to connect to init daemon (for testing)
      --system                use D-Bus system bus to connect to init daemon
      --dest=NAME             destination well-known name on D-Bus bus
      --user                  run in user mode (as used for user sessions)
  -q, --quiet                 reduce output to errors only
  -v, --verbose               increase output to include informational messages
      --help                  display this help and exit
      --version               output version information and exit

For a list of commands, try `initctl help'.

Report bugs to <upstart-devel@lists.ubuntu.com>
```

解決策は、以下のコマンドを実行するように設定することです。

```
$ sudo /etc/init.d/nginx rotate
 * Re-opening nginx log files nginx
   ...done.
```

or

```
$ sudo service nginx rotate
 * Re-opening nginx log files nginx
   ...done.
```

### 正しい設定

それでは上記で説明したコマンドを実行するように設定しましょう。

```diff:/etc/logrotate.d/nginx
  /var/log/nginx/*.log {
          daily
          missingok
          rotate 14
          compress
          delaycompress
          notifempty
          create 0640 www-data adm
          sharedscripts
          prerotate
                  if [ -d /etc/logrotate.d/httpd-prerotate ]; then \
                          run-parts /etc/logrotate.d/httpd-prerotate; \
                  fi \
          endscript
          postrotate
-                 invoke-rc.d nginx rotate >/dev/null 2>&1
+                 /etc/init.d/nginx rotate >/dev/null 2>&1
          endscript
  }
```

設定後、 `logrotate` コマンドを使いデバッグします。
`-d` `--debug` オプションでデバッグモードに入ります。

```
$ sudo logrotate -d /etc/logrotate.d/nginx
reading config file /etc/logrotate.d/nginx

Handling 1 logs

rotating pattern: /var/log/nginx/*.log  after 1 days (14 rotations)
empty log files are not rotated, old logs are removed
considering log /var/log/nginx/access.log
  log needs rotating
considering log /var/log/nginx/error.log
  log does not need rotating
rotating log /var/log/nginx/access.log, log->rotateCount is 14
```

## 付録

せっかくなので PPA リポジトリを追加せず Ubuntu 14.04 に nginx をインストールした際の logrotate のデフォルト設定を見てみましょう。

### nginx のバージョン

```shell:nginx
$ nginx -v
nginx version: nginx/1.4.6 (Ubuntu)
```

### デフォルト設定

```
/var/log/nginx/*.log {
        weekly
        missingok
        rotate 52
        compress
        delaycompress
        notifempty
        create 0640 www-data adm
        sharedscripts
        prerotate
                if [ -d /etc/logrotate.d/httpd-prerotate ]; then \
                        run-parts /etc/logrotate.d/httpd-prerotate; \
                fi \
        endscript
        postrotate
                [ -s /run/nginx.pid ] && kill -USR1 `cat /run/nginx.pid`
        endscript
}
```

`postrotate` のコマンドを見た所、 nginx の pid を kill している。
だから動いたのか！と納得しました。

## 参考文献

* [Nginxのログをlogrotateでローテーション - Carpe Diem](http://christina04.hatenablog.com/entry/2015/07/21/094631 "Nginxのログをlogrotateでローテーション - Carpe Diem")