• このエントリーをはてなブックマークに追加

スポンサードリンク

はじめに

去年, Immutable Infrastructure という言葉を知った.

この概念を Emacs の管理に利用できないかなとという話.

これをやろうと考えたのは, 去年の 6 月だった. この記事の延長が本記事.

なかなか時間がとれなくて, 結局半年後の冬休みにようやくできた.

問題の分析

問題

Emacs を家でも会社でも利用している.以下が簡単な環境.

  • 自宅
    • ArchLinux
    • Widows 8 (GUI 版)
  • 会社
    • Widows 7 (GUI 版)
    • Windows 7 (Cygwin 版)

設定を github にあげて, 設定を共有している. 会社で設定ファイルを更新するのは社内規程的に NG なので, いつもは以下のような運用.

  • 自宅で設定ファイルを git push
  • 会社で設定ファイルを git pull

しかし, 自宅で設定したものが会社で動かなかったりすることがよくある.

会社で Emacs の設定ファイルを更新した後は, 朝の 30 分は毎回 Emacs と戯れているのはここだけのないしょだ.

しかし, 設定の同期作業も, 面倒なのでなんとか時間を短縮できないもの か… というのが今回の解決したい問題.

また, 1 年に 1 回 くらいの頻度で Emacs 環境を一から再構築することがある. このとき, Emacs の パッケージ管理は el-get を利用して管理しているので, 自動ですべてのパッケージを ネットから落としてきて動作するはず.

しかし, 必ず el-get のダウンロードで失敗するパッケージがたくさんでる.

会社だと, proxy という厄介なものがある. また, 設定の問題とは思うが, MELPA へアクセスできなく github からしか elisp を取得できない.

まとめると,

  • 会社で Emacs の設定ファイルを更新したときに 起動時のエラーを発生させなくするためには?
  • Emacs 環境を一から再構築するときに エラーを発生させなくするためには?

課題

よくあるあたふたケースは,

  • 自宅の Linux 環境で push したものを 会社の windows 環境で pull して動かなくなる.
  • 会社で pull をするのが怖いのでしばらく放置した後, 久しぶりに pull すると 大量のエラーが発生する.

エラーがあっても放置してしまうのは, 頻繁に エラーの確認をしないから. それは面倒だからしない. エラーの確認作業を自動化できたらうれしい.

ということで, 課題は以下.

  • Linux 環境で push したら Windows 環境で pull してエラーチェックを する作業を自動化する.
  • 定期的に一から Emacs の設定を再構築する作業を自動化する.

解決策

この 自動でエラーをチェックするところを Immutable Infrastracture の概念と 組み合わせたらおもしろそうだと思った. 無駄な勉強にもなるし.

Immutable Infrastructure とは

簡単に調べてみた.

一度サーバーを構築したらその後はサーバーのソフトウェアに変更を加えないこと.

以下の説明がとてもわかりやすい.

Windows って調子が悪くなると再インストールしてすっきりさせるじゃないで すか. OS にいろんなソフトウェアをインストールしたりカスタマイズしたり すると調子が悪くなりますが, 再インストールすれば戻ります.

だったら, そもそも毎回作り直せばシステムはすっきりするよね, というのが 簡単な Immutable Infrastructure の説明です.

Action Plan

以下のようなアクションプランを考えた.

  • AWS 上のサーバで Emacs 環境を構築する.
  • AWS 上のサーバで エラチェックーを走らせる.
  • チェックがおわったらサーバを破棄して終了.

さらにこの手順の自動化ができたらいいけど, これは大変そうなので今度.

  • git push したら AWS 上で動く サーバで エラチェックーを走らせる.
  • 毎週深夜に, Emacs 環境を自動で構築する.

解決へのとりくみ

Windows 環境はなにかと難しいとおもったので, まずは, Linux 環境を構築することにした.

というわけで, この記事のゴールは,

AWS 上に Emacs と自分の Emacs の設定を自動でインストールすること

名づけて,

Immutable Emacs! 大作戦.

響きがとても気に入った!

AWS を借りる

別記事に独立.

ここでは, Ubuntu Server 14.04 LTS (HVM), SSD Volume Type をつかう.

ansible で Amazon AWS に SSH 接続

なれている, ansible を利用する.

mkdir -p  ~/.emacs.d/playbook
cd ~/.emacs.d/playbook
echo '54.65.121.127' >> hosts

