【Rails】rails s したらAddress already in useのエラーが出たので解消する

### 1.はじめに
railsでアプリを作成し、サーバーを立ち上げ`rails s`を行い、動作確認を試みました。
すると、`Address already in use`と表示されました。

私:「`http://localhost:3000`複数立ち上げてないはずだけど...」
複数回このエラーに遭遇したため、備忘録も兼ねてまとめていきます。

### 2.使用環境
・mac.os バージョン10.15.6
・Ruby 2.6.6
・Rails 6.0.3.5
・psql (PostgreSQL) 12.6

### 3.実際のエラー

```ターミナル.
1: from /Users/hogehoge/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/puma-4.3.7/lib/puma/binder.rb:229:in `new'
/Users/hogehoge/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/puma-4.3.7/lib/puma/binder.rb:229:in `initialize': Address already in
 use - bind(2) for "127.0.0.1" port 3000 (Errno::EADDRINUSE)
```
「Rails Address already in use」などで調べ、エラーの解消を試みました。

### 4.解決策
#### ① 別のポートを使う 
・URLを`http://localhost:3000` → 例：`http://localhost:3001`に変更する
・コマンドを`rails s`から`rails s -p 3001` に変更する

これでしばらくできていたのですが、数回行った後に同様のエラーが出ていた点、応急処置的な策だと感じた点から、別の方法を試しました。

#### ② 立ち上がっている別のrailsサーバーを落とす（今回は該当なしでした）
`ps -ax | grep ruby`とコマンドを入力します。

|  略称  |  内容  |
| ---- | ---- |
|  ps  |  process の略。プロセスとは、Linux上で動いているプログラムのもの。<br>自動的に起動しているものや、シェルからコマンドをうったもの含めてプロセスと呼ぶ。<br>OS内部で現在実行されているプロセス一覧を表示する |
|  ax  |  a:端末を持つ全てのプロセスを表示する<br>x:端末を持たない全てのプロセスを表示する  |
|  パイプ  |  コマンドの出力結果を次に渡す処理をする  |
|  grep  |  ファイル中の文字列を検索する |

※パイプは`|`のことです。

```ターミナル.
hogehoge@hogenoAir sample_app % ps -ax | grep ruby
13657 ??       242:21.97 ruby -I /Users/hogehoge/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib -I /Users/hogehoge
/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/spring-2.1.1/lib -e require 'spring/application/boot'
13666 ??         0:01.28 /Users/hogehoge/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rb-fsevent-0.10.4/bin/fsevent_watch --format
=otnetstring --latency 0.2 /Users/hogehoge/Desktop/sample_app
13667 ??         0:00.69 /Users/hogehoge/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rb-fsevent-0.10.4/bin/fsevent_watch --format
=otnetstring --latency 0.1 /Users/hogehoge/Desktop/sample_app/config/locales
13669 ??         0:00.70 /Users/hogehoge/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rb-fsevent-0.10.4/bin/fsevent_watch --format
=otnetstring --latency 0.1 /Users/hogehoge/Desktop/sample_app/db /Users/hogehoge/Desktop/sample_app/app/channels /Users/
hogehoge/Desktop/sample_app/app/controllers /Users/hogehoge/Desktop/sample_app/app/helpers /Users/hogehoge/Desktop/sample_app/app/jobs /Users/hogehoge/Desktop/sample_app/app/mailers /Users/hogehoge/Desktop/sample_app/app/models
68459 ttys004    0:00.00 grep ruby
```
プロセスを確認しrailsサーバーの場合はkillします。
（ない場合は、rails以外の別サービスが3000番ポートを使用していますのでそれを切ります。）

killをする場合は、`kill 〇〇`とコマンドを入力します。
※killは実行しているプロセスを終了するコマンドです。〇〇には、`PID(プロセス番号)`が入ります。

今回は強制終了のシグナル `-9`をつけて、killを行いました。

