Vagranfile でローカル実行
vagrant up
時、つまり Vagrantfile1 の実行時にホスト OS 側のセットアップをしたい場合、Ruby の system
モジュール関数を使ってシェル・コマンドを実行できます。
しかし、コマンドごとに system
関数を使うのが冗長だったので簡素にしたいのです。
# Script to run on Host OS (冗長な書き方。可読性がいささか悪い)
system('rm -rf hello-world > /dev/null 2>&1')
system('echo "Hello world!" > hello-world')
# Script to run on Guest OS (可能なら、上記を下のように描きたい)
$script_guest = <<-'SCRIPT'
cat /vagrant/hello-world && \
mv /vagrant/hello-world /vagrant/hello-world.done
SCRIPT
Vagrant.configure("2") do |config|
config.vm.box = "KEINOS/macOS.10.14.1_Japanese"
config.vm.network :private_network, ip: "192.168.1.100"
config.vm.synced_folder ".", "/vagrant", type: "nfs"
config.vm.provision "shell", inline: $script_guest, privileged: false, run: "always"
config.vm.provider "virtualbox" do |vb|
(...略...)
end
end
他の言語同様にヒアドキュメントを使うのが定石だと思うのですが、変数に代入してからでなく、直接 system
関数の引数にヒアドキュメントで複数行渡したいのです。
TL; DR (今北産業)
Ruby で system 関数の引数にヒアドキュメントで複数行コマンドを渡す
system(<<~'EOD')
rm -rf hello-world > /dev/null 2>&1
echo "Hello world!" > hello-world
EOD
- 参考文献
- 「Ruby|複数のヒアドキュメントをメソッドの引数にする」@ Qiita
- 当記事のコメント by @scivola
TS; DR ヒアドキュメントに悩んだコマケーこと
Vagrantfile って Ruby だもの
最初は、Bash や PHP などの感覚で以下のようにしていました。
system(<<-'EOD'
rm -rf hello-world > /dev/null 2>&1
echo "Hello world!" > hello-world
EOD
)
直感で書いたのですが動いたので、これで良いと言えば良いのですが、そもそも Ruby はよくわかりません。
いささか気持ちが悪かったので、ちょっと調べてみたところ、Qiita 記事のコメントから、以下のように書けることを知りました。
system(<<-'EOD')
rm -rf hello-world > /dev/null 2>&1
echo "Hello world!" > hello-world
EOD
変数の場合のヒアドキュメントに近い状態になり、スッキリしました。PHP などのヒアドキュメントと違うんですね。面白い。
また、この記事のコメントにもいただいたように、ヒアドキュメント内の行頭のインデントを削除してくれる記法もありました。<<-
を <<~
(ハイフンをチルダ)にすると余計なインデントを削除してくれます。便利。
system(<<~'EOD')
# remove old file
rm -rf hello-world > /dev/null 2>&1
# create new file
echo "Hello world!" > hello-world
EOD
上記は以下の文字列として system
に渡されます。一番浅いインデントを基準に行頭がトリムされます。
# remove old file
rm -rf hello-world > /dev/null 2>&1
# create new file
echo "Hello world!" > hello-world
最終的には以下のようになりました。
# Script to run on Host OS
system(<<~'SCRIPT')
rm -rf hello-world > /dev/null 2>&1
echo "Hello world!" > hello-world
SCRIPT
# Script to run on Guest OS
$script_guest = <<~'SCRIPT'
cat /vagrant/hello-world && \
mv /vagrant/hello-world /vagrant/hello-world.done
SCRIPT
Vagrant.configure("2") do |config|
config.vm.box = "KEINOS/macOS.10.14.1_Japanese"
config.vm.network :private_network, ip: "192.168.1.100"
config.vm.synced_folder ".", "/vagrant", type: "nfs"
config.vm.provision "shell", inline: $script_guest, privileged: false, run: "always"
config.vm.provider "virtualbox" do |vb|
(...略...)
end
end
参考文献
- 「Ruby|複数のヒアドキュメントをメソッドの引数にする」@ Qiita
- 「Rubyのヒアドキュメントの書き方いろいろ」@ blog.toshimaru.net
- 「Ruby におけるヒアドキュメント(行指向文字列リテラル)の基本的な仕様」@ Qiita