Home / Alt manpages / networkmanager-dispatcher(8)

  • networkmanager-dispatcher(8)
  • Admin command
  • linux

Add and Verify a NetworkManager Dispatcher Script

NetworkManager-dispatcher fires your own scripts on every connection event, and a bad hook can flap your network. You will build a small root-owned hook that logs those events safely, prove the dispatcher runs it, and remove it again without leaving a trace. Allow about 10 minutes.

You need NetworkManager 1.46.0 or a compatible release, a shell account with sudo access, and a connection you can safely bring up and down for testing.

NetworkManager-dispatcher is a D-Bus activated service. When NetworkManager reports a relevant change, it runs every regular executable file in /etc/NetworkManager/dispatcher.d and /usr/lib/NetworkManager/dispatcher.d, including subdirectories, in alphabetical order. The installed package here is network-manager 1.46.0-1ubuntu2.8.

Each script gets two positional arguments: the interface involved, and an action such as up, down, vpn-up, dhcp4-change, connectivity-change or dns-change. The interface argument is none for hostname, and empty for connectivity-change and dns-change, so never assume every event hands you a usable interface name.

1. Choose a Narrowly Scoped Hook

Use /etc/NetworkManager/dispatcher.d for local administrator scripts. A two-digit prefix makes ordering obvious, though it will not run before every other file, since all names sort together. The example below only logs the event, it does not touch routes, restart services or change DNS.

Read the script before installing it, the next command changes system state and needs elevated privileges:

sudo install -d -m 0755 /etc/NetworkManager/dispatcher.d
sudo tee /etc/NetworkManager/dispatcher.d/90-log-network-event >/dev/null <<'EOF'
#!/bin/sh
set -eu

interface=$1
action=$2
logger -t nm-dispatcher -- "interface=$interface action=$action connection=${CONNECTION_ID-unknown}"
EOF
sudo chown root:root /etc/NetworkManager/dispatcher.d/90-log-network-event
sudo chmod 0755 /etc/NetworkManager/dispatcher.d/90-log-network-event

install, tee, chown and chmod all need sudo because the target lives under /etc. The quoted here-document stops the shell expanding variables while the file is written. At event time NetworkManager supplies CONNECTION_ID when it has one, the unknown fallback keeps the logger call safe when it does not.

2. Verify the File Before You Trigger Anything

The dispatcher only runs a regular executable file owned by root, not writable by group or other, and without the set-user-ID bit. Check all of that before testing:

stat -c '%A %U:%G %n' /etc/NetworkManager/dispatcher.d/90-log-network-event
sudo sh -n /etc/NetworkManager/dispatcher.d/90-log-network-event
systemctl status NetworkManager-dispatcher.service --no-pager

You want permissions equivalent to -rwxr-xr-x, owner root:root, and the exact path. The service can show inactive before an event fires, it is D-Bus activated, so inactivity alone is not a failure. A clean shell syntax check produces no output.

3. Trigger and Inspect One Event

Pick a connection you can afford to interrupt. Bringing a production connection down can drop your own session, so use a local console or a test connection if you have one. The next command is an example only, swap in a real connection name and expect a brief interruption.

nmcli connection down id "TEST_CONNECTION_NAME"
nmcli connection up id "TEST_CONNECTION_NAME"
journalctl -t nm-dispatcher -n 20 --no-pager

You are looking for a journal line like nm-dispatcher: interface=... action=down ..., and a matching one for up. The exact interface, connection ID and order depend on your connection and other network activity. If you cannot safely interrupt a connection, wait for an ordinary DHCP or DNS change and inspect the journal instead.

Tip

NetworkManager runs dispatcher scripts one at a time and asynchronously from its main process. A script already queued still runs even if a later event makes it stale, so an up handler can fire after the interface has already gone down again. Keep handlers short and tolerant of the current state not matching the event that triggered them.

4. Use Event-specific Data Carefully

The environment carries values such as DEVICE_IFACE, DEVICE_IP_IFACE, CONNECTION_UUID, CONNECTION_ID, IP4_GATEWAY, IP4_NUM_ADDRESSES, IP4_NAMESERVERS and their IPv6 equivalents. VPN events also expose VPN_IP_IFACE and VPN-prefixed address variables, and a DHCP option can turn up as something like DHCP4_HOST_NAME. Test that a variable is actually set before you use it, different event types hand you different subsets.

For connectivity-change, check CONNECTIVITY_STATE: UNKNOWN, NONE, PORTAL, LIMITED or FULL. For dns-change, a script can read /run/NetworkManager/resolv.conf even when NetworkManager is not managing the usual resolver file.

Pre-events are a special case: put pre-up or vpn-pre-up scripts in /etc/NetworkManager/dispatcher.d/pre-up.d, and pre-down or vpn-pre-down scripts in /etc/NetworkManager/dispatcher.d/pre-down.d. NetworkManager waits for these before completing a clean transition, though a forced disconnect such as carrier loss skips the pre-down events entirely.

5. Keep the Handler Reliable

Do not put long-running work directly in a dispatcher script, NetworkManager can and will kill scripts that take too long. If the work is unpredictable, have the script launch a separate process and return promptly, with its own logging and failure handling. Scripts linked into /etc/NetworkManager/dispatcher.d/no-wait.d run in parallel without waiting for earlier scripts, only use that when concurrency is deliberate and safe.

For device-add and device-delete, only the configured generic-device handler runs, and a successful device-add handler must write an IFINDEX value to standard output. That output stream is reserved for these result keys, so send diagnostics to standard error instead; an ordinary event handler should never treat standard output as a log.

6. Remove the Test Hook

Warning

Deleting the file is irreversible, so confirm the path before you run it. Remove only the file you created in this guide:

sudo test -f /etc/NetworkManager/dispatcher.d/90-log-network-event
sudo rm /etc/NetworkManager/dispatcher.d/90-log-network-event
test ! -e /etc/NetworkManager/dispatcher.d/90-log-network-event && echo "test hook removed"

No restart is needed to remove a dispatcher script. Events already queued may still run, but nothing after this will find the removed file.

Done means

  • Ownership correct. The hook is a root-owned regular executable with no group or other write permission.
  • Arguments handled. The script accepts both dispatcher arguments and copes with missing environment values.
  • Event confirmed. A safe test event produced a matching nm-dispatcher journal entry.
  • Timing considered. Any pre-event or parallel execution choice is deliberate.
  • Cleaned up. The test file is removed, or its ongoing purpose and recovery plan are written down.