【问题标题】:How to run nginx.service after /vagrant is mounted/vagrant 挂载后如何运行 nginx.service
【发布时间】:2016-06-19 17:10:30
【问题描述】:

我想做什么?

我正在尝试通过 vagrant 自动挂载 /vagrant 进行 nginx 加载配置。

所以我编辑了 nginx.service 使其在共享文件夹挂载后启动,但它不起作用。

当然,nginx 已经在 virtualbox-guest-utils.service 之后启动,但是,它似乎在 vagrant.mount (/vagrant) 之前启动。 因为 nginx 无法从 /vagrant 加载配置,并且手动运行命令 systemctl restart nginx.service 后它可以工作。

自动生成的 .mount 单元启动后如何运行 .service 单元?

环境

  • 流浪者 1.8.1
  • Ubuntu 服务器 15.10 (ubuntu/wily64)
  • VirtualBox 5.0.14

systemctl cat nginx.service

模式 1:无效

# /lib/systemd/system/nginx.service
# Stop dance for nginx
# =======================
#
# ExecStop sends SIGSTOP (graceful stop) to the nginx process.
# If, after 5s (--retry QUIT/5) nginx is still running, systemd takes control
# and sends SIGTERM (fast shutdown) to the main process.
# After another 5s (TimeoutStopSec=5), and if nginx is alive, systemd sends
# SIGKILL to all the remaining processes in the process group (KillMode=mixed).
#
# nginx signals reference doc:
# http://nginx.org/en/docs/control.html
#
[Unit]
Description=A high performance web server and a reverse proxy server
After=network.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;'
ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;'
ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload
ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid
TimeoutStopSec=5
KillMode=mixed

[Install]
WantedBy=multi-user.target

# /etc/systemd/system/nginx.service.d/override.conf
[Unit]
Requires=virtualbox-guest-utils.service vagrant.mount
After=virtualbox-guest-utils.service vagrant.mount

模式 2:不工作

# /lib/systemd/system/nginx.service
# Stop dance for nginx
# =======================
#
# ExecStop sends SIGSTOP (graceful stop) to the nginx process.
# If, after 5s (--retry QUIT/5) nginx is still running, systemd takes control
# and sends SIGTERM (fast shutdown) to the main process.
# After another 5s (TimeoutStopSec=5), and if nginx is alive, systemd sends
# SIGKILL to all the remaining processes in the process group (KillMode=mixed).
#
# nginx signals reference doc:
# http://nginx.org/en/docs/control.html
#
[Unit]
Description=A high performance web server and a reverse proxy server
After=network.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;'
ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;'
ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload
ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid
TimeoutStopSec=5
KillMode=mixed

[Install]
WantedBy=multi-user.target

# /etc/systemd/system/nginx.service.d/override.conf
[Unit]
RequiresMountsFor=/vagrant

