Digital Oceanで起動・終了をお手軽に行うシェル・コマンド

タグ: DigitalOcean  

(追記:APIの動作変更か、tugboatコマンドの変更か、OSをインストールし直したための環境変化か、うまく動作しなくなりました。そのため、APIを直叩きするバージョンを作成しました。そちらをご利用ください。Digital Ocean起動・終了スクリプト、API直叩きバージョン

前回の記事で紹介したコマンドで、いちいちDigital Oceanへログインしたり、Vagrantをいじることなく、操作が簡単に使えるようになりました。

が…、いつも同じ操作を行うのは面倒。いつも使うドロップレット(インスタンス)をさくっと動かし、さくっと保存して停止したいと思いました。

たいてい、開発していて、その日の作業を止めるのは、眠くなった時ですから、そんな時に保存の操作をやると、間違えるリスクがどーんと増えます。眠くてコマンドが思い出せない時もありますし、ミスタイプが多くてイライラしたりもします。

そこで、前回紹介したコマンドを使用した、起動・終了・クリーンアップスクリプトを作成しました。久しぶりにシェルを組んだので、2日もかかってしまいましたが、まあ便利なものが出来たので、よしとしましょう。

ああ、それと前回の記事ですが、かなり修正しましたので、ご利用されている方は、再度確認して下さい。

注意:tugboatではサポートされていませんが、Digital OceanのAPIには、指定したスナップショットに内容をオーバーライトする、restore(だったかな?今、サイトがダウンしているようで、確認できません。)を使用することも出来ます。

インストール

Bashシェルです。ですから、どこかでアップロードして…なんて手間はかけません。このページからお好きな名前のファイルへコピペし、内容を変更し、実行権限を付けて、実行パスの通っている場所へ移動し、使って下さい。ファイルの内容は、一番最後にあります。

ファイル、つまりコマンドは3つです。各ファイルの中の先頭部分を変更して、ご利用下さい。

  • tugboat : tugboatコマンドの場所です。実行パスが通っている場合は、そのままでOKです。

  • droplet : 起動するドロップレットにつける名前です。分かりやすい、お好きな名前にして下さい。

  • snapshot : スナップショットの名前です。分かりやすい、お好きな名前にして下さい。

  • remain : 保存しておく、スナップショットの個数です。

シェル内の、tugboadコマンドにつけているオプションは最低限にしてあります。tugboadコマンド自体が~/.tugboadファイルにデフォルト値を保存できる仕組みになっているため、それを活かすためです。そのファイルのデフォルト値以外を指定したい場合は、シェルを自由に書き換えて下さい。

今回、紹介するシェルは、著作権保持にしておきますが、利用・改変はご自由にどうぞ。

ワークフロー

  1. Digital Oceanに作っておいた環境が使用したくなったら、起動スクリプトを実行します。すると、前回の最後の環境が保存されていたスナップショットから、新しいドロップレットが作成され、SSHの接続までを行います。
  2. 本日の作業はここまでとなったら、終了スクリプトを実行します。すると、インスタンスを停止し、そのディスク環境をスナップショットとして保存し、ドロップレットを削除します。
  3. 保存用のスナップショットは同名でいくつも保存されたままとなります。いざという時の、バックアップになります。とはいえ、ため過ぎも良くないので、定期的に削除しましょう。(現在は課金がされていませんが、いつ始まるか分かりません。)クリーンアップスクリプトを実行すると、内部で指定してある数だけ、最新のスナップショットを残し、残りは全部削除します。

仕組み

Digital Ocean(以降、DO)のドロップレットは削除しない限り、課金の対象です。内容はスナップショットとして保存し、次回はそのスナップショットから、ドロップレットを再作成することで、前の環境を復活できます。スナップショットは、DOの環境に保存されます。

ドロップレットとスナップショット、SSHキーには、名前が付けられます。この名前は、識別子ではなく、単なるラベルのようなものです。そのため、同じ名前をつけることが可能です。そのため、tugboatコマンドは指定された「名前」をファジーに検索します。これが使いやすくもあり、使いにくくもあります。

今回作成したシェルスクリプトには、決まったドロップレット名、スナップショット名を含めています。ドロップレット名は、シェルで起動するドロップレットの名前です。スナップショット名はドロップレットのスナップショットを保存する場合の名前になります。

起動スクリプトは、指定された名前を持つナップショットの中から、最新のものを選び、それを元にドロップレットを起動します。起動後は、SSHの接続まで行います。あとは設定によりパスワードの入力を求めまれたり、SSHのパスフレーズの入力が求められたり、そのまま接続されたりします。

終了スクリプトは、起動中のドロップレットのうち、指定された名前を持つ、最新(一番最後の起動)のものを選択し、それを一度電源停止状態にします。それから、スナップショットを取り、それが完了したら、ドロップレットを削除します。

終了スクリプトを実行せず、起動スクリプトを何度も実行すると、同名のドロップレットが、その数だけ起動します。ただし、そうした利用を想定して起動・終了スクリプトは作成していません。(同じ数だけ、起動と終了スクリプトを実行すれば、動くとは思います。)基本的に、一つだけドロップレットを起動し、要らなくなったら、保存・終了することを目的としています。

クリーンアップスクリプトは、指定された名前のスナップショットを指定された数まで削除します。指定した数だけ最新のスナップショットを残し、残りは削除します。

スクリプトですから、やっていることは一目瞭然です。

使用法

  1. インストールしていない場合は、tugboatコマンドをインストールして下さい。
  2. DOのドロップレット管理ページ、もしくはtugboatコマンドで、お望みのドロップレットを作成して下さい。環境を整え、SSHでログインができる状態にしましょう。
  3. インストール手順に従い、スクリプトにドロップレット名、スナップショット名、クリーンアップ時の保存個数を設定します。同じ名前の変数には、同じ名前を指定して下さい。
  4. まず、終了スクリプトを実行して下さい。スナップショットを取り、インスタンスを削除し、課金されない状態にします。
  5. 同じディスク環境を使用したくなったら、開始スクリプトを実行して下さい。保存してあるスナップショットから、ドロップレットを復元し、起動します。--sizeオプションをつけると、サイズが選択できるようになります。起動サイズの変更を行いたい場合に、利用して下さい。
  6. 作業終了時には、終了スクリプトを実行です。
  7. 定期的にクリーンアップスクリプトを実行しましょう。スクリプト内に指定した個数だけ、最新のスナップショットを残し、残りはまとめて削除します。

スクリプト

Bashスクリプトです。抵当なファイルにコピペし、使用して下さい。

起動スクリプト

#!/bin/bash

# Copyright Hirohisa Kawase

#pecify path to your tugboat command if needed.
# tugboatコマンドのパスを必要ならば、指定して下さい。
tugboat='tugboat'

# Specify Droplet name to make snapshot.
# 保存するドロップレットの名前を指定して下さい。
droplet='DailyDevelepment'

# Specify snapshot name.
# スナップショット名を指定して下さい。
snapshot='DailyDevelepmentBackup'


# Make temporay file name
# 一時ファイル名生成

tempfile=`mktemp`


# Display size menu.
# サイズメニューの表示

if [ "${1}" = "--size" ]
then

    PS3="Select size, or q)uit > "

    # Get droplet sizes.
    # サイズ取得

    $tugboat size > $tempfile

    awkcommand="{ match(\$0, /(.+) \(id: /, mt); print mt[1]}"
    sizes=`awk -e "$awkcommand" $tempfile`

    select item in $sizes
    do
        if [ "${REPLY}" = "q" ]
        then
            exit 0
        fi

    if [ -z "$item" ]
    then
        continue
    fi

    echo $item

    # Make -s option for create command.
    # 作成コマンドのため、-sオプションを作成する

    awkcommand="{ match(\$0, /${item} \(id: (.+)\)/, mt); print mt[1]}"
    size=`awk -e "$awkcommand" $tempfile`
        sizeoption="-s ${size}"

    break
    done

    # Wait three seconds for missed selection.
    # サイズを間違えた時のために、3秒待つ。

    sleep 3
fi


# Get snapshots.
# スナップショットイメージの取得

$tugboat images > $tempfile
cat $tempfile

# Get latest snapshot image.
# 最後に作成されたスナップショットイメージの取得

awkcommand="/^$snapshot \(id: / { match(\$0, /id: (.+), /, mt); print mt[1] }"
latestsnapshot=`awk -e "$awkcommand" $tempfile | sort -r | head -n 1`

echo $latestsnapshot

if [ -z $latestsnapshot ]
then
    echo Can\'t find droplet by named \'$droplet\' 1>&2
    exit 1
fi

# Create a droplat with latest snapshot image.
# 最後に作成されたスナップショットから、ドロップレットを作成する。

$tugboat create $droplet -i $latestsnapshot $sizeoption

# Get droplets information
# 起動しているドロップレットの情報取得

$tugboat droplets > $tempfile

# Get latest droplet id.
# 最後に作成されたドロップレットの取得

awkcommand="/^$droplet \(ip: / { match(\$0, /id: (.+)\)/, mt); print mt[1] }"
latestdroplet=`awk -e "$awkcommand" $tempfile | sort -r | head -n 1`

# Wait the droplet has made just before, to be active.
# 起動されたばかりドロプレットが、activeになるのを待つ。

$tugboat wait $droplet -i $latestdroplet -s active

# Wait a more while, then connect with SSH.
# (Because of hangup the command sometime when soon connected)
# 時間を開け、SSHに接続
# (activeになった直後にSSHへすぐ接続すると、コマンドがハングアップするため)

sleep 30
$tugboat ssh $droplet -i $latestdroplet
終了スクリプト
#!/bin/bash

# Copyright : Hirohisa Kawase

#pecify path to your tugboat command if needed.
# tugboatコマンドのパスを必要ならば、指定して下さい。

tugboat='tugboat'

# Specify Droplet name to make snapshot.
# 保存するドロップレットの名前を指定して下さい。

droplet='DailyDevelepment'

# Specify snapshot name.
# スナップショット名を指定して下さい。

snapshot='DailyDevelepmentBackup'



# Make temporay file name
# 一時ファイル名生成

tempfile=`mktemp`

# Get droplets.
# 起動中のドロップレットの取得

$tugboat droplets > $tempfile
cat $tempfile

# Get latest droplet id.
# 最後に作成されたドロップレットの取得

awkcommand="/^$droplet \(ip: / { match(\$0, /id: (.+)\)/, mt); print mt[1] }"
latestdroplet=`awk -e "$awkcommand" $tempfile | sort -r | head -n 1`

if [ -z $latestdroplet ]
then
    echo Can\'t find droplet by named \'$droplet\' 1>&2
    exit 1
fi

# Halt it and wait it.
# 電源をoffにし、終了するまで待つ。

$tugboat halt $droplet -i $latestdroplet -h
$tugboat wait $droplet -i $latestdroplet -s off


# Take a snapshot.
# スナップショットの取得

$tugboat snapshot $snapshot $droplet -i $latestdroplet

# After processing, it turn on. So wait it.
# 処理が終わると、自動的に起動する。そのため、それを待つ

$tugboat wait $droplet -i $latestdroplet -s active

# Destroy the droplet.
# ドロップレトの削除

$tugboat destroy $droplet -i $latestdroplet -c
クリーンアップスクリプト
#!/bin/bash

# Copyright Hirohisa Kawase

# Specify path to your tugboat command if needed.
# tugboatコマンドのパスを必要ならば、指定して下さい。

tugboat='tugboat'

# Specify snapshot name.
# スナップショット名を指定して下さい。

snapshot='DailyDevelepmentBackup'

# Number of holding snapshots.
# 残しておくスナップショットの数

remain='1'



# Make temporay file name
# 一時ファイル名生成

tempfile=`mktemp`

# Get images.
# イメージの取得

$tugboat images > $tempfile

cat $tempfile

# Get image ids to destroy.
# 削除するイメージのIDを取得する。

awkcommand="/$snapshot \(id: .+,/ { match(\$0, /\(id: (.+),/, mt); print mt[1] }"
sedcommand="1,$remain d"
destroyimages=`awk -e "$awkcommand" $tempfile | sort -r | sed -e "$sedcommand"`

if [ -z $destroyimages ]
then
    echo There are no snapshot images to destroy. 1>&2
    exit 1
fi

# Destroy images.
# スナップショットイメージを削除する。

for image in ${destroyimages}
do
    $tugboat destroy_image $snapshot -i $image -c
done

まだ、Digital Oceanのアカウントをお持ちでない方は、https://www.digitalocean.com/?refcode=a08c0e1bf8d8からアクセスして頂くと、うちのシロ(野良猫出身)が美味しい餌にありつけます。(かわいそうに、犬のゴンタは、若い時の美食がたたり、慢性的な尿道結石のため、専用の餌しか食べられません。既に三回手術しました。おまけに、半年に一回、膀胱洗浄をします。まあ、二匹とも弟が飼い出したので金銭的な世話は、弟の担当です。他の世話は、家族で分担です。若い時に、私が実家にいればちゃんとしつけたんですけどね。戻った時には、もう半病犬でした。)