しふみんのブログ

しふみんのブログです。

Macbookのなるべくホームポジションを維持するキーバインドについて考える

前置き

最近ずっとMacbookキーバインドについて考えていて、現時点での自分なりの回答を用意できたのでまとめてみたいと思います。 前提として、自分は、US配列キーボード、OSがSierraMacbook ProでiTerm2, tmux, Zsh, Vimあたりを使っているウエブケーエンジニアです(iTerm2, tmuxは特に考慮すべきキーバインドの競合がなかったけど)

各種アプリのインストール方法、設定方法等はインターネッツをご参照ください。

環境

MacBook Pro 13-inch, 2016, US配列キーボード
MacOS Sierra 10.12.5
iTerm2 3.0.15
tmux 2.5
Vim 8.0
Karabiner-Elements 0.91.8
英かな 2.2.3

やりたかったこと

なるべく指をホームポジションに維持したまま生きていきたかった。具体的には各種矢印, Esc, Delete, returnキーあたりのホームポジションから離れているキー(の機能)を複合キーにしてもいいからホームポジション近くに位置させたかった。

設定したキーバインド

下記が今回設定したキーバインド

USキーボードなので大前提として設定したキーバインド

左コマンドキー単体で押下 -> 英数キー
右コマンドキー単体で押下 -> かなキー
コロン -> セミコロン
セミコロン -> コロン
Caps Lockを他のキーと一緒に押下 -> Controlキーとして扱う

やりたかったキーバインド

Caps LockをContorlに変えたので下記のControlはaキーの横にあるCaps Lockを押す想定。

Control + H -> (fn)←(矢印の左)
Control + J -> (fn)↓
Control + H -> (fn)↑
Control + L -> (fn)→
Control + M -> enter
Control + , -> delete # Windowsでいうところのbackspace
Control + . -> fowarded_delete # 同上 delete

Caps Lock単体で押下 -> Escapeキー

その他(ついでに追加した設定)

Shiftキー + deleteキー -> forward delete)

必要なアプリとその設定

上記のキーバインド設定のために使用するアプリはKarabiner-Elements英かなの2つ。 それ以外はシステム環境設定も含めて特に設定はしていません。 それぞれのアプリの設定は下記の通り。

Karabiner-Elements

設定は画像の通りです。

f:id:shifumin:20170720224929p:plain

英かな

設定は画像の通りです。

f:id:shifumin:20170720224936p:plain

競合するキーバインド

上記のキーバインドを設定することによる潰れる(私の使用している)各ツールのキーバインドは下記の通り。

Zsh

$ bindkey -L
(抜粋)
bindkey "^H" backward-char
bindkey "^J" history-substring-search-down
bindkey "^K" history-substring-search-up
bindkey "^L" forward-char
bindkey "^M" accept-line
bindkey "^[," _history-complete-newer

使用コマンドのsearchはpecoに任せているので問題なし。

Vim

$ vim
:help index.txt
(抜粋)
1. Insert mode
CTRL-H          same as <BS>
CTRL-J          same as <CR>
CTRL-K {char1} {char2}
                enter digraph
CTRL-L          when 'insertmode' set: Leave Insert mode
CTRL-M          same as <CR>

2. Normal mode
CTRL-H          1  same as "h"
CTRL-J          1  same as "j"
CTRL-K             not used
CTRL-L             redraw screen
CTRL-M          1  same as <CR>

3. Visual mode
CTRL-H          2  same as <BS>

4. Command-line editing
CTRL-H          same as <BS>
CTRL-J          same as <CR>
CTRL-K {char1} {char2}
                enter digraph
CTRL-L          do completion on the pattern in front of the
                cursor and insert the longest common part
CTRL-M          same as <CR>

特に問題ないように思える。

Neosnippet

Vim本体は問題なかったが、プラグインでNeosnippet(neocomplete)を利用しており 公式のキーバインド設定をそのまま流用しているので、下記の設定の移行先を考える必要がある。

imap <C-k>     <Plug>(neosnippet_expand_or_jump)
smap <C-k>     <Plug>(neosnippet_expand_or_jump)
xmap <C-k>     <Plug>(neosnippet_expand_target)

