systemd is ignoring ExecStop in the unit file, runs it as part of ExecStart

25,408

Solution 1

As others have mentioned, the problem is that vmctl.sh immediately exits. Contrary to @Christophe's answer, forking will not work most likely, as vmctl.sh likely does not fork. What you need is a oneshot service, with RemainAfterExit=true. If you just change it to oneshot, you'll get the exact same behavior. The RemainAfterExit part tells it that even after the ExecStart exits, the service should still be considered running, so it should not run the ExecStop(s).

Solution 2

Your systemd syntax is correct. Your problem is elsewhere.

First, you can confirm that the syntax itself is correct with:

systemd-analyze verify /path/to/your/vmctl.service

Second, try substituting these lines:

ExecStart=/bin/echo "I started"
ExecStop=/bin/echo "I stopped"

After running systemctl start vmctl or systemctl stop vmctl, use journalctl -u vmctl to check the logs. I expect you'll confirm systemd ran the correct commands.

Also /lib/systemd/system is intended for a place for packages to manage systemd files. Files that human's modify and manually manage are intended to go in /etc/systemd/system

Share:
25,408

Related videos on Youtube

Jay MacDonald
Author by

Jay MacDonald

Updated on September 18, 2022

Comments

  • Jay MacDonald
    Jay MacDonald over 1 year

    I am trying to have several VirtualBox images start automatically on boot and to be shutdown properly on host shutdown before powering down. I have a bash script, /usr/local/bin/vmctl.sh, that handles starting and stopping the guest images using calls to VBoxManage. The start call is very simple - it just runs through a list of images and calls VBoxManage startvm --type headless "<imgname>" then exits 0. The stop call cycles through the list and calls VBoxManage controlvm "<imgname>" acpipowerbutton then loops until VBoxManage list runningvms returns an empty list OR 60 seconds passes before it exits 0. Running the script from the command line works perfectly.

    I have set up a unit file in /lib/systemd/system/vmctl.service:

    [Unit]
    Description=VirtualBox Control
    After=virtualbox.service
    
    [Service]
    ExecStart=/usr/local/bin/vmctl.sh start
    ExecStop=/usr/local/bin/vmctl.sh stop
    
    [Install]
    WantedBy=multi-user.target
    

    When I run systemctl start vmctl.service, it calls both the start and stop lines. When I call systemctl stop vmctl.service there is an entry in syslog that states Stopped VirtualBox Control but it does not do anything.

    I am a total neophyte to systemd. I recently upgraded this Ubuntu box to 16.04. I'm pretty sure there's a simple explanation for this behaviour that I'm just not seeing.

    Thanks!


    Update based on Mark's suggestion:

    I confirmed the syntax using systemd-analyze verify /etc/systemd/system/vmctl.service (after moving the file there - thanks for the tip). I then changed out the ExecStart and ExecStop as you suggested, ran systemctl daemon-reload and still see the same behaviour. The log shows both executing when calling systemctl start vmctl, but neither when running systemctl stop vmctl:

    # journalctl -u vmctl | tail
    .
    .
    .
    Apr 06 19:28:18 macmi10-builder systemd[1]: Started VirtualBox Control.
    Apr 06 19:28:18 macmi10-builder echo[13901]: I started
    Apr 06 19:28:18 macmi10-builder echo[13904]: I stopped
    Apr 06 19:28:33 macmi10-builder systemd[1]: Stopped VirtualBox Control.
    
    • hchandad
      hchandad about 7 years
      I actually had the same problem except that i had different script names, i set RemainAfterExit=yes and it worked.
    • Jem Tucker
      Jem Tucker almost 7 years
      Did you ever get to the bottom of this?
  • Dessa Simpson
    Dessa Simpson over 6 years
    The vmctl.sh script is not a daemon - it's a controller, and likely does not fork.
  • Dessa Simpson
    Dessa Simpson over 6 years
    After substituting those commands into a simple or forking service, the same behavior is reflected. For simple, ExecStart's echo exits, so it calls ExecStop. For forking, there are no running child processes from ExecStart's echo, and as such it calls ExecStop.