クラウド上のサーバーとのファイルのやり取り（ただしコンソールアクセスができる場合）

ちょっとしたファイルを配置したり取ったりって地味に面倒なんですよ。

## base64してコピペして送れば良い

今回も簡単なUNIXでのシェル芸の紹介です。

### 送り元でのコマンド

送りたいファイル群は少量だという前提です。
コンソールしか開けないクラウド上のマシンから`file.txt`を送りたいとき
```
$ sha1sum file.txt
04b55c80186da427a61432b7c6de5483742948fe  file.txt
$ cat file.txt | gzip -c | base64
H4sIAAAAAAAAA81QS4oVMBDcv1P0AYZ3Ct259QAx6fdsyG+S9DBLOwziqMP4QURERBARvyAIgqCH
6YvY8Tl3cJdOV1VX1Y3SMAHVzglCiaVBpwEu4TgCX3JHP3BwAxeoUveU94CRbNkxGAGQuKcSYGCq
RqbsKVDgPIAHRHfL5AHHQRohuX124CIds9vCzQGYKZk2JFqPExtdOoJjpg659NE4AJ5i8zTcoJKB
Y3TJl4PyAlGndemvJFUDAzoznsxTOQSwU2ML15ak44FAjc3JIStlaFgb3sYcsFlw+zgpkaudQ7Nj
SQF7R/AU41VDFohhx3tyA/IyBNU1G7ht4fqpxzqQV43WQfHeoTec50rBjcWwFLUVCphXi6spO+o5
VrdyQ9ntyJODgB3b2qYSlw23CiKro//rldN2s1E503mh8lXlo8pPlR8q70Hljc77Kp90PtD5ZKPz
UsVe91Re63yo8sogb1U+q3zQea7zjgnd1flI5YuKES91nqn8MtRjle8qT1WM+85QU+WZyoVOg4vK
b5XnoNNQ33TO/8yOykuVF38AClRzVeICAAA=
$
```

この`H4sIA...`から始まり、`...AAA=`で終わる数行をテキストとしてクリップボードにコピーします。


### 送り先でのコマンド

下のパイプを含むコマンドを入力します。catコマンドが標準入力待ちになりますので、コピーしたテキストを貼り付けし、`Ctrl+D`で標準入力を終了してあげます。
```
$ cat | base64 -d | gzip -dc > file_received.txt
（先程のテキストをココにペースト）
その後に「Ctrl+D」する。
$ sha1sum file_received.txt
04b55c80186da427a61432b7c6de5483742948fe  file_received.txt
$
```

コマンド例での`sha1sum`コマンドは、単に送り元と送り先でファイルが同じことを証明するだけのチェックサムコマンドなので必須ではありません。心配性な人はチェックサムを確認しましょうね。

## 課題

システムエンジニアとして仕事をしていますと、些細な作業の手際の良さがパフォーマンスの高さに影響します。なんせ、一過性の作業のやることが多いんで。何度もリピートする事象には楽をする手段が必要です。

その一つがファイルの転送です。
分断されたサーバー間でのファイル転送って不便なんです。

### 実例

「あー、あっちのサーバーにあるファイルを、ここにもコピーしたい」ってことがあります。だったら「コピーすりゃ良い」ですよね。ですが、さて、「あっちのサーバー」は自社のプライベートクラウドの中に、「こっちのサーバー」はクラウド上のVPN繋いだ先に…。

そんな中でファイル転送をしようとなると、以下の事情が
1. サーバー同士はネットワーク接続されてない
2. ファイルの持ち出しやらセキュアにするの面倒
3. scpやらWinSCPやらFTPやら…なんやらファイル転送ソフトが必要

## メリットとデメリット

### メリット

とっても楽です。
転送時や画面コピペや手打ちで起きがちな以下の問題も回避してくれます。
 - リターンコード問題
 - スペースとかタブ問題
 - ファイル終端文字問題
 - 文字の見間違い（全角半角間違い）
 - 実は端末でエンコードが違った

### デメリット

- base64コマンドがないとか前提のコマンドが入ってないと使えません
- コピペできるサイズは上限があります。まぁ、多分、サイズ上限の前に画面選択が嫌になる程の大きさです。（Windowsの場合は、4MBかな。）
- ペーストできる範囲も使用する端末で制限があるでしょう
- この技術自身の問題じゃないですが、応用すればファイル転送が禁止されている（とされている）マシンとのファイルのやり取りができること



## 解説
前の↓の記事と一緒ですが、コマンドとメリットを見て、「分かった、できる」って人は、もうこの解説は読まなくて大丈夫です。

https://qiita.com/KNAMBA-1999/items/ad65c0f9b40a6b6e45da