候補としては<C-s>あたりが有力かなと考えている。

その他

MacOS標準IME

標準IMEの下記キーバインドが潰れる。 これは結構痛いかも、、、

Control + J -> ひらがなに変換
Control + K -> カタカナに変換
Control + L -> 全角英字に変換
Control + ; -> 英字に変換

雑感箇条書き

  • 当初は英かなを使わずにKarabiner-Elementsのみで設定しようとしてcomplex_modificationsを自作すれば設定自体はできたが、Controlを押したままm/,を押してもenter/deleteが連続で押されないのを解消できなかったのでKarabiner-Elementsと英かなを併用している
  • Google Chromeのアドレスバーに単語を入れてのウェブ検索だけ、標準のreturnとCtrl + m で設定したreturnの挙動が異なっていて困っている。
    • 具体的には後者の場合、例えば"ほげ"と入力してキーを押すと「"ほげ"で検索」されずに「http://www.ほげ.com/」にジャンプしようとする
  • Ctrl + m / , / . に設定した return / delete / forward に慣れないのでしばらく指を鳴らす必要がありそう


以上です。

参考

tekezo/Karabiner-Elements: The next generation Karabiner for macOS Sierra
https://github.com/tekezo/Karabiner-Elements

Karabiner-Elements complex_modifications rules
https://pqrs.org/osx/karabiner/complex_modifications/

⌘英かな
https://ei-kana.appspot.com/

Shougo/neosnippet.vim: neo-snippet plugin contains neocomplcache snippets source
https://github.com/Shougo/neosnippet.vim

Twilogをスクレイピングしてツイートを取得して表示するRailsのWebアプリを作った

作ったもの

ツイスク

http://shifumin.com/twisc

f:id:shifumin:20151124223358p:plain f:id:shifumin:20151124223403p:plain

