In a Linux environment, I need to detect the physical connected or disconnected state of an RJ45 connector to its socket. Preferably using BASH scripting only.
The following solutions which have been proposed on other sites do NOT work for this purpose:
Isn't there some state which can be used in the /proc file system (everything else is in there)?
How is the Linux world suppose to have their own version of the Windows bubble that pop up from the icon tray indicating that you've just unplugged the network cable?
Kent Fredric and lothar, both of your answers satisfy my need... thanks a lot! Which one I'll use... I still don't know.
I guess I can't put you both down as the correct answer? And its probably fair for you that I do choose one. Flip a coin I guess? Again, thanks!
The best way to check the network interface in Linux is to use the ifconfig command. To do this, simply open a terminal and type “ifconfig -a”. This will return a list of all available network interfaces on your system.
The RJ45, Registered Jack 45 connector is used almost universally as the physical connector used on Ethernet cables, and with networking cables in general.
You can cat /sys/class/net/eth0/carrier , to check for a signal, but it still may not have a DHCP lease yet, etc.
Look for a green light on the back of your modem. At the plug where the LAN cable connects, modems usually have a light indicating the signal strength. A green light indicates a good connection. Yellow or red lights indicate signal problems. If the light is not green, then check your connection or test the cable.
You want to look at the nodes in
/sys/class/net/
I experimented with mine:
Wire Plugged in:
eth0/carrier:1
eth0/operstate:unknown
Wire Removed:
eth0/carrier:0
eth0/operstate:down
Wire Plugged in Again:
eth0/carrier:1
eth0/operstate:up
Side Trick: harvesting all properties at once the easy way:
grep "" eth0/*
This forms a nice list of key:value
pairs.
You can use ethtool:
$ sudo ethtool eth0
Settings for eth0:
Supported ports: [ TP ]
Supported link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Supports auto-negotiation: Yes
Advertised link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Advertised auto-negotiation: Yes
Speed: 1000Mb/s
Duplex: Full
Port: Twisted Pair
PHYAD: 0
Transceiver: internal
Auto-negotiation: on
Supports Wake-on: umbg
Wake-on: g
Current message level: 0x00000007 (7)
Link detected: yes
To only get the Link status you can use grep:
$ sudo ethtool eth0 | grep Link
Link detected: yes
Use 'ip monitor' to get REAL TIME link state changes.
cat /sys/class/net/ethX
is by far the easiest method.
The interface has to be up though, else you will get an invalid argument error.
So first:
ifconfig ethX up
Then:
cat /sys/class/net/ethX
On the low level, these events can be caught using rtnetlink sockets, without any polling. Side note: if you use rtnetlink, you have to work together with udev, or your program may get confused when udev renames a new network interface.
The problem with doing network configurations with shell scripts is that shell scripts are terrible for event handling (such as a network cable being plugged in and out). If you need something more powerful, take a look at my NCD programming language, a programming language designed for network configurations.
For example, a simple NCD script that will print "cable in" and "cable out" to stdout (assuming the interface is already up):
process foo {
# Wait for device to appear and be configured by udev.
net.backend.waitdevice("eth0");
# Wait for cable to be plugged in.
net.backend.waitlink("eth0");
# Print "cable in" when we reach this point, and "cable out"
# when we regress.
println("cable in"); # or pop_bubble("Network cable in.");
rprintln("cable out"); # or rpop_bubble("Network cable out!");
# just joking, there's no pop_bubble() in NCD yet :)
}
(internally, net.backend.waitlink()
uses rtnetlink, and net.backend.waitdevice()
uses udev)
The idea of NCD is that you use it exclusively to configure the network, so normally, configuration commands would come in between, such as:
process foo {
# Wait for device to appear and be configured by udev.
net.backend.waitdevice("eth0");
# Set device up.
net.up("eth0");
# Wait for cable to be plugged in.
net.backend.waitlink("eth0");
# Add IP address to device.
net.ipv4.addr("eth0", "192.168.1.61", "24");
}
The important part to note is that execution is allowed to regress; in the second example, for instance, if the cable is pulled out, the IP address will automatically be removed.
There exists two daemons that detect these events:
ifplugd and netplugd
I use this command to check a wire is connected:
cd /sys/class/net/
grep "" eth0/operstate
If the result will be up or down. Sometimes it shows unknown, then you need to check
eth0/carrier
It shows 0 or 1
Most modern Linux distributions use NetworkManager for this. You could use D-BUS to listen for the events.
If you want a command-line tool to check the status, you can also use mii-tool
, given that you have Ethernet in mind.
I do all this as normal user (not root)
Grab infos from dmesg
Using dmesg
is one of the 1st things to do for inquiring current state of system:
dmesg | sed '/eth.*Link is/h;${x;p};d'
could answer something like:
[936536.904154] e1000e: eth0 NIC Link is Down
or
[936555.596870] e1000e: eth0 NIC Link is Up 100 Mbps Full Duplex, Flow Control: Rx/Tx
depending on state, message could vary depending on hardware and drivers used.
Nota: this could by written dmesg|grep eth.*Link.is|tail -n1
but I prefer using sed
.
dmesg | sed '/eth.*Link is/h;${x;s/^.*Link is //;p};d'
Up 100 Mbps Full Duplex, Flow Control: Rx/Tx
dmesg | sed '/eth.*Link is/h;${x;s/^.*Link is //;p};d'
Down
Test around /sys
pseudo filesystem
Reading or writting under /sys
could break your system, especially if run as root! You've been warned ;-)
This is a pooling method, not a real event tracking.
cd /tmp
grep -H . /sys/class/net/eth0/* 2>/dev/null >ethstate
while ! read -t 1;do
grep -H . /sys/class/net/eth0/* 2>/dev/null |
diff -u ethstate - |
tee >(patch -p0) |
grep ^+
done
Could render something like (once you've unplugged and plugged back, depending ):
+++ - 2016-11-18 14:18:29.577094838 +0100
+/sys/class/net/eth0/carrier:0
+/sys/class/net/eth0/carrier_changes:9
+/sys/class/net/eth0/duplex:unknown
+/sys/class/net/eth0/operstate:down
+/sys/class/net/eth0/speed:-1
+++ - 2016-11-18 14:18:48.771581903 +0100
+/sys/class/net/eth0/carrier:1
+/sys/class/net/eth0/carrier_changes:10
+/sys/class/net/eth0/duplex:full
+/sys/class/net/eth0/operstate:up
+/sys/class/net/eth0/speed:100
(Hit Enter to exit loop)
Nota: This require patch
to be installed.
In fine, there must already be something about this...
Depending on Linux Installation, you could add if-up
and if-down
scripts to be able to react to this kind of events.
On Debian based (like Ubuntu), you could store your scripts into
/etc/network/if-down.d
/etc/network/if-post-down.d
/etc/network/if-pre-up.d
/etc/network/if-up.d
see man interfaces
for more infos.
on arch linux. (im not sure on other distros) you can view the operstate. which shows up if connected or down if not the operstate lives on
/sys/class/net/(interface name here)/operstate
#you can also put watch
watch -d -n -1 /sys/class/net/(interface name here)/operstate
You can use ifconfig.
# ifconfig eth0 up
# ifconfig eth0
If the entry shows RUNNING, the interface is physically connected. This will be shown regardless if the interface is configured.
This is just another way to get the information in /sys/class/net/eth0/operstate
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With