Linuxサーバ上のファイルのダウンロードが非常に遅くなったときの対応

## はじめに

うちの研究室では稀に、物理サーバ上のファイルのダウンロードが異常に遅くなる、またはできなくなる事象が発生します。具体的な症状は以下の通りです。

- サーバ上のユーザーディレクトリに置いてあるファイルをHTTPS GETしようとすると非常に時間がかかる
- 軽いファイルはダウンロード可能だが、重いファイルは実質的にダウンロード不可能
- なぜかSFTPでGETするのは速い
- サーバ上のWebサイト等へのアクセスは問題なく可能

ここでは、このような場合の原因と対応について記します。

## 原因と対策

私の研究室でのケースでは、ディスク容量またはinodeがいっぱいになっていました。
以下の手順で確認してみてください。

---
### ディスク容量の確認
ディスク容量は、読んで字の如くディスク上の容量のことです。

1. サーバにSSH接続して以下のコマンドを実行します：
   ```shell
   $ df -h
   ```
2. 出力例：
   ```shell
   Filesystem            Size  Used Avail Use% Mounted on
    /path/to/volume1
                           50G   48G     0 100% /
    /path/to/volume2
                          939M     0  939M   0% /dev/shm
    /path/to/volume3
                          477M  105M  348M  24% /boot
    /path/to/volume4
                          955G  540G  367G  60% /home
   ```
3. `Use%`が100%近くの場合、容量がいっぱいです。大きなファイルを削除または退避してください。今回のケースでは、`root`ディレクトリにマウントしているHDDが容量オーバーになっていることがわかります。

**注意点**：
- たとえば、`root`がいっぱいなのに`home`ディレクトリのファイルを削除しても効果はありません（別ディスク上のデータのため）。
- 対応するディスクのファイルを削除するよう注意してください。

---

### inodeの確認
inodeはファイルのインデックスで、平たく言えばファイル数です。このinodeが上限に達している場合、ファイルの個数が上限に達しているので、容量自体には余裕があることもありえます。

1. 以下のコマンドで確認します：
   ```shell
   $ df -i
   ```
2. 出力例：
   ```shell
   Filesystem       Inodes  IUsed  IFree IUse% Mounted on
    /path/to/volume1
                   3276800 3276800        0  100% /
    /path/to/volume2         
                    240230       1   240229    1% /dev/shm
    /path/to/volume3
                    128016      53   127963    1% /boot
    /path/to/volume4
                  63545344 3281833 60263511    6% /home
   ```
3. `IUse%`が100%近くの場合、ファイル数が上限に達しています。この場合、小さいファイルを削除してください。今回のケースでは、`root`ディレクトリにマウントしているHDDがinode上限オーバーになっていることがわかります。

**注意点**：
- 今回の問題はファイル数が多すぎることなので、大きな容量のファイルを消しても意味がありません。細々したファイルが大量に存在する箇所があると思うので、そこを削除等してください。
- たとえば、`root`がいっぱいなのに`home`ディレクトリのファイルを削除しても効果はありません（別ディスク上のデータのため）。
- 対応するディスクのファイルを削除するよう注意してください。

---

## 詳細な原因特定
コマンドを使って、容量やファイル数が以上に大きなフォルダを探していきます。
ファイル数や使用データ量が多い場合はコマンド実行にかなり時間がかかるので注意。

### 容量不足の場合
大きなディレクトリを探すには次のコマンドを実行します：
```shell
$ du -sk [対象ディレクトリ]/* | sort -rn | head -[表示させたい行数]
```
たとえばrootで実行すると、下記のようになります。これを繰り返して、原因のフォルダ/ファイルを探して、当該ファイルを削除/退避してください。
```shell
$ du -sk /* | sort -rn
du: cannot access `/proc/8872/task/8872/fd/4': そのようなファイルやディレクトリはありません
du: cannot access `/proc/8872/task/8872/fdinfo/4': そのようなファイルやディレクトリはありません
du: cannot access `/proc/8872/fd/4': そのようなファイルやディレクトリはありません
du: cannot access `/proc/8872/fdinfo/4': そのようなファイルやディレクトリはありません
588639908	/home
9213672	/var
4660600	/root
2828224	/usr
459124	/lib
104378	/boot
34064	/etc
27280	/lib64
17572	/sbin
10160	/tmp
8612	/bin
5348	/opt
1656	/result
164	/dev
16	/lost+found
4	/srv
4	/selinux
4	/run
4	/mnt
4	/media
4	/cgroup
0	/sys
0	/proc
```

### inode枯渇の場合
次のコマンドでinodeを大量に使用しているディレクトリを調査します：
   ```shell
   $ for i in [対象ディレクトリ]/*; do echo $i; find $i |wc -l; done
   ```
たとえばrootディレクトリの場合：
```shell
$ for i in /*; do echo $i; find $i |wc -l; done
```
実行すると、次のように出力されます：
```shell
$ for i in /var/spool/*; do echo $i; find $i |wc -l; done
/var/spool/anacron
4
/var/spool/at
3
/var/spool/clientmqueue
2828798
/var/spool/cron
5
/var/spool/cups
2
/var/spool/lpd
1
/var/spool/mail
223
/var/spool/mailman
48
/var/spool/mqueue
231720
/var/spool/plymouth
2
/var/spool/postfix
41
/var/spool/samba
1
```
たとえば上記結果においては、/var/spool/clientmqueueおよび/var/spool/mqueueが全体の9割以上のinodeを利用していたことが確認されました。
これは先人が遺したまま忘れ去られたスクリプトが毎分エラーログファイルを吐き出していたことによるもので、原因となっているスクリプトを特定して停止し、対処しました。

## ファイル削除・退避

### 削除時の注意点
- 削除していいファイルなのかについてはくれぐれも注意してください。
- 削除は普通にrmコマンドで削除してください。ただし、ファイルが大量だとエラーが出るので、
   ```shell
   $ echo /delete/file/path | xargs rm -f
   ```
    のようにパイプで繋いで実行してください。

### ファイルの退避
- 重要なファイルは削除せず、以下で適切なディレクトリに移動します：
   ```shell
   $ mv /path/to/file /destination/path
   ```

## おわりに
私の管理するサーバでは、上記のようなエラーによってファイルのダウンロードが以上に遅くなる現象が発生していました。今回は主に対処療法的な方法を紹介していますが、自動で生成されているファイル群が悪さをしている場合、そのファイルを生成している大元を叩かなければ根治はできません。
とりあえず現状に対処したら、原因の部分から対処を試みることをおすすめします。

## 参考リンク
https://qiita.com/masarufuruya/items/0c794083fc4ea03cd9f9
https://kazmax.zpp.jp/linux_beginner/inode.html
http://tagutagu.com/blog/view/28
https://rainbow-engine.com/linux-inode-lack/
https://bacchi.me/linux/rm-tips/