ツイスク(Twilog Scraping)Twilog( http://twilog.org/ ) に登録されてある指定したTwitterIDの指定した日付のツイートをまとめて取得して表示するRailsのWebアプリです。 なんと、TwilogスクレイピングするためTwilogに登録されていないアカウントには使えません!

用途として、例えば、フォロワーのあの人は今年のエイプリルフールに一体どんなクソツイートをしたんだろうと思って知りたい時にTwitterIDと2015年4月1日を入力して使うみたいなのを想定しています(想定していない)

構成

さくらVPS1Gプラン, CentOS6.7, Apache2.2.15, Passenger5.0.21, Ruby2.2.3, Ruby on Rails4.2.3

スクレイピングに使ったgemはNokogiriです。

コードは、Githubに上げています(inital commitってタイポしていて恥ずかしい……)

github.com

作った背景

構成については、RubyRailsを勉強していて、何かアプリを1つ作ったら学びがありそうだなと考えて、VPSを借りているからそこで公開したらついでに必然的にWebサーバの勉強にもなるなと思ったのでこういう構成になりました。

機能については、自分大好きな人間なので過去の自分のツイートをつぶやくBotを作成しようとして、ツイートをスクレイピングして取得するスクリプト自体は書いていたので、それを少し改良してあるTwitterIDのある日付のツイートを取得するようにしました。

四方山話

  • 当初は、 ある月 のツイートを取得して表示する実装にしていたのですが、1日から30日(31日)のページまで30回(31回)Nokogiriでスクレイピングする方法しか思い浮かばなくて、流石に短時間に30回連続でTwilogのサーバに負荷をかけるのはまずいんじゃないかと思って、 ある日 のツイートを取得するように変更しました。

  • 当初は、WebサーバはUnicorn + nginxという構成にしようとしたけど、とりあえず形になったらいいかと思ってApache + Passengerを採用しました。Unicorn + nginxは速くて軽いと聞くので機を見てリプレースしたいと思います。

  • CSSというかデザインが全く分からなかったし、現時点ではあまり時間をかけたくなかったので、RailsチュートリアルのBootstrapのスタイルシートを丸パク……参考にしました。CSSもBootstrapも全然分からないけど、せめて年と月と日の入力フォームを横に表示させたい……

今後

超絶簡単なRailsアプリをWeb上に公開するまでの知見は得られたので、これからも何かを作っていきたいですね。

Yahoo!ファイナンススクレイピングして一番連続した日数値下がりしている株を見つけて「〇〇は△日連続で値下がりしているので明日は上がる!買えば捗るぞ!!(自己責任)」みたいに雑な投資推奨情報を提供するアプリとか(今適当に思いついた)

Rubyプロジェクトの始め方の備忘録

Rubyプロジェクトの始め方の備忘録

自分の記憶力が薄弱すぎて、Rubyで何か書くかとなった時にいつも下準備の仕方を調べている気がするので、後で楽するために備忘録を残しておきたいと思います。

余談ですが、自分の記憶力が薄弱すぎて(大事なことなので2回繰り返した)「自分のために残すメモ的な意味の熟語なんだっけ?忘備録だったっけ?」って思ってググったら、「備忘録」(忘れるのに備える記録で備忘録)が正しくて、よく見る「忘備録」は誤記で「備えるのを忘れた記録になる」という意味になってしまうようです。 勉強になりました。

前提となる環境

  • Mac OS X
  • giboをインストール済
  • ruby-build,rbenvをインストール済

準備

ディレクトリを作ってgit initしてからgiboで.gitignoreをお手軽に作成する。giboは、RubyOSXVimを引数に指定する(OSXVimはなくてもいいかも)

$ mkdir rubyproject
$ cd rubyproject
$ git init
$ touch .gitignore
$ gibo Ruby OSX Vim >> .gitignore

simonwhitaker/gibo · GitHub https://github.com/simonwhitaker/gibo

Rubyの設定

使用するRubyの設定をする。 rbenvでその時点での最新版のRubyを入れる。

$ rbenv install -l
$ rbenv install x.x.x(インストールするRubyのバージョン)
$ rbenv local x.x.x
$ rbenv rehash

sstephenson/rbenv · GitHub https://github.com/sstephenson/rbenv

Bundlerの設定

基本的にプロジェクトで使用するBundlerでgemはローカルディレクトリに保存するけど、Bundlerとrubocopはシステムワイドにインストールしているので、その2つを最新版にする。 その後使用するgemをローカルにインストールする。

$ gem update --system
$ gem update bundler
$ gem update rubocop
$ bundle init
$ vim Gemfile
(使うgemを記述する)
$ bundle install --path vendor/bundle

Bundler: The best way to manage a Ruby application's gems http://bundler.io/

Gemfile

プロジェクトで使用するgem以外のデバッグ等に使用するgemは以下を使っている。

source "https://rubygems.org"

ruby 'x.x.x'(インストールしたRUbyのバージョン)

group :development do
  gem 'awesome_print'
  gem 'tapp'
  gem 'pry'
  gem 'pry-doc'
  gem 'pry-byebug'
  gem 'pry-stack_explorer'
  gem 'refe2'
end
  • awesome_print

デバッグ時等にオブジェクトのデータ構造を分かりやすく表示してくれる。 .pryrcに下記のように書いてpry起動時に自動的にrequireするようにしている。

# awesome_print
begin
  require "awesome_print"
  AwesomePrint.pry!
rescue LoadError => e
  puts "no awesome_print"

michaeldv/awesome_print · GitHub https://github.com/michaeldv/awesome_print

  • tapp

メソッドチェーンの途中に挟むと、pp(puts)しながらレシーバを返すObject#tappやObject#taputsが使えるようになる。 プリントデバッグが捗る。

esminc/tapp · GitHub https://github.com/esminc/tapp

  • pry

強いirb

pry/pry · GitHub https://github.com/pry/pry

  • pry-doc

show-source でCで書かれているRuby組み込みのクラスやメソッドのソースを見ることができる。

pry/pry-doc · GitHub https://github.com/pry/pry-doc

  • pry-byebug

binding.pryデバッグする時にピンポイントで処理を止めてステップ実行できる。

deivid-rodriguez/pry-byebug · GitHub https://github.com/deivid-rodriguez/pry-byebug

  • pry-stack_explorer

デバッグ時に show-stack でその時のスタックの情報が見られる。

pry/pry-stack_explorer · GitHub https://github.com/pry/pry-stack_explorer

  • refe2

refeコマンドラインからRubyリファレンスマニュアルを見ることができる。

refe2 | RubyGems.org | your community gem host https://rubygems.org/gems/refe2/versions/0.9.0

終わりに

Ruby初心者なので、Rubyで小規模な開発を行う時に便利なgemが他にあったら教えてほしいです。

vagrant up した時に共有フォルダのマウントでエラーが出る問題

問題

大分前から vagrant up した時に共有フォルダのマウントに時間がかかり下記のエラーが出ていた。

$ vagrant up
(中略)
==> web: Mounting shared folders...
    web: /vagrant => /Users/hoge/path/to/dir/project
Failed to mount folders in Linux guest. This is usually because
the "vboxsf" file system is not available. Please verify that
the guest additions are properly installed in the guest and
can work properly. The command attempted was:

mount -t vboxsf -o uid=`id -u vagrant`,gid=`getent group vagrant | cut -d: -f3` vagrant /vagrant
mount -t vboxsf -o uid=`id -u vagrant`,gid=`id -g vagrant` vagrant /vagrant

The error output from the last command was:

/sbin/mount.vboxsf: mounting failed with the error: No such device

エラーメッセージを雑に読むと、ゲストとホストで共有フォルダのマウントが上手くいってないようだ。

しかし、その後に普通に vagrant sshしたら接続はできるのでずっと放置していた。 放置していたが、さすがにそろそろ解決しようと思って色々と調べて解決した。

自分の環境

解決方法

まずはvagrantに接続しvboxのリビルドを試す。 以下はvagrant内でのコマンド操作。

$ sudo /etc/init.d/vboxadd setup
Removing existing VirtualBox non-DKMS kernel modules       [  OK  ]
Building the VirtualBox Guest Additions kernel modules
The headers for the current running kernel were not found. If the following
module compilation fails then this could be the reason.
The missing package can be probably installed with
yum install kernel-devel-2.6.32-504.el6.x86_64

Building the main Guest Additions module                   [失敗]
(Look at /var/log/vboxadd-install.log to find out what went wrong)
Doing non-kernel setup of the Guest Additions              [  OK  ]

Guest Additions の構築に失敗する。 メッセージ通り、 kernel-devel-2.6.32-504.el6.x86_64yum install してみる。

$ sudo yum install kernel-devel-2.6.32-504.el6.x86_64
読み込んだプラグイン:fastestmirror
インストール処理の設定をしています
Loading mirror speeds from cached hostfile
 * base: www.ftp.ne.jp
 * epel: ftp.kddilabs.jp
 * extras: www.ftp.ne.jp
 * remi-safe: remi.kazukioishi.net
 * updates: www.ftp.ne.jp
パッケージ kernel-devel.2.6 は利用できません。
エラー: 何もしません

そんなものは存在しない!

仕方がないので、 kernel-devel-2.6.32-504.el6.x86_64 をキーワードにググり、web上のrpmパッケージを拾ってきてインストールする。

ググったらヒットした RPM Scientific Linux 6 kernel-devel 2.6.32 x86_64 rpm の中から適当なリンクのrpmパッケージをインストールする。

$ sudo yum install ftp://mirror.switch.ch/pool/4/mirror/scientificlinux/6.6/x86_64/os/Packages/kernel-devel-2.6.32-504.el6.x86_64.rpm

インストール後にもう一度vboxのリビルドを行う。

$ sudo /etc/init.d/vboxadd setup
Removing existing VirtualBox non-DKMS kernel modules       [  OK  ]
Building the VirtualBox Guest Additions kernel modules
Building the main Guest Additions module                   [  OK  ]
Building the shared folder support module                  [  OK  ]
Building the OpenGL support module                         [  OK  ]
Doing non-kernel setup of the Guest Additions              [  OK  ]
Starting the VirtualBox Guest Additions                    [  OK  ]

今度は成功した。

その後、ホストに戻り、vagrant halt & vagrant up してもエラーが出ずにすぐに環境構築できるようになって解決した(Building the VirtualBox Guest Additions kernel modules にOKが出ていないのが気になるけど)。

Vimのカラースキームを設定できない問題

問題

VimのカラースキームをSolarizedに設定しようとして、.vimrcに以下のように書いて

NeoBundle 'altercation/vim-colors-solarized'
syntax enable
set background=dark
colorscheme solarized

何かファイルを開こうとすると、以下の Cannot find color scheme のエラーが出てカラースキームが設定されない。

$ vim .vimrc
Error detected while processing /Users/user/.vimrc:
line  100:
E185: Cannot find color scheme 'solarized'
Press ENTER or type command to continue

解決方法

Cannot find color scheme solarized · Issue #104 · altercation/vim-colors-solarized

によると、 colorscheme solarizedcall vundle#end() の後に書けとのこと。

というわけで、.vimrcを

·
·
·
NeoBundle 'altercation/vim-colors-solarized'
·
·
·
call neobundle#end()
·
·
·
syntax enable
set background=dark
colorscheme solarized

と書くようにしたら、エラーを解消してカラースキームの設定をすることができた。

ファイルの文字列をソートし直しててファイルに出力するRubyスクリプト

コマンドライン引数に指定されたファイルに書かれてある文字列をソートし直して1行ずつ新たなファイルに出力するRubyスクリプトを書いた。

ファイルの文字列をソートし直しててファイルに出力するRubyスクリプト

# -*- coding: utf-8 -*-

input_file = ARGV[0]
added_filename = '_in_line'

# 入力ファイルネームが'hoge.txt'なら出力ファイルネームは'hoge_in_line.txt'とする
output_file = File.basename(input_file, '.*') + added_filename + File.extname(input_file)

File.open input_file do |i_file|
  File.open output_file, 'w' do |o_file|
    o_file.puts i_file.read.split(/\s+/).sort
  end
end

こんなファイルを

aaa ddd
eee     ggg
       fff
    ccc hhh iii

bbb

以下のように出力し直す。

aaa
bbb
ccc
ddd
eee
fff
ggg
hhh
iii

動機として、 $ brew list で出力されたものを1行ずつ改行した形でファイルに出力したものが欲しかったので書いた。 ただ、すぐに $ brew list > hoge.txt とリダイレクトを使えば望むものが手に入ることが分かったので、今後は使うことはないと思う。

CentOSローカル開発環境構築用のAnsibleのplaybookを作った

概要

VagrantでCentOS6.6にGit,(私の)dotfiles,Zsh,Oh-My-Zsh,peco,tmux,Vim,Nginx,MySQL,rbenvをインストールしてローカル開発環境構築を自動化するAnsibleのplaybookを作った。

以下が作ったplaybook。

github.com

背景

Railsで遊ぶためにVagrantでローカル開発環境を構築しようと思ったけど、どうせなら環境構築を自動化したいと思い、構成管理ツールの中で興味があったAnsibleの勉強がてらVagrantCentOSのローカル開発環境構築用のAnsibleのplaybookを作った。Railsと言いながらrbenvのインストールまでの自動化になっている^^;

環境

実行

$ git clone git@github.com:shifumin/vagrant-ansible-centos.git
$ cd vagrant-ansible-centos
$ vagrant up

playbookの内容

CentOS6.6に

をインストールする。

各rolesの詳しい内容は以下のとおり。

yum_repo

yum_install

  • 必要そうなパッケージをインストール
  • Development Tools をグループインストール

Git

  • 依存パッケージのインストール
  • ソースコードからGitをダウンロードして解凍してインストール

dotfiles

Zsh

  • 依存パッケージのインストール
  • ソースコードからZshをダウンロードして解答してインストール
  • Oh-My-Zshのインストール
  • ログインシェルをzshに変更

peco

  • pecoのバイナリをダウンロードして解答して/usr/local/binにコピーする。

tmux

Vim

  • Vimパッケージ他のインストール

Nginx

  • Nginxパッケージをインストールする
  • ginxを起動し、自動起動の設定をonにする

MySQL

  • MySQLパッケージをインストールする
  • mysqldを起動し、自動起動の設定をonにする。

rbenv

  • 依存パッケージのインストール
  • rbenvのインストール
  • ruby-buildのインストール
  • rbenv-default-gemsのインストール
  • ~/dotfiles/default-gemsのシンボリックリンク張り
  • rbenv-updateのインストール
  • ソースコードからRSenseをダウンロードして解凍してインストール

ディレクトリ構成

vagrant-ansible-centos/
├── playbook/
│   ├── group_vars/
│   │   └── all.yml
│   ├── roles/
│   │   ├── dotfiles/
│   │   │   └── tasks/
│   │   │       └── main.yml
│   │   ├── git/
│   │   │   └── ...
│   │   ├── rbenv/
│   │   │   └── ...
│   │   ├── tmux/
│   │   │   └── ...
│   │   ├── vim/
│   │   │   └── ...
│   │   ├── yum_repo/
│   │   │   └── ...
│   │   ├── yum_update/
│   │   │   └── ...
│   │   └── zsh/
│   │   │   └── ...
│   ├── hosts
│   └── site.yml
├── Vagrantfile
└── ansible.cfg

基本的には、公式のベストプラクティスに沿った構成になっているはず。 メインのplaybookは playbook/site.yml 、inventoryファイルは playbook/hosts、変数の格納ファイルは playbook/group_vars/all.yml とした。

詰まったところ

全てがSSH関連でほとんどがgitモジュール関連。

SSH Error: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password)

