让 Vagrant 共享目录支持文件事件通知

在使用 Vagrant 的过程中发现了一个问题:对于使用 config.vm.synced_folder 进行配置的共享文件夹,如果在 Host 系统(本地环境)中修改了其路径下的文件,在 Guest 系统(虚拟机环境)中是无法通过 inotifywait 接收到文件系统事件的。

而通常情况下,Vagrant 的共享目录是用来存放源代码的。我们会在 Host 系统中编辑源代码,在 Guest 系统中运行它们。如果 Guest 系统无法监控源代码目录的变化,就无法实现源代码的自动编译和热加载。

解决方案

经过搜索,发现了一个叫 vagrant-fsnotify 的 Vagrant 插件,可以用来解决上述问题。

插件的原理是,在 Host 系统中运行一个进程监听文件系统事件,当文件发生变化时,访问 Guest 系统中对应的文件,来触发 Guest 系统中的文件系统事件。

安装

shellvagrant plugin install vagrant-fsnotify

配置

修改 Vagrantfile 中同步文件夹配置,添加 fsnotify: true 选项:

rubyconfig.vm.synced_folder ".", "/vagrant", fsnotify: true

当 Guest 系统启动后,手动运行监听命令:

shellvagrant fsnotify

或者修改 Vagrantfile 下面的代码来自动运行监听命令:

rubyconfig.trigger.after :up, :reload do |trigger|
    trigger.name = "vagrant-fsnotify"
    trigger.run = { inline: "vagrant fsnotify" }
end

使用

在 Guest 系统中使用如下脚本来监控当前目录下 *.scss 文件的变化:

bash#!/bin/bash

inotifywait -q -m -r -e close_write,delete ./ |
    while read path action file; do
        if [[ "$file" = *.scss ]] ; then
            echo "$1"
            # do something
        fi
    done