Although this approach works well as it is, ideally it should be included in the standard distribution with raspi-config modified to control it directly through ‘systemctl en/disable’ instead of writing and deleting the current Wait for Network wait.conf.
Problem
When configured to Wait for Network, the Jessie systemd init process detects dhcpcd obtaining interface configurations before proceeding to network.target and network-online.target. At that exact point, however, interface address/es are not yet configured, and name resolution comes later still.
When not configured to Wait for Network (or when dhcpcd reaches its timeout while waiting), dhcpcd forks to a background daemon and the init process proceeds immediately. This means network.target and network-online.target are reached even without the availability of interface configurations.
Compounding the problem is the fact that - as standard - network.target and network-online.target call for no further checking. network-online.target is therefore often reached before interface configurations have been applied, and in cases even before they have been obtained.
Solution
1. Change to super-user
Code: Select all
pi@fv-rpi3b:~ $ sudo su
root@fv-rpi3b:/home/pi#
(no special permissions needed)
Code: Select all
root@fv-rpi3b:/home/pi# nano /lib/systemd/system/network-wait-online.service
Code: Select all
#
# Uses 'hostname --all-fqdns' to confirm that both: IP address[es] assigned, and DNS operational
#
[Unit]
Description=Wait for Network to be Online
Documentation=man:systemd.service(5) man:systemd.special(7)
Conflicts=shutdown.target
After=network.target
Before=network-online.target
[Service]
Type=oneshot
ExecStart= \
/bin/bash -c ' \
if [ -e /etc/systemd/system/dhcpcd.service.d/wait.conf ]; \
then \
echo Wait for Network: enabled; \
while [ -z $(hostname --all-fqdns) ]; \
do \
sleep 1; \
done; \
else \
echo Wait for Network: disabled; \
exit 0; \
fi'
TimeoutStartSec=1min 30s
[Install]
WantedBy=network-online.target
Code: Select all
Ctrl-O
Code: Select all
Ctrl-X
3. Enable network-wait-online.service
Code: Select all
root@fv-rpi3b:/home/pi# systemctl enable network-wait-online.service
Created symlink from /etc/systemd/system/network-online.target.wants/network-wait-online.service to /lib/systemd/system/network-wait-online.service.
Code: Select all
root@fv-rpi3b:/home/pi# reboot now
How to reproduce the problem
1. Create a network auto-mount
On a standard system (i.e. without network-wait-online.service installed), add a line similar to the following to /etc/fstab. Dummy names can be used through-out with the exception of the host which must be a reachable hostname:
Code: Select all
//fvmedia/share /mnt/point cifs guest 0 0
Code: Select all
root@fv-rpi3b:/home/pi# systemctl list-dependencies --before dhcpcd
dhcpcd.service
…
● ├─network.target
…
● │ └─network-online.target
● │ ├─mnt-point.mount
…
2. Induce a delay to prevent DHCP & interface initialisation normally from completing before mount
a. Configure the Pi for Wi-Fi networking
b. Ensure its dhcpcd is configured to obtain its configuration from the DHCP server (the default)
c. Configure the Wi-Fi access point to hide its SSID (“hidden network”)
d. In /etc/wpa_supplicant/wpa_supplicant.conf, disable scanning (disable or remove ‘ap_scan’ and ‘scan_ssid’ entries)
3. Standard installation with Wait for Network disabled
Ensure Wait for Network is disabled and reboot
Code: Select all
root@fv-rpi3b:/home/pi# systemctl status dhcpcd
● dhcpcd.service - dhcpcd on all interfaces
Loaded: loaded (/lib/systemd/system/dhcpcd.service; enabled)
Active: active (running) since Thu 2017-06-29 13:21:36 BST; 1min 38s ago
Process: 373 ExecStart=/sbin/dhcpcd -q -b (code=exited, status=0/SUCCESS)
Main PID: 385 (dhcpcd)
CGroup: /system.slice/dhcpcd.service
└─385 /sbin/dhcpcd -q -b
Despite dhcpcd "initialising" and the Network and Network is Online targets being reached, the mount is attempted before interface initialisation and fails:
Code: Select all
root@fv-rpi3b:/home/pi# journalctl
-- Logs begin at Thu 2017-06-29 13:21:32 BST, end at Thu 2017-06-29 13:28:57 BST. --
...
Jun 29 13:21:35 fv-rpi3b dhcpcd[373]: version 6.7.1 starting
...
Jun 29 13:21:35 fv-rpi3b dhcpcd[373]: forked to background, child pid 385
...
Jun 29 13:21:36 fv-rpi3b systemd[1]: Started dhcpcd on all interfaces.
Jun 29 13:21:36 fv-rpi3b systemd[1]: Starting Network.
...
Jun 29 13:21:36 fv-rpi3b systemd[1]: Reached target Network.
...
Jun 29 13:21:36 fv-rpi3b systemd[1]: Starting Network is Online.
Jun 29 13:21:36 fv-rpi3b systemd[1]: Reached target Network is Online.
Jun 29 13:21:36 fv-rpi3b systemd[1]: Mounting /mnt/point...
...
Jun 29 13:21:36 fv-rpi3b mount[449]: mount error: could not resolve address for fvmedia: Unknown error
...
Jun 29 13:22:18 fv-rpi3b dhcpcd[385]: wlan0: carrier acquired
...
Jun 29 13:22:24 fv-rpi3b dhcpcd[385]: wlan0: leased 192.168.1.204 for 86400 seconds
...
Enable Wait for Network and reboot
Code: Select all
root@fv-rpi3b:/home/pi# systemctl status dhcpcd
● dhcpcd.service - dhcpcd on all interfaces
Loaded: loaded (/lib/systemd/system/dhcpcd.service; enabled)
Drop-In: /etc/systemd/system/dhcpcd.service.d
└─wait.conf
Active: active (running) since Thu 2017-06-29 13:36:41 BST; 5min ago
Process: 374 ExecStart=/sbin/dhcpcd -q -w (code=exited, status=0/SUCCESS)
Main PID: 552 (dhcpcd)
CGroup: /system.slice/dhcpcd.service
└─552 /sbin/dhcpcd -q -w
The mount is again attempted before interface initialisation and fails. Wait for Network only delays dhcpcd forking to the background but does not improve network availability detection.
Code: Select all
-- Logs begin at Thu 2017-06-29 13:36:07 BST, end at Thu 2017-06-29 13:37:33 BST. --
...
Jun 29 13:36:10 fv-rpi3b dhcpcd[374]: version 6.7.1 starting
...
Jun 29 13:36:41 fv-rpi3b dhcpcd[374]: timed out
Jun 29 13:36:41 fv-rpi3b dhcpcd[374]: forked to background, child pid 552
Jun 29 13:36:41 fv-rpi3b systemd[1]: Started dhcpcd on all interfaces.
Jun 29 13:36:41 fv-rpi3b systemd[1]: Starting Network.
Jun 29 13:36:41 fv-rpi3b systemd[1]: Reached target Network.
...
Jun 29 13:36:41 fv-rpi3b systemd[1]: Starting Network is Online.
Jun 29 13:36:41 fv-rpi3b systemd[1]: Reached target Network is Online.
Jun 29 13:36:41 fv-rpi3b systemd[1]: Mounting /mnt/point...
...
Jun 29 13:36:41 fv-rpi3b mount[556]: mount error: could not resolve address for fvmedia: Unknown error
...
Jun 29 13:36:53 fv-rpi3b dhcpcd[552]: wlan0: carrier acquired
...
Jun 29 13:36:59 fv-rpi3b dhcpcd[552]: wlan0: leased 192.168.1.204 for 86400 seconds
...
a. Configure network-wait-online.service as described in Solution above
b. Replace the ExecStart= option in network-wait-online.service with
Code: Select all
ExecStart= \
/bin/bash -c ' \
IPs=$(hostname --all-ip-addresses); \
while [ -z $IPs ]; \
do \
echo network-wait-online: addresses=$IPs; \
sleep 0.1; \
IPs=$(hostname --all-ip-addresses); \
done'
When systemd reinitialises, network-wait-online will have the following key relationships:
Code: Select all
root@fv-rpi3b:/home/pi# systemctl list-dependencies --before dhcpcd
dhcpcd.service
...
● ├─network.target
...
● │ ├─network-wait-online.service
...
● │ └─network-online.target
● │ ├─mnt-point.mount
...
This time the mount is only attempted after an IP address is obtained, but name resolution still fails:
Code: Select all
-- Logs begin at Thu 2017-06-29 14:20:53 BST, end at Thu 2017-06-29 14:21:51 BST. --
...
Jun 29 14:20:56 fv-rpi3b systemd[1]: Starting dhcpcd on all interfaces...
...
Jun 29 14:20:56 fv-rpi3b dhcpcd[378]: version 6.7.1 starting
...
Jun 29 14:20:56 fv-rpi3b dhcpcd[378]: forked to background, child pid 386
...
Jun 29 14:20:57 fv-rpi3b systemd[1]: Started dhcpcd on all interfaces.
Jun 29 14:20:57 fv-rpi3b systemd[1]: Starting Network.
Jun 29 14:20:57 fv-rpi3b systemd[1]: Reached target Network.
...
Jun 29 14:20:57 fv-rpi3b systemd[1]: Starting Wait for Network to be Online...
...
Jun 29 14:20:57 fv-rpi3b bash[445]: network-wait-online: addresses=
...
Jun 29 14:21:39 fv-rpi3b dhcpcd[386]: wlan0: carrier acquired
...
Jun 29 14:21:45 fv-rpi3b bash[445]: network-wait-online: addresses=
Jun 29 14:21:45 fv-rpi3b dhcpcd[386]: wlan0: leased 192.168.1.204 for 86400 seconds
...
Jun 29 14:21:45 fv-rpi3b systemd[1]: Started Wait for Network to be Online.
Jun 29 14:21:45 fv-rpi3b systemd[1]: Starting Network is Online.
Jun 29 14:21:45 fv-rpi3b systemd[1]: Reached target Network is Online.
Jun 29 14:21:45 fv-rpi3b systemd[1]: Mounting /mnt/point...
Jun 29 14:21:45 fv-rpi3b mount[1883]: mount error: could not resolve address for fvmedia: Unknown error
...
Enable Wait for Network and reboot
As expected by now, Wait for Network makes no difference other than delaying dhcpcd forking to the background. The mount is only attempted after an IP address is obtained, but name resolution still fails:
Code: Select all
-- Logs begin at Thu 2017-06-29 14:35:08 BST, end at Thu 2017-06-29 14:36:05 BST. --
...
Jun 29 14:35:11 fv-rpi3b systemd[1]: Starting dhcpcd on all interfaces...
...
Jun 29 14:35:11 fv-rpi3b dhcpcd[368]: version 6.7.1 starting
...
Jun 29 14:35:42 fv-rpi3b dhcpcd[368]: timed out
Jun 29 14:35:42 fv-rpi3b dhcpcd[368]: forked to background, child pid 548
Jun 29 14:35:42 fv-rpi3b systemd[1]: Started dhcpcd on all interfaces.
Jun 29 14:35:42 fv-rpi3b systemd[1]: Starting Network.
Jun 29 14:35:42 fv-rpi3b systemd[1]: Reached target Network.
...
Jun 29 14:35:42 fv-rpi3b systemd[1]: Starting Wait for Network to be Online...
...
Jun 29 14:35:42 fv-rpi3b bash[551]: network-wait-online: addresses=
...
Jun 29 14:35:55 fv-rpi3b dhcpcd[548]: wlan0: carrier acquired
...
Jun 29 14:35:59 fv-rpi3b bash[551]: network-wait-online: addresses=
Jun 29 14:35:59 fv-rpi3b dhcpcd[548]: wlan0: leased 192.168.1.204 for 86400 seconds
...
Jun 29 14:35:59 fv-rpi3b systemd[1]: Started Wait for Network to be Online.
Jun 29 14:35:59 fv-rpi3b systemd[1]: Starting Network is Online.
Jun 29 14:35:59 fv-rpi3b systemd[1]: Reached target Network is Online.
Jun 29 14:35:59 fv-rpi3b systemd[1]: Mounting /mnt/point...
Jun 29 14:35:59 fv-rpi3b mount[1033]: mount error: could not resolve address for fvmedia: Unknown error
...
a. Replace the ExecStart= option in network-wait-online.service with
Code: Select all
ExecStart= \
/bin/bash -c ' \
HNs=$(hostname --all-fqdns); \
IPs=$(hostname --all-ip-addresses); \
while [ -z "$HNs" -o -z "$IPs" ]; \
do \
echo network-wait-online: addresses=$IPs, hostnames=$HNs; \
sleep 0.1; \
HNs=$(hostname --all-fqdns); \
IPs=$(hostname --all-ip-addresses); \
done'
The modified network-wait-online service will start tracing IP address and DNS resolver availability as soon as dhcpcd initialises (=network.target), and will satisfy network-online.target by completing successfully once an IP address has been configured and DNS resolution operates.
This log shows that by the time the interface IP address has been configured, availability of DNS resolution and general network access cannot be assumed (network-wait-online: addresses=192.168.1.204 , hostnames=). However, because network-wait-online now assures DNS resolver availability by the time it completes, network availability is also assured (because the resolver was reached and responded). Name resolution of the remote server for the mount command therefore succeeds (although the mount still fails due to the dummy share name):
Code: Select all
-- Logs begin at Thu 2017-06-29 14:43:58 BST, end at Thu 2017-06-29 14:44:56 BST. --
...
Jun 29 14:44:01 fv-rpi3b systemd[1]: Starting dhcpcd on all interfaces...
...
Jun 29 14:44:01 fv-rpi3b dhcpcd[374]: version 6.7.1 starting
...
Jun 29 14:44:01 fv-rpi3b dhcpcd[374]: forked to background, child pid 385
...
Jun 29 14:44:02 fv-rpi3b systemd[1]: Started dhcpcd on all interfaces.
Jun 29 14:44:02 fv-rpi3b systemd[1]: Starting Network.
Jun 29 14:44:02 fv-rpi3b systemd[1]: Reached target Network.
...
Jun 29 14:44:02 fv-rpi3b systemd[1]: Starting Wait for Network to be Online...
...
Jun 29 14:44:44 fv-rpi3b bash[444]: network-wait-online: addresses=, hostnames=
...
Jun 29 14:44:44 fv-rpi3b dhcpcd[385]: wlan0: carrier acquired
...
Jun 29 14:44:50 fv-rpi3b bash[444]: network-wait-online: addresses=, hostnames=
Jun 29 14:44:50 fv-rpi3b dhcpcd[385]: wlan0: leased 192.168.1.204 for 86400 seconds
...
Jun 29 14:44:50 fv-rpi3b bash[444]: network-wait-online: addresses=192.168.1.204 , hostnames=
Jun 29 14:44:50 fv-rpi3b systemd[1]: Started Wait for Network to be Online.
Jun 29 14:44:50 fv-rpi3b systemd[1]: Starting Network is Online.
Jun 29 14:44:50 fv-rpi3b systemd[1]: Reached target Network is Online.
Jun 29 14:44:50 fv-rpi3b systemd[1]: Mounting /mnt/point...
...
Jun 29 14:44:51 fv-rpi3b mount[2610]: Retrying with upper case share name
Jun 29 14:44:51 fv-rpi3b kernel: CIFS VFS: cifs_mount failed w/return code = -6
Jun 29 14:44:51 fv-rpi3b mount[2610]: mount error(6): No such device or address
...
Enable Wait for Network and reboot
Results are similar to the previous case, as expected.
Advantages of this approach
It provides reliable detection
This approach adds the necessary checking to network-online.target, testing for both IP configuration and DNS operation.
It is deterministic
Delay-based approaches may waste boot time or not wait long enough. This approach waits as long as necessary and not any longer to ensure reliable network availability.
It is future-proof?
By integrating into the Jessie systemd init process in a standard way, the configuration for this solution will hopefully survive OS upgrades

Best of all, it's still controlled by Wait for Network!
Other approaches
Boot or user login delays:
Fixed delays usually either waste time by waiting too long, or are unreliable because they do not necessarily wait long enough.
fstab noauto, x-systemd.automount options:
This delays mounting until first access. Similarly to above it is not guaranteed to introduce a long enough delay (and in practice usually doesn't).
fstab _netdev or x-systemd.requires=network-online.target options:
These are redundant with a standard Jessie systemd installation -
Code: Select all
pi@fv-rpi3b:~ $ man systemd.special
…
network-online.target
…
All mount units for remote network file systems automatically pull in this unit, and order themselves after it.
…
Code: Select all
pi@fv-rpi3b:~ $ systemctl list-dependencies mnt-point.mount
mnt-point.mount
● ├─-.mount
● ├─system.slice
● └─network-online.target
Code: Select all
mnt-point.mount
● ├─-.mount
● ├─system.slice
● └─network-online.target
● └─network-wait-online.service