【问题讨论】:

    标签: ubuntu vagrant systemd


    【解决方案1】:

    使用 mount.target 单元似乎可以工作。

    流浪文件:

    # -*- mode: ruby -*-
    # vi: set ft=ruby :
    
    Vagrant.configure("2") do |config|
      config.vm.box = "ubuntu/wily64"
      config.vm.provision :shell, path: "bootstrap.sh"
    
      # Disabling mounting of the /vagrant directory to make sure ngnix is blocked
      # Comment this out to allow the shared folder
      config.vm.synced_folder ".", "/vagrant", disabled: true
    end
    

    bootstrap.sh:

    #!/usr/bin/env bash
    
    apt-get update
    apt-get install -y nginx
    
    # Make vagrant.mount loosely dependent on nginx.service
    sed -i 's/WantedBy=multi-user.target/WantedBy=vagrant.mount/' /lib/systemd/system/nginx.service
    systemctl daemon-reload
    
    # Update service symlinks
    systemctl disable nginx.service
    systemctl enable nginx.service
    

    通过运行vagrant reload 进行测试,以使虚拟机在没有安装 /vagrant 目录的情况下启动。登录虚拟机,发现 nginx 没有运行:

    vagrant@vagrant-ubuntu-wily-64:~$ sudo systemctl status nginx.service 
    ● nginx.service - A high performance web server and a reverse proxy server
       Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
       Active: inactive (dead)
    

    然后注释掉禁用共享文件夹和vagrant reload 的 Vagrantfile 行。再次登录VM,看到nginx正在运行:

    vagrant@vagrant-ubuntu-wily-64:~$ systemctl status nginx.service 
    ● nginx.service - A high performance web server and a reverse proxy server
      Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
      Active: active (running) since Mon 2016-07-25 04:28:00 UTC; 42s ago
     Process: 1152 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
     Process: 1146 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
    Main PID: 1156 (nginx)
      Memory: 7.4M
         CPU: 17ms
      CGroup: /system.slice/nginx.service
              ├─1156 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
          └─1157 nginx: worker process
    

    【讨论】:

    • 我已经对此进行了测试,可以确认这是正确的答案。当您在 [Install] 部分中有 WantedBy=vagrant.mount 然后 disableenable 该服务将在下次启动时正常启动。
    • 您不需要先禁用 NFS 挂载。否则,这应该是公认的答案。无需“破解”。
    • 也适合我。从语义上讲,它确实感觉像是一个 hack,因为 WantedBy 依赖关系是错误的。我尝试了各种其他解决方案(RequiresRequiresMountsForAfter 以及这些解决方案的组合),但它们都不起作用,因为 systemd 忽略了不存在的依赖项(还),如日志消息所示“无法为单元 xxx.service 添加依赖项作业,忽略:单元 vagrant.mount 无法加载:没有这样的文件或目录”。
    • 请勿编辑 /lib/systemd/system 中的 nginx.service 文件,因为此文件可能会被包更新覆盖。将文件复制到etc/systemd/system,然后在那里进行编辑。此路径用于管理目的。并且位于那里的所有systemd 单元都以更高的优先级加载。进一步注意,名称vagrant.mount 取决于安装的路径。如果您挂载vagrant/somefolder,您的挂载名称为vagrant-somefolder.mount
    • 这可能会使它们并行出现...可能足够接近但感觉很奇怪...另请参阅stackoverflow.com/questions/43001223/…
    【解决方案2】:

    编辑/lib/systemd/system/nginx.service 并在Install 部分下更改WantedBy 指令...

    WantedBy=vagrant.mount
    

    您可以通过systemctl list-units vagrant.mount 检查vagrant.mount 事件是否存在。你应该看到这个:

    UNIT          LOAD   ACTIVE SUB     DESCRIPTION
    vagrant.mount loaded active mounted /vagrant
    
    LOAD   = Reflects whether the unit definition was properly loaded.
    ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
    SUB    = The low-level unit activation state, values depend on unit type.
    
    1 loaded units listed. Pass --all to see loaded but inactive units, too.
    To show all installed unit files use 'systemctl list-unit-files'.
    

    【讨论】:

    • 请勿编辑 /lib/systemd/system 中的 nginx.service 文件,因为此文件可能会被包更新覆盖。将文件复制到etc/systemd/system,然后在那里进行编辑。此路径用于管理目的。并且所有位于那里的systemd 单元都以更高的优先级加载。进一步注意,名称vagrant.mount 取决于安装的路径。如果你挂载vagrant/somefolder,你的挂载名为vagrant-somefolder.mount
    • 完全同意这个评论,改变这个文件是一个很大的禁忌,就像你不会跳进 c:\windows\system32.. 并编辑一些东西(显示我的年龄?)
    【解决方案3】:

    根据 Ansible 总结以前的答案和 cmets(如果用于提供):

    - name: Copy Nginx Systemd unit to /etc/
      copy:
        src: /lib/systemd/system/nginx.service
        dest: /etc/systemd/system/nginx.service
        remote_src: yes
    
    - name: Change Nginx Systemd unit
      lineinfile:
        path: /etc/systemd/system/nginx.service
        regexp: '^WantedBy='
        line: 'WantedBy={{ vagrant_mount_unit }}'
        state: present
    
    - name: Systemd daemon reload
      systemd:
        daemon_reload: yes
    
    - name: Disable Nginx
      service:
        name: nginx
        enabled: no
    
    - name: Enable Nginx
      service:
        name: nginx
        enabled: yes
    

    用 Vagrant 挂载单元名称替换 {{ vagrant_mount_unit }}。它取决于挂载点,例如如果挂载点为/home/vagrant/app,则单元名称为home-vagrant-app.mount

    【讨论】:

      【解决方案4】:

      我写了一个post how I'm using udev event to restart nginx and php5-fpm

      简而言之,我将使用规则添加/etc/udev/rules.d/50-vagrant-mount.rules

      SUBSYSTEM=="bdi",ACTION=="add",RUN+="/bin/bash /root/.udev-mount-restart-services.sh"
      

      而脚本/root/.udev-mount-restart-services.sh是:

      sleep 5 # wait for a bit for NFS to make sure resources are available
      systemctl restart php5-fpm > /dev/null 2>&1
      systemctl restart nginx > /dev/null 2>&1
      

      【讨论】:

      • 谢谢!不错的黑客。但是,为什么.mountRequiresMountsFor 不起作用?
      • vagrant.mountRequiresMountsFor 模式也不适用于 Debian 8 客户机。
      • 当您将WantedBy 更改为vagrant.mount 时,您必须再次启用该服务才能正常工作。
      • 无需编辑 udev 规则。请参阅下面@jacob-wan 的答案以获得更清洁的解决方案。
      【解决方案5】:

      我想在这里放弃我自己的答案,因为似乎每个答案都有正确答案的一部分,并且一些细节只能在 cmets 中找到。

      在本例中,我在 /var/www/mymount1 和 /var/www/mymount2 中有 2 个文件系统挂载

      我的 Vagrantfile 的这一部分:

      config.vm.provision "shell", path: "docs/vagrant/init-vagrant.sh"
      config.vm.synced_folder "mymount1", "/var/www/mymount1", type: "nfs"
      config.vm.synced_folder "mymount2", "/var/www/mymount2", type: "nfs"
      

      我将下面的脚本放在 /docs/vagrant/init-vagrant.sh 作为我的配置文件。

      # Copy nginx systemd script and make edits in /etc/systemd/system, as updates might change the original in /lib/systemd/system/nginx.service
      cp /lib/systemd/system/nginx.service /etc/systemd/system/
      # These tell that nginx should not be started before file system mounts are available
      echo WantedBy=var-www-mymount1.mount >> /etc/systemd/system/nginx.service
      echo WantedBy=var-www-mymount2.mount >> /etc/systemd/system/nginx.service
      
      # Update service symlinks
      systemctl daemon-reload
      systemctl disable nginx.service
      systemctl enable nginx.service
      

      【讨论】:

        猜你喜欢
        • 2015-11-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-11-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多