準備中の Vagrant ボックスと、プロビジョニング ファイルとしてのシェル スクリプトがあります。私はそれを機能させるために数日を費やしましたが、今では安定して完全に見えます. ベース ボックスは Ubuntu 12.04 (32 ビット) で、VM で Postgres、Redis、および Memcached が実行されています。プロビジョニング スクリプトは、Nginx 構成をセットアップし、空のデータベースを作成し、いくつかの基本的なハウスキーピングを行います。
VM をパッケージ化し、自宅の別のマシンで再実行しようとしたとき、最初の実行で問題が発生し続け ( vagrant up
)、どのサービスも実行されていなかったため、実行しようとしdropdb
たりcreatedb
失敗したりしました.
なぜこれが起こったのかを掘り下げてみると (そして、私は元 Windows の人間なので、これにはある程度の作業が必要でした)、実行レベルと/etc/rc[0-6,S].d
ファイルの奥深くにいることに気づきました。
興味のある 3 つのサービスに関連する S (開始) ファイルがあります。
vagrant@precise32:~$ ls -l /etc/rc2.d
total 4
-rw-r--r-- 1 root root 677 Apr 14 2012 README
lrwxrwxrwx 1 root root 20 Dec 29 10:05 S19postgresql -> ../init.d/postgresql
lrwxrwxrwx 1 root root 19 Dec 29 10:05 S20memcached -> ../init.d/memcached
lrwxrwxrwx 1 root root 15 Dec 29 10:05 S20nginx -> ../init.d/nginx
lrwxrwxrwx 1 root root 22 Dec 29 10:05 S20redis-server -> ../init.d/redis-server
...
および実行レベル 0 (シャットダウン) の K 個のファイルなので、すべてが順番に表示されます。
vagrant@precise32:~$ ls -l /etc/rc0.d
total 4
lrwxrwxrwx 1 root root 19 Dec 29 10:05 K20memcached -> ../init.d/memcached
lrwxrwxrwx 1 root root 15 Dec 29 10:05 K20nginx -> ../init.d/nginx
lrwxrwxrwx 1 root root 22 Dec 29 10:05 K20redis-server -> ../init.d/redis-server
lrwxrwxrwx 1 root root 20 Dec 29 10:05 K21postgresql -> ../init.d/postgresql
....
これは、基盤となる VM ランレベルが 2 ではないことを示唆しているように思われたため、この問題をデバッグするために、a.) プロビジョニング時のランレベル、および b.) 予想されるプロセスが実行されていました (memcache、prostgres、redis):
ps aux | grep memcache
ps aux | grep postgres
ps aux | grep redis
# expected output is 'N 2'
runlevel
を実行しvagrant destroy
、次にvagrant up
これを実行した結果は次のとおりです。
[default] Running provisioner: Vagrant::Provisioners::Shell...
root 791 0.0 0.2 4624 840 ? S 10:33 0:00 grep memcache
root 793 0.0 0.2 4624 836 ? S 10:33 0:00 grep postgres
root 795 0.0 0.2 4624 840 ? S 10:33 0:00 grep redis
unknown
つまり、プロビジョニング スクリプトの実行時にはサービスが実行されておらず、さらに紛らわしいことに、runlevel
コマンドは認識されません。
その後、実行中の VM で を使用してプロビジョニング スクリプトを繰り返し再実行するvagrant provision
と、最初の数回は同じ結果が得られ、最終的に (2 ~ 3 分後) 最初に期待していたことがわかります。
[default] Running provisioner: Vagrant::Provisioners::Shell...
memcache 1103 0.2 0.2 46336 1072 ? Sl 10:56 0:00 /usr/bin/memcached -m 64 -p 11211 -u memcache -l 127.0.0.1
root 1267 0.0 0.2 4624 840 ? S 10:56 0:00 grep memcache
postgres 1073 13.0 2.0 50440 7828 ? S 10:56 0:02 /usr/lib/postgresql/9.1/bin/postgres -D /var/lib/postgresql/9.1/main -c config_file=/etc/postgresql/9.1/main/postgresql.conf
postgres 1077 0.3 0.3 50440 1248 ? Ss 10:56 0:00 postgres: writer process
postgres 1078 0.3 0.3 50440 1244 ? Ss 10:56 0:00 postgres: wal writer process
postgres 1079 0.1 0.6 50860 2296 ? Ss 10:56 0:00 postgres: autovacuum launcher process
postgres 1080 0.0 0.3 20640 1284 ? Ss 10:56 0:00 postgres: stats collector process
root 1269 0.0 0.2 4624 836 ? S 10:56 0:00 grep postgres
redis 1123 0.6 0.2 3292 1036 ? Ss 10:56 0:00 /usr/bin/redis-server /etc/redis/redis.conf
root 1271 0.0 0.2 4624 840 ? S 10:56 0:00 grep redis
N 2
すべてが立ち上がるまでに少し時間がかかっているようですが、これは理にかなっていますが、プロビジョニングスクリプトが最初は常に失敗するという大きな問題があります.
これは既知の状況ですか? もしそうなら、解決策は何ですか? 理想的には、プロビジョニング スクリプトは、ランレベルが 2 に変更されるまで一時停止します。つまり、ボックスがシェル コマンドを受け入れる準備が整うまでです。
[更新: ハック]
次のスクリプトを一緒にハッキングすることで、この問題を回避することができました。
while [ "`runlevel`" = "unknown" ]; do
echo "runlevel is 'unknown' - waiting for 10s"
sleep 10
done
echo "runlevel is now valid ('`runlevel`'), kicking off provisioning..."
これを「pre-provision.sh」として保存すると、Vagrantfile は次のようになります。
# Enable provisioning with a shell script.
config.vm.provision :shell, :path => "pre-provision.sh"
config.vm.provision :shell, :path => "provision.sh", :args => "myapp"
次の出力が得られます。
[default] Running provisioner: Vagrant::Provisioners::Shell...
runlevel is 'unknown' - waiting for 10s
runlevel is 'unknown' - waiting for 10s
runlevel is 'unknown' - waiting for 10s
runlevel is 'unknown' - waiting for 10s
runlevel is 'unknown' - waiting for 10s
runlevel is 'unknown' - waiting for 10s
runlevel is 'unknown' - waiting for 10s
runlevel is 'unknown' - waiting for 10s
runlevel is 'unknown' - waiting for 10s
runlevel is 'unknown' - waiting for 10s
runlevel is 'unknown' - waiting for 10s
runlevel is now valid ('N 2'), kicking off provisioning...
[default] Running provisioner: Vagrant::Provisioners::Shell...
...
その後、オリジナルprovision.sh
が実行され、すべて問題ありません。
私はまだ何をすべきか知りたいので、これを答えとしてマークしていません(答えですが)-これは確かに機能する方法ではありませんか?