問題

ansible-playbookしようとすると、初っ端に以下のエラーが出る。

fatal: [192.168.xx.xx] => SSH Error: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).
    while connecting to 192.168.42.30:22
It is sometimes useful to re-run the command using -vvvv, which prints SSH debug output to help diagnose the issue.

公開鍵が云々。

解決方法

原因はこれらしい。 ansible.cfgに private_key_file を付け加える。

[defaults]
private_key_file = .vagrant/machines/web/virtualbox/private_key

Warning: Permanently added the RSA host key for IP address '192.30.xx.xx' to the list of known hosts

問題

gitモジュールでgit cloneしようとすると、以下のエラーが出る。

failed: [192.168.xx.xx] => {"cmd": "/usr/local/bin/git ls-remote '' -h refs/heads/HEAD", "failed": true, "rc": 128}
stderr: Warning: Permanently added the RSA host key for IP address '192.30.xx.xx' to the list of known hosts.
Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

msg: Warning: Permanently added the RSA host key for IP address '192.30.xx.xx' to the list of known hosts.
Permission denied (publickey).
fatal: Could not read from remote repository.

known hostsにhostkeyが云々。

解決方法

Vagrant上に構築する仮想環境に秘密鍵を置かずにGithubとやり取りをするためにansible.cfgに ForwardAgent=yes を付け加える。

