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

Posted

技术标签:

【中文标题】如何检测网线/连接器的物理连接状态?【英文标题】:How to detect the physical connected state of a network cable/connector? 【发布时间】:2010-10-22 22:54:24 【问题描述】:

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

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

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

难道没有一些状态可以在 /proc 文件系统中使用(其他的都在里面)吗?

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


Kent Fredriclothar,您的两个答案都满足了我的需求……非常感谢!我会用哪一个……我还是不知道。

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

【问题讨论】:

【参考方案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

【讨论】:

ifconfig 已过时,不建议使用 谢谢你告诉我!【参考方案2】:

在 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”。

【讨论】:

【参考方案3】:

如果你想在命令后检查以太网电缆是否插入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。

【讨论】:

【参考方案4】:

你要查看节点

/sys/类/网/

我用我的做实验:

电线插入:

eth0/carrier:1
eth0/operstate:unknown

拆线:

eth0/carrier:0
eth0/operstate:down

再次插入电线:

eth0/carrier:1
eth0/operstate:up

小窍门:一次收获所有属性的简单方法:

grep "" eth0/* 

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

【讨论】:

请注意,正如 Marco 在下面所说,接口必须启动(即使未配置)才能查询这些值。 grep "" eth0/* 非常优雅和简单,谢谢! :) 使用 -s 开关 grep 不会抱怨目录。 我更喜欢:grep -H . eth0/*:这条鞭打空行和打印条目名称属于每一行。 可以忽略 grep 中的目录错误:grep -s "" eth0/* 注意接口必须是up的。请参阅下面的 Marco 的回答。在我的系统中,默认情况下没有设置 eth0,我的程序会随机为其生成一个 IP 地址。我在寻找承运人时收到“无效参数”错误【参考方案5】:
tail -f /var/log/syslog | grep -E 'link (up|down)'

或者对我来说更快得到:

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

它将监听系统日志文件。

结果(如果断开连接并在 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

【讨论】:

【参考方案6】:

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

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

【讨论】:

【参考方案7】:

可以使用 ifconfig。

# ifconfig eth0 up
# ifconfig eth0

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

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

【讨论】:

【参考方案8】:

在 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

【讨论】:

【参考方案9】:

一些精度和技巧

    我以普通用户(不是root)的身份完成所有这些操作

    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
    

    围绕/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

    好吧,这肯定已经有什么了……

    根据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 了解更多信息。

【讨论】:

感谢您的 cmets 和对此事的意见。虽然,您确实意识到这些是“自动化”脚本。在第 2 点中,当您说输出“”另一个输出时,或者当您说“取决于状态,消息可能因使用的硬件和驱动程序而异”...这是一个真正的大问题。输出必须一致,否则生产脚本开始中断。但无论如何,这都是很好的信息,谢谢。 @Jeach 输出可能会有所不同意味着:您可以使用除e1000之外的其他驱动程序,并且事件可能发生在936555.596870以外的其他时间,但你总会看到 NIC Link is.【参考方案10】:

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

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

结果是向上还是向下。有时显示未知,那你需要检查一下

eth0/carrier

显示0或1

【讨论】:

【参考方案11】:

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

ifplugdnetplugd

【讨论】:

我使用来自ifplugd 守护进程的ifplugstatus 工具。无需参数,只需键入ifplugstatus,您将获得所有 NIC 的插入或拔出状态。【参考方案12】:

使用“ip monitor”获取实时链接状态变化。

【讨论】:

就我而言,这是唯一有效的答案... /sys/class/net/eth0/carrier 当我的电缆断开时仍然显示1ip monitor 实际上显示了一些东西 感谢彼得,对这种方法进行了一些扩展。类似于回答有关了解电缆插头状态的原始问题的任何示例。【参考方案13】:

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

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

首先:

ifconfig ethX up

然后:

cat /sys/class/net/ethX

【讨论】:

尝试“cat /sys/class/net/eth[n]/operstate”,其中 [n] 是 eth 设备号。 这只会告诉你 eth[n] 是否启动,如果它关闭,它不会告诉你电缆是否连接。 @Brice,确实,你想检查文件ethX/carrier,如果检测到“运营商”,则该文件为 1,这意味着电缆已连接并传输数据...... 这对我有用,它使用 Process Runtime Exec 命令检查电缆是否在 android 中连接。 或者,在 ifconfig ethX up 之后, ifconfig ethX 并寻找 RUNNING。【参考方案14】:

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

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

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

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地址将自动删除。

【讨论】:

【参考方案15】:

你可以使用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 链接;完成 请注意,正如 Marco 在下面所说,接口必须启动(即使未配置)才能查询这些值。 这太棒了!我有办法检查以太网是否可用,以太网是否启用,以太网是否已连接,但无法检查实际电缆是否已连接。 grep Link 做到了。谢谢!! 这里不工作。 HP 硬件上的 Ubuntu 16.04。未配置的接口是“无链接”,即使强制为up 状态。【参考方案16】:

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

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

【讨论】:

mii-tool 已被 ethtool 取代。 mii-tool 不知道 GigE 链接。 另外,大部分服务器都手动配置了适配器,NM会忽略。 mii-tool 似乎是接口关闭时唯一可以报告链路状态的命令。

以上是关于如何检测网线/连接器的物理连接状态?的主要内容,如果未能解决你的问题,请参考以下文章

socket编程中,服务器如何检测到客户端网络连接的断开.比如说客户端的网线断掉了,从服务端如何能检测到呢l

使用firebase时如何检测设备连接状态? [复制]

“Linux”中如何判断哪个网卡连接网线?

Linux 如何判断哪个网卡是不是连接网线

SignalR:检测客户端上的连接状态

Swift - 如何在 iOS 应用中检测 CarPlay 的连接/断开状态?