Linuxトラブルシュートと原因の特定

# 概要
システムを運用していると、様々なトラブルが発生する。
サーバのレスポンスが突如遅くなり、その原因を突き詰めるということはインフラエンジニアとして日用茶飯事。

また、トラブルシューティングの方法はエンジニアによって様々だったりする。
自分の場合は

1. dstatコマンドでリソース状況を大雑把に確認
1. topコマンドでCPU/メモリー毎にソート
1. psコマンドでプロセスの状態を確認
1. netstatで状態確認

という順番で調査するようにしている。

このように調査することにより、
遠くからどこが問題なのかざっくり見つつ、
問題を突き止めることが比較的容易になるからだ。

# dstatコマンドでリソース状況を大雑把に確認

とりあえず最低限必要な情報を表示する。

```
dstat  -tlmnd
```
<img width="802" alt="スクリーンショット 2017-12-29 20.09.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/75761/95f426ed-b7dd-f41e-8175-22395557b071.png">


| オプション | 意味 |
| :-- | :-- | 
| -t | 時間   | 
| -l | Load Average   | 
| -m | Memory   | 
| -n | Network   | 
| -d | Disk IO   | 

状況によっては割り込み回数など、もっと深く見ることも可能。
ただしdstatの場合は横に広がってしまうので（ターミナルの設定次第だけど）
自分は通常はこの程度の出力のみに止めている。

ちなみにLoad averageに限って言うと、負荷のかかる原因は大きく２つある。

* 処理がそもそも重い
* Disk IOがかかっている。

Load averageが高騰している場合は、この点を真っ先に疑う。

# topコマンドでCPU/メモリー毎にソート

topコマンドはデフォルトで利用されているCPU順に表示される
<img width="850" alt="スクリーンショット 2017-12-29 20.10.31.png" src="https://qiita-image-store.s3.amazonaws.com/0/75761/a902ac0b-bedd-5221-d337-d193e32b45ae.png">
CPU/メモリーを利用されている状況に応じて切り替える。
topコマンドの状態でshift+mでメモリー順にソートへ切り替わる。
<img width="663" alt="スクリーンショット 2017-12-29 20.10.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/75761/94920af4-1115-72a6-82d3-35aec41dcc54.png">
再度CPU順にソートする場合はshift+p


# psコマンドでプロセスの状態を確認する

topコマンドで見つけた怪しそうなプロセスを確認する
psコマンドはエンジニアの中でも、-efオプション派か、auxオプション派かに分かれる（気がする）。

```
ps -ef
ps aux
```

<img width="918" alt="スクリーンショット 2017-12-29 20.09.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/75761/903a94c3-1a15-7ada-890f-b5f243b08bca.png">


見比べてみると、
ps -efの場合は簡易的に
* プロセス番号
* 経過時間
* コマンド
程度はわかるものの、プロセスが消費しているリソースの中身まではわからない。
ps auxオプションの場合、プロセス毎のリソース消費状態がわかる。


``` -ef　オプション

[root@cent ~]# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root     25172 25063 20 20:34 pts/1    00:00:01 dd if=/dev/zero of=1G.dummy bs=1
root     25174 25159  0 20:34 pts/0    00:00:00 ps -ef
[root@cent ~]# 
````

``` auxオプション

[root@cent ~]# ps aux 
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root     25180 16.3  0.1 108984  1668 pts/1    R+   20:37   0:06 dd if=/dev/zero of=1G.dummy bs=1M count=10000
root     25189  0.0  0.0 112676   976 pts/0    R+   20:38   0:00 grep -E --color=auto  dd|RSS
[root@cent ~]# 
```

-efオプションにはなく、auxオプションで見れる有益な情報はこの点。

<img width="916" alt="スクリーンショット 2017-12-29 20.38.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/75761/93a8e17d-03c7-6a15-65f3-bcfb251985bf.png">

## VSZ
仮想メモリーの使用サイズ(キロバイト表示)

## RSS
物理メモリーの使用サイズ(キロバイト表示)

## 物理メモリーと仮想メモリーの違い
* 物理メモリー
物理的にサーバに搭載されたメモリー。
直接プロセスが使うことはない。

もしプロセスが直接、物理メモリーを使ってしまうと、アドレスの変更が頻繁に発生してしまう。
複数のプロセスが開始・終了を繰り返した結果、断片化されたメモリーを使わなければならなくなってしまう。

* 仮想メモリー
すべてのプロセスに独立したメモリーを割り当てる機能。

なお、物理メモリと仮想メモリーの紐付けをページテーブルという機能で行っている。
この機能により、プロセスは他の処理に影響されないようになっている。 

## STAT
プロセスのステータス
このステータスは主に以下のステータスがある。

|記号 |状態|説明|
|:-- | :-- | :--- |
|R|実行(可能)状態|CPU時間割り当てしている段階。もしくは実行中。 |
|D|待機状態|IO完了待ち。割り込み不能|
|S|待機状態|スリープ状態。割り込み可能|
|T|停止状態|STOPシグナル受信。終了処理中。|
|W|Swap out|実メモリーに存在しない|
|Z|ゾンビ状態|プロセスは完了したが、残っている状態|

実行を終了したプロセスはゾンビ状態になる。
その後、子プロセスは（というかLinuxカーネルは）、終了したプロセスの親プロセスに対してSIGCHLD(CHLD)シグナルを送信する。

親プロセスがwait()関数で子プロセスの終了を待っている場合、ここで初めてwaitから抜けてることができ、ゾンビ化した子プロセスは終了する。
親プロセスに何らかの問題があり子プロセスを終了できない場合、子プロセスはゾンビ状態のままとなる。

通常は、子プロセスが無くなってから、親プロセスが無くなる。
しかし、子プロセスより先に親プロセスが無くなってしまった場合は
Linuxが最初に起動されるプロセス /sbin/init が引き継ぐ。


# 親と子プロセスを視覚化
ps axwfオプションを使うことで、
何が親となっていて子プロセスが派生しているのか見ることも可能。

```
root@558aa0d3fa66:/# ps axwf
  PID TTY      STAT   TIME COMMAND
    1 pts/0    Ss     0:00 /usr/bin/python3 -u /sbin/my_init -- bash -l
   10 pts/0    S      0:00 /usr/sbin/syslog-ng --pidfile /var/run/syslog-ng.pid -F --no-caps
   16 pts/0    S      0:00 /usr/bin/runsvdir -P /etc/service
   18 ?        Ss     0:00  \_ runsv cron
   20 ?        S      0:00  |   \_ /usr/sbin/cron -f
   19 ?        Ss     0:00  \_ runsv sshd
   17 pts/0    S      0:00 bash -l
   32 pts/0    R+     0:00  \_ ps axwf
root@558aa0d3fa66:/# 

```

# netstatで確認
WEBサーバが動いていて、外部からの接続がボトルネックとして考えられる時、
プロセスに加え、netstatで各接続の状態を確認する事がある

```
netstat -an
```

オプションの意味は以下の通り。

| オプション| 意味|
|:--|:--|
| -a | 全てのアクティブなソケットを表示する |
| -n | ホストやユーザーの名前解決を行わず数字のまま出力する |

![netstat.png](https://qiita-image-store.s3.amazonaws.com/0/75761/e484db00-36d1-8579-b945-81717d528370.png)

赤枠がTCPの状態になる。

|状態| 意味|
|:--|:--|
|LISTEN|TCPモジュールはリモートホストからのコネクション要求待ち|
|ESTABLISHED|データ転送が行える通常の状態|
|CLOSING|リモートホストからのコネクション終了要求待ち|
|TIME-WAIT|コネクション終了要求応答確認待ち|
|CLOSED|終了|

ステータス状態の詳細はこちら
https://qiita.com/mogulla3/items/196124b9fb36578e5c80

# 犯人の特定
今回の場合は、ddコマンドでこの処理が負荷を上げていたということにたどり着く。
<img width="665" alt="スクリーンショット 2017-12-29 20.10.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/75761/830e6adf-7a50-5e58-4792-b43e886b1c08.png">


# ユーザー毎の使っているCPU使用率を表示
psコマンドを元にawsで成形することにより、各ユーザーのCPU使用率をまとめて計算することも可能。

```
ps aux | awk '{ if(NR>1){p[$1] += $3; n[$1]++} }END{for(i in p) print p[i], n[i], i}'
```
<img width="890" alt="スクリーンショット 2018-02-11 17.40.54.png" src="https://qiita-image-store.s3.amazonaws.com/0/75761/6753fa5d-d015-99e3-389a-0c5e9294732e.png">
3桁目はCPUだが、4桁目を指定するとメモリーになる。

```
ps aux | awk '{ if(NR>1){p[$1] += $4; n[$1]++} }END{for(i in p) print p[i], n[i], i}'
```

<img width="895" alt="スクリーンショット 2018-02-11 17.43.17.png" src="https://qiita-image-store.s3.amazonaws.com/0/75761/5ec1115b-6589-7234-1783-026d96bad108.png">