コマンド
無駄に時間がかかっている作業をスピードアップしましょう。
$ tar cfp ./ - | gzip -c | tee /backup/backup.tar.gz | \
ssh targethost "cd /targetdir/; cat | tee /backup/backup.tar.gz | gzip -dc | tar fx -"
課題
システムの構築や移行などでは、ある程度の量のファイルをUNIXサーバー間でコピーする必要があります。元のサーバー側で纏める処理をして、先のサーバー側で展開する処理が必要な場合もあるでしょう。特定のフォルダの中身全部とか、DBのバックアップを取得して相手方に送るとか。結構、時間がかかるんですよね。
一般的に以下の順番で実施します。
- まとめファイルを作る(バックアップやファイルのアーカイブ処理)
- 圧縮する
- 転送する
- 圧縮を解く
- まとめファイルを展開する(リストアコマンドの実行とか、アーカイブ展開とか)
少量のファイルであれば、各処理に大した時間は掛かりません。ですが、私が過去に担当していた日本アイ・ビー・エムのWebサイトやショッピングサイトでは、データベースもコンテンツの量も大量です。上記に時間を含めると、まとめファイル作成に30分、圧縮に10分、転送に一時間(帯域による制限)、圧縮解除に10分、展開に30分と、それぞれの間に色々とコマンドを実行したり、一処理が終わっているのに気がつかなかったりで10分と、計2時間半です。
限られた時間で保守や移行を行うには、この2時間半は痛い損失です。
じゃあ、「全部をいっぺんにやろう!」というのが冒頭のコマンドになります。
メリットとデメリット
「全部をいっぺんにやる」ことで先の説明での時間配分ですと計2時間半を1時間に短縮できます。
デメリット
ただし、リスクがあります。
- よく原理を理解し、事前の試運転をしてから実施する必要があります。大舞台でこのパイプを一発勝負で実施して、成功する人はすごいです。
- 個別に実施している場合には、送り先側でのエラーがあってもステップごとにリカバリができます。送り先側で「展開スペースがないエラー/リストア失敗」等が起きてしまうと、SIGPIPEシグナルが送られてパイプ全体のコマンドが終了してしまいます。結果、すべてやり直しになります。
これらの対処方法は解説に記載します。
解説
コマンドとメリットを見て、「分かった、できる」って人は、もうこの後は読まなくて大丈夫です。
動作原理
パイプ「|
」は簡単にプログラム(コマンド)間の通信を実現するUNIXの大事な機能です。標準出力を標準入力にいれることで、各機能を実現するコマンドを数珠つなぎにして、一度に動作させます。
-
tar cfp ./ -
転送元の現在のフォルダ以下をtarアーカイブ形式にまとめて標準出力「-
」に出します。 -
gzip -c
標準入力に入った内容を圧縮します。 -
tee /backup/backup.tar.gz
標準入力に入った内容をそのまま標準出力に出しながら/backup/backup.tar.gzに保管します -
ssh targethost "cd /targetdir/; cat
リモートのtargethostホストにログイン(以下、前提参照)して、/targetdirに移動し、標準入力に入った内容をそのまま標準出力に出します。 -
tee /backup/backup.tar.gz
標準入力に入った内容をそのまま標準出力に出しながら異リモート側の/backup/backup.tar.gzに保管します -
gzip -dc
圧縮を解除します -
tar fx -
アーカイブファイルを/targetdir以下に展開します
前提:sshでのログインは公開鍵使ってパスワード入れないで済むになっているとかは前提です。検索して一発で出てきたQiitaのこの記事でも参考にしてください。
デメリットの対応策
リスクとして説明したデメリットへの対処方法です。
デメリット1への対策は、事前に予行演習等を行って、掛かる時間や宛先での容量等を確認してください。思わぬところで、NWのタイムアウト等に引っかかる可能性もあります。
デメリット2は、すべての処理を一連のパイプとして実施していることに起因します。ですのでパイプを二分割できればいいのです。シェル芸のワンライナーでは済まなくなるので面倒ですが、この様にします。
# 空のファイルを作る
$ touch /backup/backup.tar.gz
# 空のファイルをtailする形でリストア側のコマンドを先にスタート
$ tail -f /backup/backup.tar.gz | ssh targethost "cd /targetdir/; cat | tee /backup/backup.tar.gz | gzip -dc | tar fx -"
# 元側のファイル作成を開始
$ tar cfp ./ - | gzip -c >> /backup/backup.tar.gz
この状態では、2番目のssh先でトラブルが起きても元側のコマンドは影響を受けずに済みます。
tailが成立するために、/backup/backup.tar.gz
への書き込みを追記書き込みにしていたり、実行順番が大事だったりと細かい配慮が必要です。また、最後に、tailは止める必要があるでしょう。ここらへんの理解の上で使ってくださいね。
2番目のssh先で送り先にトラブルが起きた場合は、仕方ないので全部がしゅとくできたあとで以下のコマンドでやり直しをします。
$ cat /backup/backup.tar.gz | ssh targethost "cd /targetdir/; cat | tee /backup/backup.tar.gz | gzip -dc | tar fx -"
背景
今日はシェル芸の紹介をしました。
プログラムを書いて、世の中の役に立つ製品でも作って生きたいなと思ってIBMって会社へ入社したらSE(当時の呼ばれ方、システムズエンジニア)という職種になって25年です。なったもんは仕方ないので、SEという職種で一人前になってやろうと言うことで、今にいたりますが。世の中の発展は早すぎて、何がSEの一人前がわからないくらいの状態ですし、技術に追いつくのがやっとこさです。とはいえ、世の中は25年前とあんまり変わらないテクノロジー(Linux)が存続していて、ローテクのシェル芸も私と同じく現役で役に立ちます。
現場の作業の実態を見ていると、どうにも非効率な状況が惜しい知識不足だったりするため、この記事を書くことにしました。
皆様のお仕事がスムーズ・安全に進むよう願っております。