Score:1

How to get if-up script run only when the cable is plugged?

cn flag

I'm using Ubuntu 18.04 in our embedded device. I followed https://netplan.io/faq by creating "/etc/networkd-dispatcher/routable.d/50-ifup-hooks":

#!/bin/sh

echo "Interface up"
# Do something

exit 0

When the network cable is plugged in the router, the script is called. The problem is, this script got called every 5 seconds after the cable connected. I'd like just "Do something" once the network cabled is plugged in the router but not running "Do something" every 5 seconds after the cable already connected. Is there a way to make sure the script is only got called once the network cable is plugged in the router but not executed when the cable is already connected to the router?

Thanks!

Edit: Here is the ll command in /etc/networkd-dispatcher folder:

root@machine:/etc/networkd-dispatcher# ll
total 28
drwxr-xr-x  7 root root 4096 Sep 20 16:04 ./
drwxr-xr-x 77 root root 4096 Sep 16 18:03 ../
drwxr-xr-x  2 root root 4096 Sep 20 16:05 carrier.d/
drwxr-xr-x  2 root root 4096 Oct 15  2018 dormant.d/
drwxr-xr-x  2 root root 4096 Oct 15  2018 no-carrier.d/
drwxr-xr-x  2 root root 4096 Sep 20 07:12 off.d/
drwxr-xr-x  2 root root 4096 Sep 20 16:04 routable.d/

Here is the ll command for carrier.d folder:

root@machine:/etc/networkd-dispatcher# ll carrier.d/
total 12
drwxr-xr-x 2 root root 4096 Sep 20 16:05 ./
drwxr-xr-x 7 root root 4096 Sep 20 16:04 ../
-rwxr-xr-x 1 root root  209 Sep 20 16:05 50-ifup-hooks*
Kev Inski avatar
us flag
According to `man networkctl` scripts under `routable.d` get executed when 'the link has carrier and routable address configured'. My guess is that on every lease update, the script gets executed. Try putting the script in the folder `carrier.d` - it should only get executed when there is a carrier. But it depends on the use-case you are trying to achieve. Like: "do something when the cable is plugged in" or "do something when the link gets a (probably new) address"
cn flag
Thanks @Kev Inski. That "Do something" is "Do DHCP release/renew". What we wanted to do is to do DHCP release/renew once the network cable is plugged. That explains why the script is kept getting called. By following your suggestion, I created the folder /etc/networkd-dispatcher/carrier.d folder(as it didn't exist by default. Not sure if it's correct by manually created the folder). Then I moved the script to "carrier.d" folder. I restarted the service. But there is nothing happen when the cable is plugged. Am I doing it right? Is there a better way to achieve my goal?
Kev Inski avatar
us flag
I'm setting up a 18.04 VM and try to test this. It's a lillte bit odd that the folder did not exist, but I'll look into it. Is the newly created folder `carrier.d` owned by root with 0755 permissions? Is the script executable and owned by root. You may want to edit your question. `ll /etc/networkd-dispatcher/` or maybe `tree /etc/networkd-dispatcher/` would also be nice to see. Is it a 18.04 server (since it's an embedded device) or a "normal" desktop version?
Kev Inski avatar
us flag
I think I've found out why this is not working for you or for Ubuntu 18.04. The problem lies in the version of `systemd`, which provides the networking stuff. Ubuntu 18.04 uses systemd version 237, where Ubuntu 20.04 uses the version 245. Therefore my provided solution will not work since you are not able to detect the state-change with netplan. The only solution I see is either upgrade to ubuntu 20.04 (which may not be possible) or use the 'old' `ifupdown` to replace netplan. (manual installation/compilation of systemd is also an option but not recommended.)
cn flag
Thanks @Kev Inski. Upgrading to Ubuntu 20.04 isn't an option for now. Switching to the "old" ifupdown isn't an option either. One solution I'm thinking is to check the status of the network interfaces. Based on https://linuxconfig.org/how-to-detect-whether-a-physical-cable-is-connected-to-network-card-slot-on-linux, I could use "for i in $( ls /sys/class/net ); do echo -n $i: ; cat /sys/class/net/$i/carrier; done" to periodically check the network interface status. If any network interface's status changed from 0 to 1, I'll run DHCP release/renew. Do you think that'll work? Thanks.
cn flag
@Kev Inski Is there a way that we can tell the difference between a cable plug and a DHCP address renew in the carrier.d/50-ifup-hooks script? If there is a way, then I can just do DHCP release/renew for the cable plug but not for the address update. Thanks.
Score:0
us flag

Maybe that little script can help you. That can even be called as intended by netplan (systemd) from the routable.d folder if you uncomment #NETDEV=${IFACE}. Of course it's not final and needs a bit of work but you are free to use it as a basis.

#!/bin/bash

NETDEV=enp0s3
#NETDEV=${IFACE}
TMP_FILE=/tmp/link_state-${NETDEV}
OLD_STATE=
HAS_CARRIER="CARRIER"
HAS_NO_CARRIER="NO_CARRIER"

if [ -e "${TMP_FILE}" ]; then
    OLD_STATE=$(cat "${TMP_FILE}")
fi
    
echo "old_state: ${OLD_STATE}"

RESULT=$(ip link show dev "${NETDEV}" | grep '<NO_CARRIER')
RETVAL=$?

if [ ${RETVAL} -eq 1 ]; then
    echo "has a carrier"
    if [ "${OLD_STATE}" = "${HAS_CARRIER}" ]; then
        echo "no state change"
    else
        echo -n "${HAS_CARRIER}" > "${TMP_FILE}"
    fi
else
    echo "${NETDEV} state is currently ${HAS_NO_CARRIER}"
    if [ "${OLD_STATE}" = "${HAS_NO_CARRIER}" ]; then
        echo "no state change"
    else
        echo -n "${HAS_NO_CARRIER}" > "${TMP_FILE}"
    fi
fi
cn flag
Thanks @Kev Inski I uncommented the "#NETDEV=${IFACE}" line. There is nothing happen when I plug in the cable. Then I modified the line to use our interface "NETDEV=pan0". When I plug in the cable, the first "if" got run, and further the embedded "if" got run as well. However, after I put "/sbin/dhclient -r /sbin/dhclient" in there, this part of code got run in a loop again. That means, when I plug in the cable, the DHCP release/renew got running every 5 seconds. So the question is, is there a way to tell the difference between a cable plug event and a DHCP address renew?
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.