Two brew services questions


#1

Technically, I have now had a start of a docker-machine through a system-wide (/Library/LaunchDaemons) launchd .plist working. The stuff about code signing (Docker install issues) was probably a red herring (though signing does make errors go away).

The default .plist that brew services start docker-machine installs is this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>EnvironmentVariables</key>
    <dict>
        <key>PATH</key>
        <string>/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin</string>
    </dict>
    <key>Label</key>
    <string>homebrew.mxcl.docker-machine</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/local/opt/docker-machine/bin/docker-machine</string>
        <string>start</string>
        <string>default</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>WorkingDirectory</key>
    <string>/usr/local</string>
  </dict>
</plist>

This does not work on my machine (and probably on all machines) because user root has no docker knowledge (i.e. there is no~root/.docker directory). The docker machine has been created by user sysbh (the same user that is used for brew) on my system.

So, when I use launchctl to unload the service, edit the .plist to say

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>EnvironmentVariables</key>
    <dict>
        <key>PATH</key>
        <string>/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin</string>
    </dict>
    <key>Label</key>
    <string>homebrew.mxcl.docker-machine</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/local/opt/docker-machine/bin/docker-machine</string>
        <string>start</string>
        <string>default</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>UserName</key>
    <string>sysbh</string>
    <key>WorkingDirectory</key>
    <string>/Users/sysbh</string>
  </dict>
</plist>

and use launchctl to load the service a docker-machine is actully launched and can be used.

Now, the easy solution would be to just use my own .plist. But I am getting the impression that if I run sudo brew services stop docker-machine, the .plist is not only removed from /Library/LaunchDaemons but the docker-machine is also stopped (docker-machine stop). However, not always. When I just use my own .plist, I can use launchctl unload to unload it, but the virtual machine (VBoxHeadless) keeps running and I have to explicitly stop it using docker-machine stop.

Two questions:

  1. Is sudo brew services stop docker-machine also supposed to have the effect of stopping the virtual machine? And if so, is that expected as an effect from launchd or is brew doing something in the background based on what is in the brew services database?
  2. Is there a way to influence what sudo brew services start docker-machine installs in /Library/LaunchDaemons?

(Sean Molenaar) #2

Brew services also stops the progress, your command only removes the service. See the launchctl docs: http://www.launchd.info/

As I mentioned before, services are defined in the homebrew formula itself. So you’d have to maintain your own version of each formula you want to modify.


#3

Normally, when you unload a LaunchDaemon, launchd also kills it. E.g. when I unload nginx or minio or sshd on my system (which are started under launchd control as /Library/LaunchDaemons .plists), the nginx or minio or sshd processes also are ended (get SIGTERM, I think, and after a grace period get SIGKILL).

Because using launchctl unload does not kill the virtual machine, I actually thought that the homebrew way of putting a ‘service’ for docker under launchd might break launchd requirements because launchd cannot end the process. See man launchd.plist on a macOS system.

Daemons or agents managed by launchd are expected to behave certain ways:

 A daemon or agent launched by launchd MUST NOT do the following in the
 process directly launched by launchd:

       o   Call daemon(3).
       o   Do the moral equivalent of daemon(3) by calling fork(2) and
           have the parent process exit(3) or _exit(2).

 A launchd daemon or agent should not perform the following as part of its
 initialization, as launchd will always implicitly perform them on behalf
 of the process.

       o   Redirect stdio(3) to /dev/null.

My suspicion is that the docker-machine command doesn’t result in a situation where launchd's attempt to end the virtual machine succeeds. Here is an example of one docker-machine running:

  501   436     1   0  20  0  4287220   8116 -      S      ??    0:04.97 /Applications/VirtualBox.app/Contents/MacOS/VBoxXPCOMIPCD
  501   438     1   0  20  0  4350884  13800 -      S      ??    0:32.57 /Applications/VirtualBox.app/Contents/MacOS/VBoxSVC --auto-shutdown
  501   452   438   0  20  0  5071656 680608 -      S      ??   29:21.09 /Applications/VirtualBox.app/Contents/MacOS/VBoxHeadless --comment default --startvm f291551b-8b19-4500-b927-acab7930ddd9 --vrde config
  501   455   438   0  20  0  4305536   6564 -      S      ??    0:01.17 /Applications/VirtualBox.app/Contents/MacOS/VBoxNetDHCP --comment HostInterfaceNetworking-vboxnet1 --config /var/folders/rp/lf0qqbbd11s4n4s028pf4wbh0000gn/T/dhcp-config-ns1on.xml

Interestingly enough, VBoxHeadless has indeed launchd as grandparent process, so that looks good. Killing 438 from the above list actually kills the virtual machine too, so that also looks good.

But using launchctl unload does not have that effect (while it does have that effect on minio, nginx, sshd, etc.

Part of that may be that the whole launchd system has changed from long ago. E.g. load/unload are now ‘legacy’ subcommands and using them to interact may have unwanted side effects. So, possibly, trying to use these to start/stop the service may not be right. I need to investigate.


#4

What do I have to do if I want to use my own version of a formula such as docker-machine?

Oh, and thanks for the reply.


(Sean Molenaar) #5