まぁ、技術は大したことじゃないです。要は、「巧く使いましょうプロなんだから…」って話です。

### 基本は前回のパイプと一緒

パイプの一部として、自分のマシンの「クリップボード」（コピペの際の保管メモリのこと）を使っているだけです。

- `base64`コマンド : 昔のメールインフラのために作られたデータを扱いやすい[Base64テキスト](https://ja.wikipedia.org/wiki/Base64)に変換したり、Base64テキストから元に戻せるコマンドです。
- `gzip`コマンド：圧縮したり圧縮を解除してくれます。

この`gzip`と`base64`コマンドは、可逆的なコマンドです。`base64`でエンコードして`base64 -d`でデコードすれば元通りです。`gzip -c`で圧縮して、`gzip -dc`で圧縮を解除すれば元通りです。

`gzip`を入れなくてもいいんですが、ファイルが大きくなるので入れています。


## 応用

サンプルは単一のファイルでしたが「可逆なコマンド」のペアと「標準出力」を組み合わせればいいのですから、以下のような応用があります。

### 応用1: tarを使った複数ファイルの一括送付

サンプルとして、こんなフォルダ構造の塊を送りたいとします。
```
$ find dir_a
dir_a
dir_a/afile1
dir_a/dir01
dir_a/dir01/afile1
dir_a/dir02
dir_a/dir02/afile2
```

tarしてgzipしてbase64しましょう。
送り元：
```
$ tar cfp - dir_a/ | gzip -c | base64
H4sIAAAAAAAAA+3VSwrCMBSF4SylO/Dem6RZjhSqUBSFavdvH4gdKQFTFP5vkAwSSOBwkrbr983O
FSWjFOM0a4qynp+chhRqH5KaOlE1UVfFstdaDLd701eVOw2X7vpm36f1P9XO+TfH7nzQUmdMAdch
ZORvFr2rpNSF1sh/zH8cRYu9Ajn9HzdO+asX+r+Fdf6lXoGc/i/5exOj/1t45W8/0X8VP/ff+P83
sc5/7r99/4ys/3/O32sK9B8AAAAAAAAAAAAAcjwArnaePAAoAAA=
$
```

先ほどと同じようにコピーします。

送り先：
```
$ cat | base64 -d | gzip -dc | tar fxpv -
（先程のテキストをココにペースト）
その後に「Ctrl+D」する。
dir_a/
dir_a/afile1
dir_a/dir01/
dir_a/dir01/afile1
dir_a/dir02/
dir_a/dir02/afile2
kunio@LAPTOP-DM9KOI5G:~$
```
同じフォルダ構造が、送り先に展開されました。


### 応用2: uuencodeとuudecodeを使う

`base64`はメールに添付するためのツールですが`uuencode`と`uudecode`という先輩がいます。
同じファイルに対する処理の結果で、似たようなもんですが、送った先で使ってほしいファイル名（この例だと`anewname.txt.gz`）をつける必要があります。
```
$ cat file.txt | gzip -c | uuencode anewname.txt.gz
begin 644 anewname.txt.gz
M'XL(`````````\U02XH5,!#<OU/T`89W"MVY]0`QZ?=LR&^2]#!+.PSBJ,/X
M041$1!`1OR`(@J"'Z8O8\3EW<)=.5U57U8W2,`'5S@E"B:5!IP$NX3@"7W)'
(省略)
M>:[SC@G=U?E(Y8N*$2]UGJG\,M1CE>\J3U6,^\Y04^69RH5.@XO*;Y7GH--0
4WW3._\R.RDN5%W\`"E1S5>("````
`
end
$
```
デコード側も似たようなコマンドです。`uudecode -o /dev/stdout`で送信側で付けられた名前を無視して標準出力にできると、[IBMのuudecodeのmanページ](https://www.ibm.com/docs/ja/aix/7.3?topic=u-uudecode-command)が言ってます。さらには、uuencodeで`-m`オプションを付けるとBase64フォーマットでの出力もできるとか、送信元に`base64`コマンドがなくても、もしかしたら`uuencode -m`が使えるかもしれません。

```
$ cat file.txt | gzip -c | uuencode -m anewname.txt.gz
begin-base64 644 anewname.txt.gz
H4sIAAAAAAAAA81QS4oVMBDcv1P0AYZ3Ct259QAx6fdsyG+S9DBLOwziqMP4
(省略)
33TO/8yOykuVF38AClRzVeICAAA=
====
```

### 応用3: メールに添付

さすが最近は難しいと思いますが、UNIXサーバーで`mail`コマンドなんて物が有効な場合もあります。

`base64`や前身の`uuencode`で作ったファイルをメールに添付して自分に送ってしまうなんて便利な使い方ができたりするかもしれません。
```
$ cat file.txt | gzip -c | uuencode -m anewname.txt.gz | mail -s "mail title" sendto@example.com
```

特に`uuencode`コマンドを使っていると便利です。
なんで便利か？

Base64の説明で記載しましたが「昔のメールインフラ」の為の古き良きルールで使われていた仕組みです。現代のメールインフラも原則的に、この古代のプロトコルには従っています。その為、`uuencode`でファイル名を指定してエンコードされメールに含まれたファイルは、指定したファイル名でデコードされた「ファイル」として届きます。この例で言えば、「file.txt」を圧縮したものが、「anewname.txt.gz」添付ファイルで届きます。

メールクライアントが、Base64やuuencodeをデコードするのは既定の動きのためです。
ただし、Base64はエンコードしたデータにファイル名を持たないため、メールクライアントはファイル名なしのデータを巧く扱えないかもしれません。その意味では、`uuencode`を使うことが重要です。

### 応用4: `base64`コマンドがないOMG！

Oh my gosh! 双方にbase64コマンドがないと、このコピペ手段は使えません。
でも、ご安心を、色んなところに base64 は実装されてます。

#### `openssl`コマンドの`base64`モード

もう、世の中、sshでログインするのは流石にデフォルトです。そんな、sshの裏で暗号化を支えているのは、opensslのライブラリです。ということは、大抵において、`openssl`コマンドは導入されてます。

以下のコマンドが使えちゃうでしょう。
```
$ cat file.txt | gzip -c | openssl base64 -A -in -
H4sIAAAAAAAAA81QS4oVMBDcv1P0AYZ3Ct25(省略)XnoNNQ33TO/8yOykuVF38AClRzVeICAAA=
```

base64は改行しなくてもいいんで、１行でながーくなますけど、同じ効果です。

#### opensslコマンドもない！

大丈夫です。
Base64は、もはや、どんな言語でもライブラリがあって（単純だから）、スクリプト言語でワンライナーで実現されてます。

perlくらい入ってるかも？ pythonくらい入っているかも？

https://qiita.com/aikige/items/ed0b14d5915ca5015363

ちょっとテキストを書いて実行するぐらいできるでしょう。ロジックが簡単すぎでシェルスクリプトで実現する人だっているでしょう。


### 応用5: Key Vaultのエントリに

かなりの応用ですが、コンテナベースのアプリ等で、ちょっとした設定やシークレットが複数入ったファイルなんかを扱いたいときもあるでしょう。

Key Vaultのエントリーは、大抵、数KB程度は保管できることが多く。この「コピペ」メソッドで固めた内容くらいを保存して入れておけたりします。

ユーザーやパスワード等、セットになった文字列を、既存の設定ファイルの一連の項目を作る必要があったりします。
```
user = こことか;
password = ここに;
url = "https://foo.bar.baz/api/";
```

更には文字のエスケープとか面倒くさいですね。同じ手段でBase64で１行化した文字列を登録しておけば、まるっと、一個のエントリで扱えたりして便利です。


## おわりに

以下のように同じ様なことを紹介している人は、います。

https://qiita.com/quenhulu/items/711c17fd5932c4767219

https://takuan.hateblo.jp/entry/20120803/p1

https://qiita.com/yamamototetsuya/items/92e496d74160bc52bdc7

ただ、今回は応用力が大事だと思うのです。base64コマンドがなくても、ワンライナーやopensslコマンド、PowershellだとCertutilでも使えるらしいと。

https://qiita.com/halpas/items/2296cf611a6370f640a3

SEは、沢山の仕事があります。些細なことで時間を取らないよう、こんな記事でも参考にして頑張ってほしいと思います。

## 背景

今日はシェル芸の紹介をしました。

プログラムを書いて、世の中の役に立つ製品でも作って生きたいなと思ってIBMって会社へ入社したらSE(当時の呼ばれ方、システムズエンジニア)という職種になって25年です。なったもんは仕方ないので、SEという職種で一人前になってやろうと言うことで、今にいたりますが。世の中の発展は早すぎて、何がSEの一人前がわからないくらいの状態ですし、技術に追いつくのがやっとこさです。とはいえ、世の中は25年前とあんまり変わらないテクノロジー(Linux)が存続していて、ローテクのシェル芸も私と同じく現役で役に立ちます。

現場の作業の実態を見ていると、どうにも非効率な状況が惜しい知識不足だったりするため、この記事を書くことにしました。

皆様のお仕事がスムーズ・安全に進むよう願っております。