[ssh_connection]
ssh_args = -o ForwardAgent=yes

Failed to find required executable git

問題

同じく、gitモジュールでgit cloneしようとすると、以下のエラーが出る。

failed: [192.168.xx.xx] => {"failed": true}
msg: Failed to find required executable git

FATAL: all hosts have already failed -- aborting

gitのバイナリがない?って言われる。

解決方法

sudo時にgitへのPATHが通っていないからっぽい。 gitモジュールではsudoじゃなくてユーザで実行させるために、taskに sudo=no をつける。

---
- name: git clone dotfiles repository
  sudo: no
  git:
    repo=git@github.com:shifumin/dotfiles.git
    dest=/home/{{ user }}/dotfiles
    accept_hostkey=yes

github.com has an unknown hostkey

問題

さらに同じく、gitモジュールでgit cloneしようとすると、以下のエラーが出る。

failed: [192.168.xx.xx] => {"failed": true}
msg: github.com has an unknown hostkey. Set accept_hostkey to True or manually add the hostkey prior to running the git module

github.comに登録されてあるhostkeyが違う?ので、accept_hostkeyを有効にしろって言われる。

解決方法

playbookの一番最初に実行するgitモジュールのtaskに accept_hostkey=yes をつける。 初回のみでいいはず。

---
- name: git clone dotfiles repository
  sudo: no
  git:
    repo=git@github.com:shifumin/dotfiles.git
    dest=/home/{{ user }}/dotfiles
    accept_hostkey=yes

