linux - Vagrant 配置脚本在 VM 完全启动之前运行?

标签 linux ubuntu vagrant

我正在准备一个 Vagrant box,以及一个 shell 脚本作为配置文件。我花了几天时间让它工作,现在看起来稳定而完整。基本系统是 Ubuntu 12.04(32 位),在虚拟机上运行 Postgres、Redis 和 Memcached。配置脚本设置 Nginx 配置,创建一个空白数据库,并执行一些基本的内务处理。

当我开始打包 VM,并尝试在家里的另一台机器上重新运行它时,我在第一次运行时一直遇到问题 (vagrant up)服务正在运行 - 所以我尝试运行 dropdbcreatedb 失败。

深入了解为什么会发生这种情况(我是一个前 Windows 用户,所以这需要做一些工作)我发现自己处于运行级别和 /etc/rc[0-6,S .d 文件。

我有我感兴趣的三个服务的相关 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 命令。

如果我随后使用 vagrant provision 在正在运行的 VM 上重复重新运行配置脚本,我会在前几次运行它时得到相同的结果,然后最终(在 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,即盒子已准备好接受 shell 命令。

[更新:破解]

我已经通过破解以下脚本设法解决了这个问题:

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,一切OK。

我没有将此标记为答案(虽然它是一个答案)因为我仍然想知道我应该做什么 - 这肯定不是它的工作方式吧?

最佳答案

事实证明,最简单的方法是查找相关进程的 PID 文件(有关 pid 文件的解释,请参阅本文 - What is a .pid file and what does it contain?)

NGINX_PID=/var/run/nginx.pid

...

## set up nginx configuration using .config from shared directory
if [ ! -f $NGINX_PID ]; then
    echo "---> Waiting for for Nginx process to spin up"
    while [ ! -f $NGINX_PID ]; do
        echo .
        sleep 1
    done
fi

关于linux - Vagrant 配置脚本在 VM 完全启动之前运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14100797/

相关文章:

c - 高性能阅读 - linux/pthreads

ubuntu - Ansible 无法找到 requirements.txt

laravel - Laravel Homestead 安装上的 403 禁止 nginx/1.6.2

mysql - CentOS 6.5 mysql 使用大量内存

linux - 如何重命名两个文件 - 第一个到第二个和相反

linux - Linux 下批量音乐目录重命名脚本/命令 (bash)

linux - 删除 linux 目录中的所有文件夹和文件,除了一个文件夹和该文件夹中的所有内容

ubuntu - R 3.6.1; Ubuntu,尝试更新 Bioconductor 的包并出现错误 : . ... 安装路径不可写,无法更新包

linux - Control + F4 在 ubuntu 16.04 中不起作用

c# - 在 Ubuntu 环境中使用 MonoDevelop 将 C# 代码交叉编译为 Colibri iMX6 (Linux) exe