1

I am on ubuntu 18.04 server. I need to run a script that updates an IP address on CloudFlare (kind of DynDNS script). In previous versions I could do this with a DHCLIENT exit hooks for the interface enp1s0.

However, systemd now uses their own build-in DHCP client. How can I write a systemd unit that executes my bash script as soon as a new IP address is provided to the DCHP client?

Systemd is managing the interface enp1s0:

#sudo  systemctl status systemd-networkd
● systemd-networkd.service - Network Service
   Loaded: loaded (/lib/systemd/system/systemd-networkd.service; enabled-runtime; vendor preset: enabled)
   Active: active (running) since Tue 2018-09-18 01:54:16 +08; 10h ago
     Docs: man:systemd-networkd.service(8)
 Main PID: 878 (systemd-network)
   Status: "Processing requests..."
    Tasks: 1 (limit: 4915)
   CGroup: /system.slice/systemd-networkd.service
           └─878 /lib/systemd/systemd-networkd

Sep 18 01:54:27 xxx systemd-networkd[878]: enp1s0: Configured
2

I don't know of any systemd solution, but you can monitor changes to interfaces efficiently with ip monitor and pipe the output into a script that looks for the changes that interest you. For example, if I do

$ ip monitor address dev enp3s0

then add a new alias address to interface enp3s0 I get the line

2: enp3s0    inet 192.168.77.77/24 brd 192.168.77.255 scope global enp3s0:1
       valid_lft forever preferred_lft forever

I presume you would see something similar for dhcp changes.

If you prefer, you can write a C program to do the same, see this ipevent.c.

1

Many packages do not work with systemd-networkd ... yet. (see bug Report on LaunchPad)

For now, ISC DHCP client (dhclient) still reign supreme, particularly in custom DHCP-Option needed by many ISP's DHCP servers (I'm looking at you, Juniper Networks), as well as supporting OS-scripting.

So, head over to /etc/systemd/network to edit the config file that deals with dynamic IP addressing and disable systemd's DHCP in the following:

[Match]
Name=eth1
[Network]
# Using ISC DHCP client (dhclient) instead of systemd-networkd
# Better support of DHCP-Options and OS-specific script supports
DHCP=no

Then ensure the following for ISC DHCP client (dhclient) in /etc/network/interfaces:

auto eth0
iface eth0 inet dhcp

And for /etc/dhcp/dhclient.conf:

send host-name "Wireless_Broadband_Router";
send domain-name "home";
request subnet-mask, broadcast-address, time-offset, routers,
    domain-name, domain-name-servers, time-servers, log-servers,
    default-ip-ttl, dhcp-requested-address, dhcp-lease-time,
    dhcp-server-identifier,dhcp-parameter-request-list,
    vendor-class-identifier,dhcp-client-identifier,
    www-server,
    dhcp6.name-servers, dhcp6.domain-search, dhcp6.fqdn, 
    dhcp6.sntp-servers,
    interface-mtu,
    ntp-servers;

Last step is to have systemd fire up the ISC DHCP client as a daemon. Create a file in /etc/systemd/system/dhclient@.service.

# cat /etc/systemd/system/dhclient@.service 
[Unit]
Description=dhclient on %I
Wants=network.target
Before=network.target
BindsTo=sys-subsystem-net-devices-%i.device
After=sys-subsystem-net-devices-%i.device

[Service]
# ExecStart=/sbin/dhclient -4 -q %I
ExecStart=/sbin/dhclient -4 -v -pf /run/dhclient.%I.pid -lf /var/lib/dhcp/dhclient.%I.leases %I

[Install]
WantedBy=multi-user.target

And make ISC DHCP client available to systemd daemon by executing from a shell:

sudo systemctl daemon-reload   #makes the dhclient@.service available
sudo systemctl enable dhclient@eth0.service
sudo systemctl start dhclient@eth0.service
0

Take a look at networkd-dispatcher. It is a daemon which runs scripts from /etc/networkd-dispatcher/*.d on various network events. Details about the events are passed to the scripts via environment variables.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.