以下メモ

変数をどこに格納するか

変数をどこに書くかに大分迷ったけど、変数の使い分け等をしない場合は group_vars/all に書いておけば特に指定しなくても全rolesに適用されるようだ。 また、ファイル名をall.ymlとすることで、シンタックスハイライトを付けることができる(YAMLファイルにシンタックスハイライトを設定している場合)

したがって、変数は、 group_vars/all.yml に記述することにした。

ソースコードをダウンロードして解凍してmake installするやり方

他の人の方法を見ていたら色々なやり方・書き方があることが分かって、当初は全てをshellモジュールを使って一気通貫で処理させていた。 例えば以下のように記述していた。

- name: install tmux
  shell: |
    wget https://github.com/tmux/tmux/releases/download/{{ tmux_ver }}/tmux-{{ tmux_ver }}.tar.gz
    tar zxvf tmux-{{ tmux_ver }}.tar.gz
    rm -f tmux-{{ tmux_ver }}.tar.gz
    cd tmux-{{ tmux_ver }}
    ./configure
    make
    make install
  args:
    chdir: "{{ src_dir }}"

しかし、shellモジュールは冪等性が担保されずに初回以降も毎回実行されて (上手く条件分岐すれば回避できるだろうけど)スキップされないので、Ansible標準のモジュールを使いtaskを分けるようにした。

