1

I am trying to make my RPI 4 execute a script, when it connects to a network (be it cable or wifi) i.e when it goes from not connected to connected.

I am running Raspbian (Buster) as OS and on Ubuntu 18.04 I can simply put the script in NetworkManager/dispatcher.d but since NetworkManager is not installed on my RPI (and I want to keep as clean an installation as possible) I tried to place it in /etc/network/if-up.d based on different answers years ago - it seems like if-* not used any more or..?

Any idea?

Test-script:

#!/bin/sh
echo "WORKING">out.txt

CutePoison
  • 113
  • 3
  • Your test script should probably use an absolute path for `out.txt`, otherwise it is likely to end up not where you thought it would. – goldilocks Feb 01 '21 at 19:30

3 Answers3

3

Dhcpdcd, which is used for DHCP client negotiation by default in Raspbian/RpiOS, has a "hooks" directory in /lib/dhcpcd/dhcpcd-hooks. Beware not to confuse dhcpcd with dhclient, which can serve much the same purpose and also entertains hooks (but is not used by default), or dhcpd (one less letter), which acts as a DHCP server (the cd in dhcpcd is for "client daemon").

man dhcpcd-run-hooks documents this very succinctly. When the script is run by dhcpd, the environment will contain a bunch of variables with information. There is a list of a dozen or so reasons that this will happen; the specific one will be in $reason.

Try placing this there:1

reportLog=/some/absolute/path/dhcpcd-report.log

msg() {
    echo $@ >> $reportLog
}

date >> $reportLog
msg Invoked for $reason

# 'printenv' dumps all the environment variables
printenv >> $reportLog   

echo >> $reportLog

An example of the output:

Mon Jan 25 17:12:03 EST 2021
Invoked for BOUND
new_subnet_cidr=24
new_ip_address=192.168.0.21
new_network_number=192.168.0.0
pid=427
new_dhcp_message_type=5
if_down=false
ifmtu=1500
new_routers=192.168.0.1
new_subnet_mask=255.255.255.0
interface=wlan0
new_domain_name=hitronhub.home
reason=BOUND
ifcarrier=up
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
ifssid=ISS2
protocol=dhcp
interface_order=lo eth0 wlan0
new_host_name=raspberrypi
if_up=true
new_dhcp_server_identifier=192.168.0.1
new_domain_name_servers=64.71.255.204 64.71.255.198
new_broadcast_address=192.168.0.255
WPAconfig=/etc/wpa_supplicant/wpa_supplicant.conf
ifflags=69699
PWD=/
ifmetric=303
ifwireless=1
new_dhcp_lease_time=604800

A couple of the variables are inherited from the system ($PATH, $PWD), the rest are all from dhcpcd (many/most of them are described in the hooks man page). Of particular relevance to you is of course if_up=true. You'll have to experiment a bit to decide when you should do what it is you want to do. For example, there's a distinction between an interface going up and an actual connection being established, and some specific combination of $reason and $interface may be the key you want to watch for; if you just do it every time a hook is run with if_up=true you will end up doing it three or four times in rapid succession, etc.


  1. Dhcpcd executes this via sh (which is why there is no point in a shebang #!/___), meaning you can't use bashisms like exec &> to redirect all output (hence the cumbersome msg() function above) or capture the output of a command in a variable with foo=$(bar). However, you can get around that by making the hook script just:

     /bin/bash /path/to/some/bashscript.sh
    

You could do something similar to run a python script or execute anything; those environment variables are inherited.

goldilocks
  • 56,430
  • 17
  • 109
  • 217
2

In the "good old days" there was ifplugd available with Debian networking, managed with /etc/network/interfaces. It monitors the network interfaces and calls a script if they change their state. But Debian networking isn't well supported on the Raspberry Pi OS, because it uses dhcpcd by default.

I have made ifplugd available again with systemd-networkd. How to use it you can look at Make ifplugd available with systemd. You can also find a practical example at How to make Raspian Buster shutdown when I unplug the ethernet cable.

Ingo
  • 40,606
  • 15
  • 76
  • 189
  • 1
    You can add scripts to `dhcpcd` that trigger when an interface goes up, gets connected, etc., but it is perhaps slightly more labour intensive than `/etc/interface` stuff -- see `man dhcpcd-run-hooks`. The script's environment will include things like `$interface` and `$if_up`, as described in that man page. Unfortunately I don't have time to write an example right now... – goldilocks Jan 29 '21 at 20:59
  • I have tried adding `echo "test">./out.txt"` and placed it in `/etc/dhcp/dhclient-exit-hooks.d` but nothing happens when I disconnect/connect again. The script can be run manually – CutePoison Jan 30 '21 at 09:10
  • @goldilocks I know about hook scripts with `dhcpcd` but I like to support **systemd** ;-) – Ingo Jan 30 '21 at 09:56
  • @CutePoison You are mixing up things. With `/etc/dhcp/dhclient-exit-hooks.d` you try to configure the **isc-dhcp-client**. But that isn't used on RaspiOS. Used is `dhcpcd` (note the additional **c**) that must be configured in `/etc/dhcpcd.conf`. – Ingo Jan 30 '21 at 10:00
  • Does `ifplugd` work with wifi interfaces? – goldilocks Jan 30 '21 at 16:44
  • @goldilocks Yes. It isn't clearly stated in [man ifplugd](https://manpages.debian.org/testing/ifplugd/ifplugd.8.en.html) but you will find it with option "-m | --api-mode= *MODE*" there. – Ingo Jan 31 '21 at 17:43
0

The

dhcpcd-run-hooks

method worked for me.

I needed to activate a broadband usb-key connection before dhcpcd start to search for an IP on my wan interface

As stated from man dhcpcd-run-hooks i wrote my script in /etc/dhcpcd.enter-hook that is executed before system provided hooks in /lib/dhcpcd/dhcpcd-hooks If you need to execute your script as the last one put it in /etc/dhcpcd.exit-hook instead.