読者です 読者をやめる 読者になる 読者になる

文系プログラマによるTIPSブログ

文系プログラマ脳の私が開発現場で学んだ事やプログラミングのTIPSをまとめています。

.bash_profileはフラグメント化してプロビジョニングしやすくしよう!

ansible シェルスクリプト

プロビジョニング時に .bash_profile にパスをechoで追記するような処理、もうやめませんか?ちゃんとファイルで管理するためにフラグメント化しちゃいましょう。
f:id:treeapps:20160219001058p:plain

いままでの .bash_profile

# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
	. ~/.bashrc
fi

# User specific environment and startup programs
export PATH="$HOME/.rbenv/bin:$PATH
eval "$(rbenv init -)"'

PATH=$PATH:$HOME/.local/bin:$HOME/bin

export PATH

これはダサい、ダサすぎる。そしてプロビジョナに厳しすぎる。まるで骨付き肉を持った原始人を見ているようだ。

他にも、例えばプロビジョニング時に以下のようなコードを書いちゃう人はイケてません。骨付き肉です。

$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile

フラグメント化した .bash_profile

.bash_profile

まず、こうします。

# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
	. ~/.bashrc
fi

# load bash flagment
if [ -d "${HOME}/.bash.d" ] ; then
    for f in "${HOME}"/.bash.d/*.sh ; do
        [ -x "$f" ] && . "$f"
    done
    unset f
fi

PATH=$PATH:$HOME/.local/bin:$HOME/bin

export PATH

「# load bash flagment」の部分に注目。「.bash.d」というフォルダの中で拡張子が「.sh」のものをループし、実行権限が付いているものを逐次読み込んでいくのです。

以下のように「.bash.d」フォルダを作成し、XXX_名称.sh を配置します。XXXは0パディングした数値を適当に指定します。

[vagrant@node1 ~]$ ll -R .bash*
-rw------- 1 vagrant vagrant  94  522 00:21 .bash_history
-rw-r--r-- 1 vagrant vagrant  18  36 07:06 .bash_logout
-rw-r--r-- 1 vagrant vagrant 345  521 01:54 .bash_profile
-rw-r--r-- 1 vagrant vagrant 231  36 07:06 .bashrc

.bash.d:
合計 4
-rwxr--r-- 1 vagrant vagrant 59  521 01:56 200_rbenv.sh
フラグメントファイル

「200_rbenv.sh」の中身はこうです。よく見る初期化コマンドをファイル化しただけです。

[vagrant@node1 ~]$ cat .bash.d/200_rbenv.sh
export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"

なんでこれがいいの?

例えばrbenvとpyenvの両方のパスと初期化をしたい場合、従来のやり方だとechoでがんばってリダイレクトして追記していく苦行を甘んじるしかありません。

export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"

export PATH="$HOME/.pyenv/bin:$PATH"
eval "$(pyenv init -)"

もしrbenv、pyenvのインストール前に.bash_profileに事前にこう書いてしまうと、インストール前に eval が実行されてしまい、「そんなコマンドまだインストールされてないんですけど!?なんなんですのあなたは???」と怒られてしまいます。

ここでフラグメントの出番です。

200_rbenv.sh
200_pyenv.sh

と用意しておき、rbenvのインストール中にrbenvのフラグメントファイルを配置、pyenvのインストール中にpythonのフラグメントファイルを配置、とすると、echoでゴリゴリしなくてよくなり、バージョン管理も簡単になり、プロビジョナ側もファイルをコピーするだけで済み、いいことづくめなのです。

ちなみにフラグメントのプレフィックスを数値にしたのは、ファイル名によって読み込む順をコントロールするためです。

もし一時的に読み込まさせたくなくなった場合は、「chmod -x」で実行権限を外すだけでOKなのです。

雑感

最近Githubのunusableの色々な人のplaybookを眺めていて、こういうフラグメントが利用される場面が多いので、これは今後必須になるだろうなあ、というかやらないとechoがくっそしんどいなあ、という感じです。

UNIXシェルスクリプトコマンドブック 第3版 (コマンドブックシリーズ)

UNIXシェルスクリプトコマンドブック 第3版 (コマンドブックシリーズ)

シェルプログラミング実用テクニック (Software Design plus)

シェルプログラミング実用テクニック (Software Design plus)

フルスクラッチから1日でCMSを作る シェルスクリプト高速開発手法入門

フルスクラッチから1日でCMSを作る シェルスクリプト高速開発手法入門