つまり、以下のように、get_urlモジュールでソースコードをダウンロードして、unarchiveモジュールで解凍して、最後のmake installだけをshellモジュールで処理するようにした。

---
- name: download tmux source
  get_url:
    url=https://github.com/tmux/tmux/releases/download/{{ tmux_ver }}/tmux-{{ tmux_ver }}.tar.gz
    dest="{{ src_dir }}/tmux-{{ tmux_ver }}.tar.gz"

- name: extract tmux source
  unarchive:
    src="{{ src_dir }}/tmux-{{ tmux_ver }}.tar.gz"
    dest="{{ src_dir }}"
    copy=no

- name: install tmux
  shell: >
    {{ item }}
    chdir="{{ src_dir }}/tmux-{{ tmux_ver }}"
    creates="{{ bin_dir }}/tmux"
  with_items:
    - ./configure
    - make
    - make install

get_urlモジュールはdestに既にファイルが存在する場合はスキップされ、unarchiveモジュールもdestのディレクトリに解凍後のファイルがあればスキップされるので冪等性は保たれる。そして、最後のmake installのshellモジュールはcreatesでインストールされていたらスキップするようにした。

YAML複数行にわたる書き方

上記の、ソースコードからmake installするshellモジュールの書き方を考えている時に、どうしたらきれいに書けるだろうと調べていたら、YAMLにはLiteral StyleとFolded Styleという書き方があることを知った。

Literal Style

Literal Styleはインジケータとして "|" を使う書き方で、

text: |
  hoge
  foo
  bar
"text" => "hoge\nfoo\nbar\n"

各行の改行が保存される。

Folded Style

そして、Folded Styleは、インジケータとして ">" を使う書き方で、

shell: >
  hoge
  foo
  bar
"text" => "hoge foo bar\n"

各行の改行が半角スペースに置換され、最終行の改行は保存される。

この2つを使えば、例えば、shellモジュールで./configureした後にmakeしてその後にmake installする処理は、

shell: |
  ./configure
  make
  make install

と書けるし、

./configure && make && make intallする処理を複数行に分けて書きたい時は、

shell: >
  ./configure &&
  make &&
  make install

と書くことができる。

詳しくは、

YAML Ain’t Markup Language (YAML™) Version 1.2

8.1.2. Literal Style8.1.3. Folded Style 辺りに書いてあった。

終わり

ゆくゆくはさくらVPSCentOS本番環境構築自動化に取り組みたい。

・・・の前にNginxとMySQLの初期設定の自動化にも取り組みたい。

参考

Best Practices — Ansible Documentation

Configuration file — Ansible Documentation

git - Deploy software (or files) from git checkouts — Ansible Documentation

YAML Ain’t Markup Language (YAML™) Version 1.2

Ansibleを使い出す前に押さえておきたかったディレクトリ構成のベストプラクティス - 双六工場日誌

Ansible で git clone させる - Qiita

Vagrant 1.7+でSSH接続エラーが出た場合の対処法 | mawatari.jp