Sunzi で sudo を使えるようにするラッパーを作った

sunzi を試してみる - Memo で試した Sunzi だけど sudo が使えないのが困った。


今の職場は root 権限は貰えないけど個人のアカウントに sudo は付けて貰える。
なので sudo ができるのが前提。

シェルスクリプトの中で sudo を付けて、sunzi deploy を実行するとこんなエラーになる。

sudo: sorry, you must have a tty to run sudo

単純に ssh コマンドを発行している所で -t を付けたら行けると思ったが以下のようなエラーになった。

Pseudo-terminal will not be allocated because stdin is not a terminal.
Warning: Permanently added '192.168.1.10' (RSA) to the list of known hosts.
user@192.168.1.10's password: 
sudo: sorry, you must have a tty to run sudo

仮に本体の方を sudo できるように issue をたてたり、パッチを作っても取り入れられなさそう。

Always use the root user.

GitHub - kenn/sunzi: Sunzi: Server configuration automation for minimalists

と Readme に書かれている通り root 前提という設計思想。
Sunzi をとても気に入ったのでラッパーを作る事にした。


SSH で sudo できる関連の事を調べている最中に Python の Fabric は sudo が使える事を思い出した。
Sunzi のコードを読んみると、定義したシェルスクリプトを一つのディレクトリ(compiled)にまとめるのと、compiled を転送してリモートサーバで install.sh を実行するタスクが分かれていた。
なので全てポーティングするではなく、Sunzi を利用して転送、実行の箇所だけ Fabric を使う事にした。


GitHub - heavenshell/sunzi-sudo: Wrapper for Sunzi using Python Fabric

  • Fabric で Sunzi の compile を実行し(sunzi compile)、compiled ディレクトリを作る
  • Fabric で compiled を tar.gz 形式に圧縮し、Fabric の put() を作ってリモートサーバに転送
  • Fabric でリモートサーバに転送したファイルを展開
  • Fabric でリモートサーバの install.sh を sudo() を使って実行

やってるのはこんな感じ。

使い方

Fabric と PyYaml が必要なのでインストールする。

$ sudo pip install Fabric
$ sudo pip install PyYaml

Githubリポジトリより fabfile を sunzi プロジェクトと同階層にダウンロードする。

$ git clone https://github.com/heavenshell/sunzi-sudo.git

実行

$ fab sunzi:foo@example.com

bundler を使ってる場合は以下の様にする。

$ fab sunzi:bundle,foo@example.com

Fabric のオプションを利用した書き方もできる。

$ fab sunzi:bundle -H example.com -u foo

複数ホストに対して実行する場合は以下のように書く。

$ fab sunzi:bundle -H a.example.com,b.example.com -u foo


本来なら Ruby でラッパーを作るのが筋なんだろうけど、動く事が目的だし自分の為のツールだし、sudo やリモートの操作が出来る Fabric を使いたいから Python で書いた。
これで便利になった!


あと、Fabric は exit ステータスが 0 じゃないと警告を出すので、install.sh とかの最後は sunzi::silencer で終わらない方が良い。