如何检测网线/连接器的物理连接状态?


145

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

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

  1. 使用“ ifconfig”-由于可以连接网络电缆,但是网络配置不正确或当前未启动。
  2. ping主机-因为产品将使用未知的网络配置和未知的主机位于LAN内。

在/ proc文件系统中没有可用的某种状态(其他所有文件都在其中)吗?

Linux世界应该如何在图标托盘中弹出自己的Windows气泡版本,以表明您刚刚拔下网络电缆?


肯特·弗雷德里克Kent Fredric)洛萨(lothar),您的回答都满足了我的需求……非常感谢!我会用哪一个...我还是不知道。

我想我不能把你们俩都当成正确的答案吗?我选择其中一种可能对您很公平。我猜是掷硬币吗?再次感谢!

Answers:


228

您要查看中的节点

/ sys / class / net /

我尝试了我的:

电线插入:

eth0/carrier:1
eth0/operstate:unknown

电线拆除:

eth0/carrier:0
eth0/operstate:down

电线再次插入:

eth0/carrier:1
eth0/operstate:up

Side Trick:轻松收获一次所有财产:

grep "" eth0/* 

这形成了一个不错的key:value配对列表 。


8
请注意,正如Marco在下面说的那样,必须打开接口(即使未配置)才能查询这些值。
杰米·基特森

11
grep“” eth0 / *非常简洁易用,谢谢!:)使用-s开关,grep不会抱怨目录。

2
我更喜欢::grep -H . eth0/*此鞭打空行和带有打印条目名称分别属于每行。
F. Hauri

关于grep目录的错误可以通过以下方式忽略:grep -s "" eth0/*
mrtumnus

请注意,接口必须打开。请参阅下面的Marco答案。在我的系统中,默认情况下未设置eth0,我的程序会随机为其生成IP地址。我得到一个“无效参数”错误从catting载体
VocoJax

84

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

ip链接| grep广播| cut -d':'-f 2 | 一边读我 回显$ i; ethtool $ i | grep链接; 完成
布莱恩·亨特

3
请注意,正如Marco在下面说的那样,必须打开接口(即使未配置)才能查询这些值。
杰米·基特森

这太棒了!我有一种方法来检查以太网是否可用,是否启用了以太网,是否连接了以太网,但是没有办法检查实际的电缆是否已连接。grep Link可以。谢谢!!
ᴛʜᴇᴘᴀᴛᴇʟ

在这里不工作。HP硬件上的Ubuntu 16.04。未配置的接口是“无链接”的,即使强制up状态也是如此。
0xF2

26

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


3
就我而言,这是唯一可行的答案... / sys / class / net / eth0 / carrier仍然显示1何时断开电缆连接,而ip monitor实际上却显示出一些东西
Tim Tisdall 2014年

彼得,对此方法的一些扩展表示感谢。像任何示例一样,它回答了有关了解电缆插头状态的原始问题。
Sopalajo de Arrierez '18

17

cat /sys/class/net/ethX 到目前为止,这是最简单的方法。

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

所以首先:

ifconfig ethX up

然后:

cat /sys/class/net/ethX

4
尝试“ cat / sys / class / net / eth [n] / operstate”,其中[n]是eth设备号。
pmont

这只会告诉您eth [n]是否接通,如果eth [n]断开,则不会告诉您电缆是否已连接。
布里斯

@Brice,实际上,如果要ethX/carrier检测到“载体” ,则要检查文件为1,这意味着电缆已连接并正在传输数据……
Alexis Wilke,2016年

这对我有用Process Runtime Exec命令检查在Android中电缆是否已连接。
阿林

或者,在ifconfig ethX启动后,ifconfig ethX并查找RUNNING。
craig65535

8

在较低级别,可以使用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地址将被自动删除。


4

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

ifplugdnetplugd


我使用守护程序中的ifplugstatus工具ifplugd。无需输入参数,只需键入ifplugstatus,即可插入或拔出所有NIC。
Sopalajo de Arrierez,

3

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

如果您想让命令行工具检查状态,则mii-tool考虑到以太网,也可以使用。


3
mii-tool已被ethtool取代。mii-tool不知道GigE链接。
JimB

此外,大多数服务器具有手动配置的适配器,NM会忽略它们。
JimB

1
mii-tool当接口关闭时,似乎是唯一可以报告链接状态的命令。
donothingsuccessally


2

一些技巧和窍门

  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更多信息。


感谢您的意见和建议。虽然,您确实意识到这些是“自动化”脚本。在第2点中,当您说“输出” “另一个输出”时,或者当您说“ 根据状态而定时,消息可能会根据所使用的硬件和驱动程序而有所不同 ”……这是一个很大的问题。输出必须一致或生产脚本开始中断。但这是很好的信息,谢谢。
Jeach

@Jeach输出可能会有所不同:您可以使用以外的其他驱动程序,e1000在以外的其他时间发生936555.596870偶发事件,但是始终可以看到NIC Link is
F. Hauri

2

可以使用ifconfig。

# ifconfig eth0 up
# ifconfig eth0

如果条目显示“正在运行”,则表明接口已物理连接。无论是否配置了界面,都将显示此内容。

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


你节省了我的时间!
ADITYA VALLURU

1

在Arch Linux上。(我不确定在其他发行版上),您可以查看该剧本。如果已连接,则显示为向上;如果未连接,则显示为向下

/sys/class/net/(interface name here)/operstate
#you can also put watch 
watch -d -n -1 /sys/class/net/(interface name here)/operstate

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

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。


0

我将我的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。

希望这至少可以帮助到别人!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.