proc_open(): fork failed - Cannot allocate memory の解決策

## はじめに
この記事はプログラミング初学者による備忘録用の記事であり、また、少しでも他の初学者のお役に立てればと思い書いています。

今回は、LaravelでS3を扱うためにleague/flysystem-aws-s3-v3パッケージのインストールを実行すると、``proc_open(): fork failed - Cannot allocate memory``エラー(OOMエラー)が発生したので解決策を備忘録としてまとめておきたいと思います。
ちなみに、LaravelアプリケーションはAWS EC2インスタンス配下でgit cloneした状態です。

間違いなどがございましたら、ご指摘のほどよろしくお願い致します。

## エラー内容 : ``proc_open(): fork failed - Cannot allocate memory``
LaravelでAmazon S3を利用するためにパッケージをインストールすると下記のようなエラーが発生しました。

```
$ composer require league/flysystem-aws-s3-v3:^1.0

Installation failed, reverting ./composer.json to its original content.
The following exception is caused by a lack of memory or swap, or not having swap configured
Check https://getcomposer.org/doc/articles/troubleshooting.md#proc-open-fork-failed-errors for details

PHP Warning:  proc_open(): fork failed - Cannot allocate memory in phar:///usr/bin/composer/vendor/symfony/console/Application.php on line 952

Warning: proc_open(): fork failed - Cannot allocate memory in phar:///usr/bin/composer/vendor/symfony/console/Application.php on line 952
```
実行結果の中に、エラーに関する情報が記載されているリンク先が表示されているので、下記のリンク先を参考にしてエラーの解決を試みます。

https://getcomposer.org/doc/articles/troubleshooting.md#proc-open-fork-failed-errors

## proc_open(): fork failed errorsの解決手順

上記のリンク先を見ると、今回のエラーは``VPSのメモリが不足し、スワップ領域が有効になっていないために発生する``らしいです。

このエラーを解決するために、いくつか設定すべきが箇所があるので下記で手順をまとめておきます。

### 1.エラーの原因となっているメモリの利用状況を確認する
``$free -m``コマンドを実行して、メモリの利用状況を確認します。
```
[ec2-user@ ~]$ free -m
              total        used        free      shared  buff/cache   available
Mem:            956         531         307           0         117         296
Swap:             0           0           0
```
実行結果の1行目では、メガバイト単位でメモリの利用状況が表示されています。
今回のエラーは、このメモリの利用可能な容量を超えるパッケージのインストールを試みたのが原因だと思います。

2行目の「Swap:」はスワップ領域の状況を表示しています。
この**スワップ領域が今回のエラー解決の鍵**となっています。
※「used」が大きい場合、スワップ領域に大きな負担がかかっていることになります。

### 2.Swap領域を作成する
下記コマンドの``/bin/dd if=/dev/zero of=ファイル bs=バイト数 count=個数``で、「バイト数×個数」分のサイズのSwap領域を作成します。
```
[ec2-user@ ~]$ sudo /bin/dd if=/dev/zero of=/var/swap.1 bs=1M count=1024
1024+0 レコード入力
1024+0 レコード出力
1073741824 バイト (1.1 GB) コピーされました、 6.61102 秒、 162 MB/秒
```
``コマンドとオプションの説明``

|コマンド|説明|
|:--|:--|
|dd|ファイルを指定された入出力ブロックサイズで (デフォルトでは標準入力から標準出力へ) コピーします。|

|ddのオプション|説明|
|:--|:--|
|if=ファイル|標準入力の代わりにファイルから読み出す。デバイスファイルも指定可能<br>「/dev/zero」は常にNULL文字（0x00）を出力し続けるという特殊なデバイスです|
|of=ファイル|標準出力の代わりにファイルへ書き込む。デバイスファイルも指定可能<br>今回はswap.1というファイル名です|
|bs=バイト数|1回に読み書きするブロックサイズ（バイト数）指定する<br>バイト数やブロックサイズには2種類の単位が使用可能。1024の累乗で指定する場合はK、M、G、T、P、E、Z、Y、1000の累乗で指定するときはKB、MB...を使用する|
|count=個数|bsで指定したサイズのブロックを入力から個数分だけコピーする|

### 3.作成したファイルをSwap領域にする
``mkswap``コマンドを実行して、作成したファイルをSwap領域にします。

```
[ec2-user@ ~]$ sudo /sbin/mkswap /var/swap.1
mkswap: /var/swap.1: パーミッション 0644 は安全な値ではありません。 0600 をお勧めします。
スワップ空間バージョン 1 を設定します。サイズ = 1024 MiB (1073737728 バイト)
ラベルはありません, UUID=8696fe3c-10cd-4202-8191-384fb71773af
```
Swap領域にするファイルのパーミッションを変更する際は、``$ sudo /bin/chmod 0600 /var/swap.1``を実行してください。

### 4.Swap領域を有効化する
``swapon``コマンドを実行して作成したSwap領域を有効化します。
```
[ec2-user@ ~]$ sudo /sbin/swapon /var/swap.1
swapon: /var/swap.1: パーミッション 0644 は安全な値ではありません。 0600 をお勧めします。
```

### 5.作成したSwap領域を確認する
最後に、``$ free -m``コマンドを実行してメモリの利用状況を確認してください。
Swap:に指定したサイズが反映されていれば成功です。
```
[ec2-user@ ~]$ free -m
              total        used        free      shared  buff/cache   available
Mem:            956         537          66           0         351         281
Swap:          1023           0        1023
```
以上で、Sawp領域の設定は完了です。
これで、``proc_open(): fork failed``エラーは解決できると思います。



## 補足:Swap領域を削除する
Swap領域を削除する場合、下記の手順に従って削除してください。

### 1.Swapファイルを無効にする
下記コマンドでSwapファイルを無効化してください。
```
$ sudo swapoff /swapファイル名
```

### 2.Swap領域の使用状況を表示するコマンドを実行して無効化したSwap領域が表示されないことを確認する
``$ swapon -s``コマンドを実行してSwap領域の使用状況を確認してください。
無効化したSwap領域が表示されなければ、``$ sudo swapoff /swapファイル名``コマンドの実行は成功です。
```
$ swapon -s
Filename                                Type            Size    Used    Priority
```

### 3.Swap領域用のSwapファイルを削除する
``rm``コマンドを実行して、無効化したSwapファイルを削除してください。
```
$ sudo rm Swapファイル名
```

## 参考文献
[Composer docs proc_open(): fork failed errors](https://getcomposer.org/doc/articles/troubleshooting.md#proc-open-fork-failed-errors)
[dd(1) — Linux manual page](https://man7.org/linux/man-pages/man1/dd.1.html#top_of_page)