Vagrantfile の Shell プロビジョンで anyenv のインストールなど `exec $SHELL -l` するような処理を書くとき


# 結論

`exec $SHELL -l` の代わりに、 `. ~/.bash_profile` とか `. ~/.bashrc` を適宜やろう。

## `. <FilePath>` ってなんぞ
`.` （ドット1文字）っていうコマンドがあります。
bash の場合は、 [`source`のエイリアス](http://linuxjm.osdn.jp/html/GNU_bash/man1/bash.1.html#lbDB)です。

# 
Vagrant を使う際に、 [Shell Provision](https://www.vagrantup.com/docs/provisioning/shell.html) で、 `exec $SHELL -l` したいときありますよね。 「[anyenv](https://github.com/riywo/anyenv) を使って Node.js とかインストールしたい」とか「dotfiles をインストールして、それを読み込んだ前提で何か書きたい」っていうときです。  
~~でも、 各種Provision のなかで `exec $SHELL -l` しても、 .bash_profile とかの更新分は、反映されません。~~ `exec $SHELL` したところで、その分の Shell プロビジョンが終了します。

## `exec $SHELL -l` との違い
`exec $SHELL -l` は、現在のログインシェルを再起動する に近いです。（解説は[『シェルを再起動させる簡単な方法』](http://qiita.com/yusabana/items/c4de582c6f85a42817d8)とか読むといいです。）
それに対して、 `source` は、読み込むファイルを明示しなければいけないので、シェルの起動プロセスとかを把握してないと使えないです。

* 使用する shell に応じて、 `source` するファイルを変える
* /etc/profile.d に追加するとかの場合は、そっちを `source` する

## Shell プロビジョンが終了することの確認
以下のようなファイルを準備して、検証しました。
要するに、 **Shell プロビジョン内で `exec $SHELL` はしてはいけない** っぽいです。

```ruby:Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.box = "centos/7"
  # PID 確認
  config.vm.provision :shell, inline: 'ps -f | egrep "$$|PID"'
  config.vm.provision :shell, inline: 'ps -f | egrep "$$|PID"'
  # anyenv で git 使う
  config.vm.provision :shell, inline: "yum -y -q install git"
  config.vm.provision :shell, "privileged": false, path: "./anyenv.sh"
  ###
  config.vm.provision :shell, "privileged": false, path: "./nodenv.sh"
end
```

```bash:anyenv.sh
echo anyenv.sh
echo tick1
git clone https://github.com/riywo/anyenv ~/.anyenv
echo tick2
echo 'export PATH="$HOME/.anyenv/bin:$PATH"' >> ~/.bash_profile
echo tick3
echo 'eval "$(anyenv init -)"' >> ~/.bash_profile
echo tick4
exec $SHELL -l
echo tick5
exec $SHELL
echo tick6
anyenv install nodenv
echo tick7
exec $SHELL -l
echo tick8
exec $SHELL
echo tick9

```

```bash:nodenv.sh
echo nodenv.sh
echo tick101
anyenv install nodenv
echo tick102
exec $SHELL -l
echo tick103
exec $SHELL
echo tick104
nodenv install 6.9.5
echo tick105
```


出力結果

```
C:\tmp\vm>vagrant destroy -f && vagrant up
==> default: Forcing shutdown of VM...
==> default: Destroying VM and associated drives...
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'centos/7'...
==> default: Matching MAC address for NAT networking...
==> default: Checking if box 'centos/7' is up to date...
==> default: Setting the name of the VM: vm_default_1489040647386_94904
==> default: Fixed port collision for 22 => 2222. Now on port 2200.
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
==> default: Forwarding ports...
    default: 22 (guest) => 2200 (host) (adapter 1)
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2200
    default: SSH username: vagrant
    default: SSH auth method: private key
    default:
    default: Vagrant insecure key detected. Vagrant will automatically replace
    default: this with a newly generated keypair for better security.
    default:
    default: Inserting generated public key within guest...
    default: Removing insecure key from the guest if it's present...
    default: Key inserted! Disconnecting and reconnecting using new SSH key...
==> default: Machine booted and ready!
==> default: Checking for guest additions in VM...
    default: No guest additions were detected on the base box for this VM! Guest
    default: additions are required for forwarded ports, shared folders, host only
    default: networking, and more. If SSH fails on this machine, please install
    default: the guest additions and repackage the box to continue.
    default:
    default: This is not an error message; everything may continue to work properly,
    default: in which case you may ignore this message.
==> default: Rsyncing folder: /cygdrive/c/tmp/vm/ => /vagrant
==> default: Running provisioner: shell...
    default: Running: inline script
==> default: UID        PID  PPID  C STIME TTY          TIME CMD
==> default: root     10106 10097  0 06:24 ?        00:00:00 bash -l
==> default: root     10107 10106  0 06:24 ?        00:00:00 ps -f
==> default: root     10108 10106  0 06:24 ?        00:00:00 grep -E 10106|PID
==> default: Running provisioner: shell...
    default: Running: inline script
==> default: UID        PID  PPID  C STIME TTY          TIME CMD
==> default: root     10181 10172  0 06:24 ?        00:00:00 bash -l
==> default: root     10182 10181  0 06:24 ?        00:00:00 ps -f
==> default: root     10183 10181  0 06:24 ?        00:00:00 bash -l
==> default: Running provisioner: shell...
    default: Running: inline script
==> default: Public key for perl-Carp-1.26-244.el7.noarch.rpm is not installed
==> default: warning: /var/cache/yum/x86_64/7/base/packages/perl-Carp-1.26-244.el7.noarch.rpm: Header V3 RSA/SHA256 Sign
ature, key ID f4a80eb5: NOKEY
==> default: Importing GPG key 0xF4A80EB5:
==> default:  Userid     : "CentOS-7 Key (CentOS 7 Official Signing Key) <security@centos.org>"
==> default:  Fingerprint: 6341 ab27 53d7 8a78 a7c2 7bb1 24c6 a8a7 f4a8 0eb5
==> default:  Package    : centos-release-7-3.1611.el7.centos.x86_64 (@anaconda)
==> default:  From       : /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
==> default: Running provisioner: shell...
    default: Running: C:/Users/XXXXXX~1/AppData/Local/Temp/vagrant-shell20170309-8564-1mmitjh.sh
==> default: anyenv.sh
==> default: tick1
==> default: Cloning into '/home/vagrant/.anyenv'...
==> default: tick2
==> default: tick3
==> default: tick4
==> default: Running provisioner: shell...
    default: Running: C:/Users/XXXXXX~1/AppData/Local/Temp/vagrant-shell20170309-8564-1dbhwan.sh
==> default: nodenv.sh
==> default: tick101
==> default: /tmp/nodenv.20170309062507.11853 ~
==> default: Cloning https://github.com/nodenv/nodenv.git...
==> default: Cloning into 'nodenv'...
==> default: ~
==> default: ~/.anyenv/envs/nodenv/plugins ~
==> default: Cloning https://github.com/nodenv/node-build.git...
==> default: Cloning into 'node-build'...
==> default: ~
==> default: ~/.anyenv/envs/nodenv/plugins ~
==> default: Cloning https://github.com/nodenv/nodenv-default-packages.git...
==> default: Cloning into 'nodenv-default-packages'...
==> default: ~
==> default: ~/.anyenv/envs/nodenv/plugins ~
==> default: Cloning https://github.com/nodenv/nodenv-vars.git...
==> default: Cloning into 'nodenv-vars'...
==> default: ~
==> default:
==> default: Install nodenv succeeded!
==> default: Please reload your profile (exec $SHELL -l) or open a new session.
==> default: tick102

```