How to detect the physical connected state of a ne

2019-01-12 13:55发布

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:

  1. Using 'ifconfig' - since a network cable may be connected but the network not properly configured or not currently up.
  2. Ping a host - since the product will be within a LAN using an unknown network configuration and unknown hosts.

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!

11条回答
你好瞎i
2楼-- · 2019-01-12 14:01

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.

查看更多
趁早两清
3楼-- · 2019-01-12 14:02

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/operstate:up
eth0/carrier:1

Side Trick: harvesting all properties at once the easy way:

grep "" eth0/* 

This forms a nice list of key:value pairs.

查看更多
虎瘦雄心在
4楼-- · 2019-01-12 14:05

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

查看更多
孤傲高冷的网名
5楼-- · 2019-01-12 14:08

Some precisions and tricks

  1. I do all this as normal user (not root)

  2. 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
    
  3. Test around /sys pseudo filesystem

    Reading or writting under /syscould 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.

  4. 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.

查看更多
放荡不羁爱自由
6楼-- · 2019-01-12 14:09

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
查看更多
孤傲高冷的网名
7楼-- · 2019-01-12 14:09

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.

查看更多
登录 后发表回答