ドケチへ送るサーバーのディスク＆メモリ節約のための7つ道具

# はじめに

- 「レンタルサーバーは無料枠・エコノミープランでしか使わん（ ＾ω＾）」
- 「今使っているサーバーの容量とかギリギリだけど、増設は面倒_(:3 」∠ )_」
- 「クラウドのディスク容量課金・転送量課金をケチりたい('A`).」

と常日頃考えている私が、同じような志を持つ初心者の為に、１０年前のLinux初心者だった私へ伝えたいと思う７つのコトをまとめてみました。


# 前提など

- 「初心者向け ＆ 忘記録」な内容
- クラウドのレンタルサーバー（低スペ、SSH可、sudo不要）を想定
- Linuxの一般的なディストリビューションで、追加インストール等なしでできること


もっといろんな工夫はあると思いますが、今回はとりあえずパッと思い付いた７つだけを紹介します。


# 1. 標準入力

基本中の基本ですが、データを逐次的に処理する場合であれば、全データをメモリ上に載せる必要はありません。

たとえば、以下のようなことは安易にやってはいけません。

```python

fi = open('x00.csv', encoding='utf-8').readlines()
for line in fi:
  print('\t'.join(line.strip().split(',')))
```

Pythonで上記のように書くと、データ`x00.csv`をメモリ上にすべて展開してしまいます。
数GBオーバーのデータを扱おうとした場合、明らかに問題です。

無論、データ全体をメモリ上に載せる必要がある場合もありますが、基本的にはfor文などで逐次的に処理していくことがほとんどです。

色々と回避する手段はありますが、標準入力（Pythonでは`sys.stdin`）を使うのが汎用性が高くおすすめです。

```shell
# シェル
cat x00.csv | python test.py
```

```python
# python
import sys

for line in sys.stdin:
  print(line.strip().split(','))
```

# 2. ファイル圧縮 `gzip -c`

さて、処理したデータをどのように保存するのが良いでしょうか？

通常は標準出力を使って以下のように保存することが多いでしょう。

```shell

cat x00.csv | python test.py > y00.tsv
```

しかし、ディスク容量を少しでもケチるのであれば、標準出力されたデータを圧縮しながら保存しましょう。


```shell

cat x00.csv | python test.py | gzip -c > y00.tsv.gz
```

ファイル圧縮のコマンドには、`gzip`、`bzip2`、`xz`などがあり、この３つのコマンドであれば`-c`オプションをつけることで、パイプラインでデータを受け取り、圧縮結果を標準出力として書き出すことができます。

よく使用されるのは`gzip`であり、ほとんどのシステムで圧縮・解凍ができるため、安定性があります。
`gzip`は上記の3つ中では最も圧縮率が低いですが、それでもかなりファイルサイズを圧縮できます（圧縮率がデフォルトで、おおよそ半分くらい）。

基本的には圧縮率が高いほど圧縮や展開に時間がかかるため、必要に応じてオプションやコマンドを変更しましょう。

なお参考に、オプションを与えず圧縮した場合、容量は以下のようになりました。

```
ls -lh
338M x00.csv
142M x00.csv.gz
97M x00.csv.bz2
92M xcsv.xz
```


# 3. 圧縮したファイルの読み込み `zcat`

上記でデータを圧縮しましたが、使用するために以下のように展開していては、まったくの無駄です。

```shell

gzip -d y00.csv.gz 
```

そこで、展開しながら中身を標準出力で吐き出す`zcat`などのコマンドを活用しましょう。
たとえば、以下のように処理をすることで、常に圧縮した状態でデータを扱うことができます。

```shell

zcat y00.csv.gz | python hoge.py | gzip -c > z00.txt.gz
```

なお、`.bz2`に対応するコマンドは`bzcat`、`.xz`に対応するコマンドは`xzact`になります。

# 4. ファイル分割 `split`

1つのファイルのサイズが大きくなると、様々な不都合が生じます。

たとえば、数10GBのファイルを処理しているときに、アクシデントやエラーによって途中で中断してしまった場合、また最初から処理をやり直さなければならない状況になりえます。
特に、処理時間が長くなりがちな低スペマシンでは致命的ともいえるでしょう。

**また進行状況も把握しにくく、精神衛生上もよくありません。**
**本当に精神衛生上よくありません。**

そこで、大きすぎるファイルは以下のように分割して扱います。

```shell

mkdir x_dir; cd x_dir
split -l 10000 ../x00.csv -d
```

上記コマンドでは、x00.csvを10000行ずつのファイルに分割して保存します（データサイズでの分割も可能です）。

なお、圧縮後のファイルでも問題なく分割できます。


# 5. ディレクトリを圧縮 `tar -zcvf`

さて上記のように分割すると、特定のディレクトリに複数のファイルが存在することになりますが、このディレクトリ全体を圧縮したい場合が出てきます。

そのような場合`tar`コマンドを使用します。パッケージをダウンロードすると、よく`.tar.gz`などの拡張子がついていますが、要するにあの形式に落とし込みます。

`tar`では`.gz`、`.bz2`、`xz`などで圧縮することができます。

```shell

tar -zcvf x_dir.tar.gz x_dir
tar -jcvf x_dir.tar.bz2 x_dir
tar -Jcvf x_dir.tar.xz x_dir
```

なお、以下の方法で解凍することができます。

```shell

tar -zxvf x_dir.tar.gz
tar -jxvf x_dir.tar.bz2
tar -Jxvf x_dir.tar.xz
```

# 6. 圧縮しながら転送する `rsync -az`

AWSなどの多くのクラウドのレンタルサーバーでは、データの転送量に課金が発生します。

そこで転送量を抑えるために、サーバー間のデータ転送に`scp`ではなく、より高機能な`rsync`を利用します。

```bash
rsync -az --progress x_dir.tar.gz aws:~/
```

-z オプションを指定してやることで、圧縮しながら転送してくれます。

また、帯域を制限したり、更新のあったファイルのみアップロードしたりするなど、便利な機能が多数存在します。

なお豆知識ですが、同サーバー内のコピーでもrsyncを使用できます。


# 7. 同じデータを作らない `ln -s`

安易に`cp`コマンドを使わないようにしましょう。

まったく同じデータを複数作ってもほぼ無駄ですし、**コピーしすぎると元が何のデータであったかわからなくなる**デメリットも生じます。

ファイルの場所を参照する`ln -s`を使用して、実態を減らしましょう。

```
ln -s original_path symble_path
```

なお、rsyncで`-a`オプション(正確には`-l`。`-a`には`-l`が含まれている)をつけていれば、シンボリックリンクをシンボリックリンクとしてコピーできます（scpだと、実ファイルがコピーされる）。

# おわりに

この記事では初心者の人にぜひ知っておいてほしい、ディスク＆メモリ節約の７つ道具について紹介しました。
今からでもすぐにできることばかりだと思いますので、早速実践してみてはいかがでしょうか？