以下の作業はすべて,~/.emacs.d/playbook で実施.

ansible.cfg ファイルを作成.

   [defaults]
   hostfile = ./hosts
   remote_user = ubuntu
   private_key_file = ~/.ssh/archlinux.pem
   host_key_checking = False

ping する.

ansible all -m ping -i hosts
54.64.58.11 | success >> {
    "changed": false, 
    "ping": "pong"
}

ansible playbook

org-mode で書いたものは, 以下のスクリプトで yaml に変換する.

#!/bin/sh
# -*- mode: shell-script -*-
#
# tangle files with org-mode
# see: http://orgmode.org/manual/Batch-execution.html
#
DIR=`pwd`
FILE=""

for i in $@; do
    # tangle org to yaml
    emacs -Q --batch --eval "(progn
     (add-to-list 'load-path \"/usr/share/emacs/site-lisp/org\")
     (require 'org) (require 'ob) (require 'ob-tangle)
     (setq org-src-preserve-indentation t)
     (find-file (expand-file-name \"$i\" \"$DIR\"))
     (org-babel-tangle)
     (kill-buffer))" 2>&1 | grep tangled

    # execute ansible command to yml file
    string_filename=${i##*/}
    string_filename_without_extension=${string_filename%.*}
    string_path=${i%/*}

    if test $string_filename = $i ; then
	ansible-playbook ${string_filename_without_extension}.yaml -i hosts
    else
	ansible-playbook ${string_path}/${string_filename_without_extension}.yaml -i hosts
    fi
done

ここからは実際の ansible playbook を書く.

ansible settig

---
- hosts: defaults
  sudo: yes
  vars:
    home_dir: /home/ubuntu
    emacs_dir: emacs
    dotfiles_dir: dotfiles
  tasks:

initial tools

  • libncurses5-dev は tputs error 対策
  • gnutls-bin for el-get
  • texinfo for makeinfo
    - name: apt-get update
      command: apt-get update
    - name: apt-get install git
      apt: pkg=git
    - name: apt-get install build tools
      apt: pkg=build-essential,autoconf,automake,libncurses5-dev,gnutls-bin,texinfo

install emacs

    - name: get emacs from git repository
      git: repo=git://git.savannah.gnu.org/emacs.git dest={{home_dir}}/{{emacs_dir}} accept_hostkey=yes
    - name: make emacs configure file
      command: ./autogen.sh chdir={{home_dir}}/{{emacs_dir}}
    - name: make emacs Makefile
      command: ./configure --prefix=/usr/local --without-makeinfo --with-x-toolkit=no --without-all chdir={{home_dir}}/{{emacs_dir}}
    - name: make emacs
      command: make chdir={{home_dir}}/{{emacs_dir}}
    - name: install emacs
      command: make install chdir={{home_dir}}/{{emacs_dir}}

install dotfiles

    - name: clone dotfiles
      git: repo=https://github.com/tsu-nera/dotfiles.git dest={{home_dir}}/{{dotfiles_dir}}
    - name: make lnlinks
      command: ./make_lnlink chdir={{home_dir}}/{{dotfiles_dir}}
      sudo: yes
      sudo_user: ubuntu

install additinal tools for emacs

    - name: install additinal tools for pdf-tools
      apt: pkg=libpng-dev,libz-dev,libpoppler-glib-dev,libpoppler-private-dev 
    - name: install additinal tools for magit
      apt: pkg=texinfo
    - name: install additinal tools for org2blog
      apt: pkg=bzr
    - name: install additinal tools for exectable-find
      apt: pkg=mercurial
    - name: install additinal tools for cmigemo
      apt: pkg=cmigemo
    - name: install additinal tools for ag
      apt: pkg=silversearcher-ag

boot emacs

Emacs の boot に, el-get を利用してパッケージを次々にダウンロードする.

    - name: boot emacs first 
      command: emacs --daemon
      sudo: yes
      sudo_user: ubuntu
    # - name: reboot emacs
    #   command: emacsclient -e '(progn (defun yes-or-no-p (p) t) (kill-emacs))' && emacs --daemon
    #   command: emacs --daemon
    #   sudo: yes

おわりに

これで AWS 上で動く Ubuntu サーバに Emacs をインストールすることができた.

まだまだ, 改良の余地は大ありだ.まだ, スタート地点.

dotfiles を育てるように, ansible のコードも育てていきたい.