```ターミナル.
hogehoge@hogenoAir sample_app % kill -9 13657
hogehoge@hogenoAir sample_app % kill -9 13666
kill: kill 13666 failed: no such process
hogehoge@hogenoAir sample_app % kill -9 13667
kill: kill 13667 failed: no such process
hogehoge@hogenoAir sample_app % kill -9 13669
kill: kill 13669 failed: no such process
```
該当のrailsサーバーのプロセスがないですが、killコマンドでプロセスの停止を試みました。`failed: no such process`というエラーが表示されました。(プロセス番号の打ち間違えや、killコマンドを打ち込む前にプロセスが終了していると考えられます。)

#### ③ 3000番ポートを使用している他のプロセスを探してkillする
`lsof`コマンドを使用します。`lsof [オプション] [パス名]`という風に使います。
今回は、`lsof -i:3000`とコマンドを入力します。


|  略称  |  内容  |
| ---- | ---- |
|  lsof  | オープンしているファイルを一覧表示する|
|  -i  |  全てのネットワークソケットを対象にする<br>※「-i4」でIPv4,「-i6」でIPv6を指定できる <br>IPv4はIP(インターネットプロトコル:インターネットでデータ通信を<br>行う際の基本的なルールのこと)の第4版,IPv6は第6版。|


```ターミナル.
hogehoge@hogenoAir sample_app % lsof -i:3000
COMMAND   PID     USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
ruby    13924 hogehoge   23u  IPv6 0xc40f37229745897b      0t0  TCP localhost:hbci->localhost:54998 (CLOSE_WAIT)
ruby    13924 hogehoge   24u  IPv6 0xc40f372296a66d3b      0t0  TCP localhost:hbci->localhost:55019 (CLOSE_WAIT)
ruby    15604 hogehoge   12u  IPv6 0xc40f372296a6735b      0t0  TCP localhost:hbci (LISTEN)
ruby    15604 hogehoge   13u  IPv4 0xc40f37228ef3cb4b      0t0  TCP localhost:hbci (LISTEN)
ruby    15604 hogehoge   23u  IPv6 0xc40f372291635d3b      0t0  TCP localhost:hbci->localhost:55859 (CLOSE_WAIT)
ruby    15604 hogehoge   24u  IPv6 0xc40f372297454c3b      0t0  TCP localhost:hbci->localhost:55879 (CLOSE_WAIT)
ruby    15604 hogehoge   30u  IPv6 0xc40f372291632c3b      0t0  TCP localhost:hbci->localhost:55904 (CLOSE_WAIT)
ruby    15604 hogehoge   35u  IPv6 0xc40f37229163261b      0t0  TCP localhost:hbci->localhost:55905 (CLOSE_WAIT)
ruby    15604 hogehoge   37u  IPv6 0xc40f37229b46e97b      0t0  TCP localhost:hbci->localhost:55911 (CLOSE_WAIT)
ruby    15604 hogehoge   40u  IPv6 0xc40f37229b46b25b      0t0  TCP localhost:hbci->localhost:55912 (CLOSE_WAIT)
```

`13924`と`15604`がヒットしたので、それぞれkillします。

```ターミナル.
hogehoge@hogenoAir sample_app % kill 13924
hogehoge@hogenoAir sample_app % kill 15604
```

再度確認してみます。

```ターミナル.
hogehoge@hogenoAir sample_app % lsof -i:3000
COMMAND   PID     USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
ruby    13924 hogehoge   23u  IPv6 0xc40f37229745897b      0t0  TCP localhost:hbci->localhost:54998 (CLOSE_WAIT)
ruby    13924 hogehoge   24u  IPv6 0xc40f372296a66d3b      0t0  TCP localhost:hbci->localhost:55019 (CLOSE_WAIT)
ruby    15604 hogehoge   12u  IPv6 0xc40f372296a6735b      0t0  TCP localhost:hbci (LISTEN)
ruby    15604 hogehoge   13u  IPv4 0xc40f37228ef3cb4b      0t0  TCP localhost:hbci (LISTEN)
ruby    15604 hogehoge   23u  IPv6 0xc40f372291635d3b      0t0  TCP localhost:hbci->localhost:55859 (CLOSE_WAIT)
ruby    15604 hogehoge   24u  IPv6 0xc40f372297454c3b      0t0  TCP localhost:hbci->localhost:55879 (CLOSE_WAIT)
ruby    15604 hogehoge   30u  IPv6 0xc40f372291632c3b      0t0  TCP localhost:hbci->localhost:55904 (CLOSE_WAIT)
ruby    15604 hogehoge   35u  IPv6 0xc40f37229163261b      0t0  TCP localhost:hbci->localhost:55905 (CLOSE_WAIT)
ruby    15604 hogehoge   37u  IPv6 0xc40f37229b46e97b      0t0  TCP localhost:hbci->localhost:55911 (CLOSE_WAIT)
ruby    15604 hogehoge   40u  IPv6 0xc40f37229b46b25b      0t0  TCP localhost:hbci->localhost:55912 (CLOSE_WAIT)

```
再度表示されたので、`kill -9`でkillします。

