154

在 Linux 环境中,我需要检测 RJ45 连接器与其插座的物理连接或断开状态。最好只使用 BASH 脚本。

以下已在其他站点上提出的解决方案不适用于此目的:

  1. 使用“ifconfig” - 因为可能连接了网络电缆,但网络未正确配置或当前未启动。
  2. Ping 主机 - 因为产品将在 LAN 中使用未知的网络配置和未知的主机。

/proc 文件系统中是否没有某些状态可以使用(其他所有内容都在其中)?

Linux 世界如何假设有他们自己版本的 Windows 气泡,它会从图标托盘中弹出,表明您刚刚拔掉了网络电缆?


肯特弗雷德里克洛塔尔,你的两个答案都满足了我的需要......非常感谢!我会用哪一个……我还是不知道。

我想我不能把你们两个都当作正确答案?我确实选择了一个,这对你来说可能是公平的。我猜掷硬币?再次,谢谢!

4

16 回答 16

241

你想看看节点

/sys/类/网/

我用我的实验:

电线插入:

eth0/carrier:1
eth0/operstate:unknown

拆线:

eth0/carrier:0
eth0/operstate:down

再次插入电线:

eth0/carrier:1
eth0/operstate:up

小技巧:一次收获所有属性的简单方法:

grep "" eth0/* 

这形成了一个很好的 key:value对列表。

于 2009-04-30T19:17:51.647 回答
91

您可以使用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

要仅获取链接状态,您可以使用 grep:

$ sudo ethtool eth0 | grep Link
    Link detected: yes
于 2009-04-30T19:17:07.797 回答
27

使用“ip monitor”获取实时链接状态更改。

于 2012-09-05T21:13:07.717 回答
18

cat /sys/class/net/ethX是迄今为止最简单的方法。

接口必须启动,否则您将收到无效参数错误。

所以首先:

ifconfig ethX up

然后:

cat /sys/class/net/ethX
于 2011-11-01T14:51:36.137 回答
9

在底层,可以使用rtnetlink套接字捕获这些事件,无需任何轮询。旁注:如果您使用 rtnetlink,则必须与 udev 一起工作,否则当 udev 重命名新的网络接口时,您的程序可能会混淆。

使用 shell 脚本进行网络配置的问题在于shell 脚本对于事件处理(例如插入和拔出网络电缆)非常糟糕。如果您需要更强大的功能,请查看我的NCD 编程语言,这是一种专为网络配置而设计的编程语言。

例如,一个简单的 NCD 脚本将打印“cable in”和“cable out”到标准输出(假设接口已经启动):

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 :)
}

(内部net.backend.waitlink()使用 rtnetlink,net.backend.waitdevice()使用 udev)

NCD 的想法是您专门使用它来配置网络,因此通常配置命令会介于两者之间,例如:

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");
}

需要注意的重要部分是允许执行倒退;在第二个例子中,例如,如果电缆被拔出,IP 地址将自动被删除。

于 2011-11-01T15:25:10.450 回答
5

存在两个检测这些事件的守护进程:

ifplugdnetplugd

于 2013-08-29T23:27:41.303 回答
4

我使用这个命令来检查电线是否连接:

cd /sys/class/net/
grep "" eth0/operstate

如果结果将向上或向下。有时显示未知,则需要检查

eth0/carrier

它显示 0 或 1

于 2014-08-19T05:59:54.303 回答
3

大多数现代 Linux 发行版为此使用NetworkManager 。您可以使用 D-BUS 来监听事件。

如果你想要一个命令行工具来检查状态,你也可以使用mii-tool,因为你有以太网。

于 2009-04-30T19:16:30.903 回答
3

一些精度和技巧

  1. 我作为普通用户(不是root)做这一切

  2. 从获取信息dmesg

    使用是查询系统当前状态dmesg的第一件事:

    dmesg | sed '/eth.*Link is/h;${x;p};d'
    

    可以回答如下:

    [936536.904154] e1000e: eth0 NIC Link is Down
    

    或者

    [936555.596870] e1000e: eth0 NIC Link is Up 100 Mbps Full Duplex, Flow Control: Rx/Tx
    

    根据状态,消息可能会因使用的硬件和驱动程序而异。

    注意:这可以写dmesg|grep eth.*Link.is|tail -n1,但我更喜欢使用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. 围绕/sys伪文件系统进行测试

    阅读或写作/sys可能会破坏您的系统,特别是如果以root身份运行!您已被警告;-)

    这是一种池化方法,而不是真正的事件跟踪

    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
    

    可以呈现类似的东西(一旦你拔掉并插回去,取决于):

    +++ -   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
    

    (点击Enter退出循环)

    注意:这需要patch安装。

  4. 好吧,这一定已经有什么东西了……

    根据Linux 安装,您可以添加能够对此类事件做出反应的脚本if-upif-down

    基于Debian(如Ubuntu),您可以将脚本存储到

    /etc/network/if-down.d
    /etc/network/if-post-down.d
    /etc/network/if-pre-up.d
    /etc/network/if-up.d
    

    查看man interfaces更多信息。

于 2016-11-18T13:38:22.887 回答
1

在拱 linux 上。(我不确定在其他发行版上)您可以查看操作状态。如果连接则显示,如果不存在则显示关闭

/sys/class/net/(interface name here)/operstate
#you can also put watch 
watch -d -n -1 /sys/class/net/(interface name here)/operstate
于 2017-10-06T12:06:11.980 回答
1

可以使用 ifconfig。

# ifconfig eth0 up
# ifconfig eth0

如果条目显示 RUNNING,则接口已物理连接。无论是否配置了接口,都会显示此信息。

这只是获取信息的另一种方式/sys/class/net/eth0/operstate

于 2018-12-14T00:10:54.337 回答
1
tail -f /var/log/syslog | grep -E 'link (up|down)'

或者对我来说更快得到:

tail -f /var/log/syslog | grep 'link \(up\|down\)'

它将监听 syslog 文件。

结果(如果断开连接并在 4 秒后再次连接):

Jan 31 13:21:09 user kernel: [19343.897157] r8169 0000:06:00.0 enp6s0: link down
Jan 31 13:21:13 user kernel: [19347.143506] r8169 0000:06:00.0 enp6s0: link up
于 2019-01-31T21:25:36.530 回答
1

不知何故,如果您想检查以太网电缆是否在推荐后插入linux:“ifconfig eth0 down”。我找到了解决方案:使用 ethtool 工具。

#ethtool -t eth0
The test result is PASS
The test extra info:
Register test  (offline)         0
Eeprom test    (offline)         0
Interrupt test (offline)         0
Loopback test  (offline)         0
Link test   (on/offline)         0

如果连接了电缆,则链路测试为 0,否则为 1。

于 2019-10-28T00:42:42.927 回答
1

此命令在“ip a”命令的第二个界面中检查“状态 UP”。我已经检查了 2 台运行 wifi 的计算机,列出的第二台是有线以太网。如果您想检查不同的接口,只需将下面命令中的“2”更改为正确的索引位置。

astate=`ip a | grep -E -o -m 1 "2:.*state UP"`  
if [ -n "$astat" ]; then
   echo 'cable is on'
else
   echo 'cable is off'
fi
于 2021-03-08T13:41:22.083 回答
0

在 OpenWRT 上,至少对我而言,可靠地做到这一点的唯一方法是运行以下命令:

# Get switch name
swconfig list

# assuming switch name is "switch0"
swconfig dev switch0 show | grep link:

# Possible output
root@OpenWrt:~# swconfig dev switch0 show | grep link:
        link: port:0 link:up speed:1000baseT full-duplex txflow rxflow
        link: port:1 link:up speed:1000baseT full-duplex txflow rxflow eee100 eee1000 auto
        link: port:2 link:up speed:1000baseT full-duplex txflow rxflow eee100 eee1000 auto
        link: port:3 link:down
        link: port:4 link:up speed:1000baseT full-duplex eee100 eee1000 auto
        link: port:5 link:down
        link: port:6 link:up speed:1000baseT full-duplex txflow rxflow

这将在交换机的每个端口上显示“link:down”或“link:up”。

于 2020-10-06T16:30:45.003 回答
-1

我将我的 OpenWRT 增强型设备用作中继器(它添加了虚拟以太网和无线局域网功能),发现 /sys/class/net/eth0 运营商和 opstate 值不可靠。我玩弄了 /sys/class/net/eth0.1 和 /sys/class/net/eth0.2 以及(至少在我的发现)没有可靠的方法来检测是否有东西被物理插入并正在谈论任何东西的以太网端口。我想出了一种粗略但看似可靠的方法来检测至少自上次重新启动/开机状态以来是否插入了任何东西(在我的情况下,这完全符合我的需要)。

ifconfig eth0 | grep -o 'RX packets:[0-9]*' | grep -o '[0-9]*'

如果自上次开机或重新启动循环以来没有插入任何东西,则如果没有插入任何东西(即使已插入并且已移除),您将获得 0 和大于 0 的值。

希望这至少可以帮助某人!

于 2019-01-13T00:51:07.880 回答