My Raspberry Pi 4 kept losing its wlan0
interface. I could usually reconnect via Ethernet but, from time to time, I noticed that the eth0
interface would also go walkabout.
I tried a lot of things but the one described here seems to have cured the problem. I have no idea why it works. It just does.
The script shown in the next step should be created on your Raspberry Pi. Please do not make the mistake of selecting the text, copying it into a text editor on your Windows machine, saving the file, and then moving the file to your Raspberry Pi. Unless you take precautions, Windows will add its 0x0d 0x0a
(CR+LF) line endings and those will stop the script from working properly on your Raspberry Pi.
Use your favourite Unix text editor to create this script:
#!/bin/bash
logger "isc-dhcp-fix launched"
while [ $# -gt 0 ] ; do
for CARD in $@ ; do
ifconfig "$CARD" | grep -Po '(?<=inet )[\d.]+' &> /dev/null
if [ $? != 0 ]; then
logger "isc-dhcp-fix resetting $CARD"
ifconfig "$CARD" up
sleep 5
fi
sleep 1
done
sleep 1
done
Save it with the name isc-dhcp-fix.sh
Note:
- This script changed on 2021-12-14. Previously, it had
sudo dhclient "$CARD"
where you seeifconfig "$CARD" up
. That did not work where an interface was configured with a static IP address. It caused the interface to lose its static address and acquire a dynamic address. Thesudo
was unnecessary because the script is launched with root privileges.
If you don't know how to use a text editor on the Raspberry Pi, follow these instructions:
-
Connect to your Raspberry Pi via SSH.
-
Select the script text above and copy it to the clipboard.
-
Type the command:
$ vi isc-dhcp-fix.sh
-
Press the lower-case letter i once. That puts
vi
into insert mode. -
Paste the contents of the clipboard.
-
Press the esc key once. That takes
vi
out of insert mode. -
Press the following keys:
- : - puts
vi
into its command mode; - w - saves to
isc-dhcp-fix.sh
; and - q - tells
vi
to exit.
- : - puts
-
Check your work like this:
$ cat isc-dhcp-fix.sh
This assumes the isc-dhcp-fix.sh
is in your working directory:
$ sudo cp isc-dhcp-fix.sh /usr/bin
$ sudo chmod 555 /usr/bin/isc-dhcp-fix.sh
$ sudo chown root:root isc-dhcp-fix.sh
First, you have to identify your active network interfaces. This can be a bit trickier than you might imagine so here are some guidelines:
- Does your Raspberry Pi have an Ethernet port? If yes then it's probably
eth0
. - Does your Raspberry Pi have a WiFi on board? If yes then it's probably
wlan0
. - Have you done anything special like create a bridged network to bond
eth0
andwlan0
into a single broadcast domain? If yes then it's probablybr0
.
The test command you need depends on which interfaces are active. Here are some examples:
-
A Raspberry Pi 3 or 4 on WiFi where the Ethernet port doesn't have a cable or a Raspberry Pi W2 which is WiFi only
$ sudo isc-dhcp-fix.sh wlan0
-
A Raspberry Pi 3 or 4 where both Ethernet and WiFi are active:
$ sudo isc-dhcp-fix.sh eth0 wlan0
-
A Raspberry Pi 3 or 4 on WiFi where both Ethernet and WiFi are active but the interfaces have been tied together into a bridged network:
$ sudo isc-dhcp-fix.sh br0
The correct result is nothing. No error. No command prompt. Just silence. Wait a few seconds then press control+c to terminate the command. Then type:
$ grep -a "isc-dhcp-fix" /var/log/syslog
The
-a
flag means "process a binary file as if it were text". System logs are text files but, occasionally, seem to be misinterpreted as binary files.
You should expect to see at least one line containing the words "isc-dhcp-fix launched". If you do not see that, go back and check your work.
Use your favourite text editor to open /etc/rc.local
. It's a protected file so you will need sudo
. The following example uses the vi
text editor:
$ sudo vi /etc/rc.local
The last line of /etc/rc.local
contains exit 0
. Before the exit 0
, insert your test command from above, followed by a space and the &
character. For example:
/usr/bin/isc-dhcp-fix.sh eth0 wlan0 &
Notes:
-
Pay attention to the space followed by an ampersand (
&
) on the end of the line. It must be present. It means "run the script in the background". Your Pi will not boot correctly if you omit it. -
Remember, the new line must be before the
exit
statement. When you have finished, the last part of/etc/rc.local
should look something like this:
# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
printf "My IP address is %s\n" "$_IP"
fi
/usr/bin/isc-dhcp-fix.sh eth0 wlan0 &
exit 0
$ sudo reboot
If you did all the earlier steps correctly, rc.local
will have spawned isc-dhcp-fix.sh
as a background process during the start-up. You can see if everything is in place by:
$ grep -a "isc-dhcp-fix" /var/log/syslog
You should expect to see at least the "isc-dhcp-fix launched" from your earlier test, and another one from the reboot when isc-dhcp-fix.sh
was launched by rc.local
.
You will also see a log entry each time isc-dhcp-fix.sh
senses that one of the interfaces has stopped working and has attempted a reset.
Hint:
-
I added that
grep
of the system log to my.profile
. Whenever I login I get instant feedback ifisc-dhcp-fix.sh
has found it necessary to reset either interface. Keep in mind that the system log rolls over every 24 hours† so you will only see today's events.† this is true for Raspbian Buster. Under Bullseye, syslog rotates every week unless you change it. See the PiBuilder tutorial Restoring Buster-style log rotation for syslog if you want to know more.
isc-dhcp-fix.sh
is based on WillyWeiss/Avahi-daemon-withdraws-address-record.
Thanks !!!!