```ターミナル.
hogehoge@hogenoAir sample_app % kill -9 13924
hogehoge@hogenoAir sample_app % kill -9 15604
hogehoge@hogenoAir sample_app %
[1]  - killed     rails s
hogehoge@hogenoAir sample_app % lsof -i:3000
hogehoge@hogenoAir sample_app %
```
killができたようなので、再度`rails s`でサーバーを起動します。

```ターミナル.
hogehoge@hogenoAir sample_app % rails s
=> Booting Puma
=> Rails 6.0.3.5 application starting in development
=> Run `rails server --help` for more startup options
Puma starting in single mode...
* Version 4.3.7 (ruby 2.6.6-p146), codename: Mysterious Traveller
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://127.0.0.1:3000
* Listening on tcp://[::1]:3000
Use Ctrl-C to stop

```
ということで、無事エラーを解決することができました。

### 5.考えられるエラーの原因

サーバーを停止する前にターミナルを閉じてしまったことが原因のようです（PCの不調で急に電源が落ちる等の現象が起きていました）。
ターミナルを閉じてしまうとCtrl + cを押してもサーバーが停止しないため、`Address already in use`のエラーが出たと考えられます。

### 6.参考リンク
1:[【 ps 】コマンド――実行中のプロセスを一覧表示する](https://www.atmarkit.co.jp/ait/articles/1603/28/news022.html)
2:   [rails sが通らない](http://hyottokoaloha.hatenablog.com/entry/2015/09/17/144100)
3:[パイプでつないでgrep?: Railsチュートリアル備忘録 - 8章]
(https://qiita.com/naokit-dev/items/0eefa3ad2a76dd0f24a3)
4:[grepコマンドの詳細まとめました【Linuxコマンド集】]
(https://eng-entrance.com/linux-command-grep)
5:[プロセスを終了するkillコマンドの使い方まとめ！【Linuxコマンド集】]
(https://eng-entrance.com/linux-command-kill)
6:[【kill】Linuxでプロセスを終了させるコマンド]
(https://uxmilk.jp/50638)
7:[【 lsof 】コマンド――オープンしているファイルを一覧表示する](https://www.atmarkit.co.jp/ait/articles/1904/18/news033.html)
8:[知ったかぶりをしていたソケット通信の基礎を改めて学んでみる](https://qiita.com/megadreams14/items/32a3eed4661e55419e1c#comments)
9:[【初心者向け】Linuxのプロセスについて一通りわかる！]
(https://eng-entrance.com/linux-process)
10:[FreeBSDハンドブック 第3章UNIXの基礎知識 3.8. デーモン、シグナルとプロセス終了]
(https://docs.freebsd.org/ja_JP.eucJP/books/handbook/basics-daemons.html)
11:[IPv6やIPv4ってなに？PPPoEとIPoEの比較とおすすめについて]
(https://www.nuro.jp/article/ipv6ipoe/)
12:[【Rails】rails serverコマンド(rails s)の使い方まとめ]
(https://pikawaka.com/rails/rails-s)

### 7.最後に
記事の感想や意見、ご指摘等あれば伝えていただけるとありがたいです。
読んでいただき、ありがとうございました。