2

I hope to use launchd to set a static route on a server at boot time since I haven't figured a better way to configure this sort of networking on a server.

My problem is that the command seems to be running before the network stack is set up, so I'm looking for advice how to change my plist to somehow depend on the system routing being set up before it runs.

Jan 16 14:39:45 server com.company.route.legacy_printer[149]: route: writing to routing socket: Network is unreachable

Jan 16 14:39:45 server com.company.route.legacy_printer[149]: add net 10.1.1.1: gateway 10.0.1.2: Network is unreachable

I get this error after a reboot, but loading the same plist as root once the mac has booted works just fine so I'm hoping it's an easy tweak or someone clueing me into a better way to get a static route reliably after each boot.

<?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>Label</key>
    <string>com.company.route.legacy_printer</string>
    <key>ProgramArguments</key>
    <array>
        <string>/sbin/route</string>
        <string>-n</string>
        <string>add</string>
        <string>-net</string>
        <string>10.1.1.1</string>
        <string>10.0.1.2</string>
        <string>255.255.255.0</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <false/>
    <key>AbandonProcessGroup</key>
    <true/>
</dict>
</plist>

I have reviewed both Running a command whenever Mac boots up with launchctl/plist and How can I run/stop/relaunch an application automatically, at boot/login/some other time? to get this far, but need an extra nudge on finding the correct dependency to get the timing right for the route command.

2
  • If you can afford to, the easiest solution might be to simply add a couple seconds of delay. Jan 16, 2012 at 22:04
  • I'm tempted to put in 60 seconds sleep and a pipe since launchd doesn't necessarily schedule jobs in the same order. It shouldn't be a big issue delaying things, just less clean than knowing how to actually build in the correct trigger.
    – bmike
    Jan 17, 2012 at 0:01

1 Answer 1

3

A short call to scutil should help with testing whether the network is up for a specific interface on IPv4 which should suffice to determine when you can add an IPv4 route. The following command will return a 0 if the first ethernet connection has a viable IPv4 address within the default 15 second timeout period.

  • /usr/sbin/scutil -w State:/Network/Interface/en0/IPv4

You could instead call a script to do the testing and routing - perhaps using the -t command to adjust the timeout if needed. I don't know a way to overload the launchd arguments to have everything contained, but it should be fine to have launchd kick off a script on the local filesystem to accomplish this task. Use care if you are not using en0 for your IPv4 or wish to have routing on other than the default networking interface.

That script can then check for errors, perhaps check for other interfaces as well as log success and failure using the logger command.

3
  • That call won't work in a wireless-only scenario, as those devices are generally en1. Just more emphasis on "[…] testing whether the network is up for a specific interface on IPv4". Feb 13, 2012 at 21:46
  • When confronted with multiple steps for launchd plists, I usually find that writing a script and using the plist to call the script works best.
    – afragen
    Feb 13, 2012 at 22:04
  • Good point @afragen - bonded interfaces and thunderbolt adapters can make en0 not the choice network name.
    – bmike
    Oct 21, 2015 at 14:43

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .