如何检测网络电缆/连接器的物理连接状态?

时间:2009-04-30 19:08:08

标签: linux networking connection detection

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

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

  1. 使用'ifconfig' - 因为网络电缆可能已连接但网络未正确配置或当前未正常运行。
  2. Ping主机 - 因为产品将位于使用未知网络配置和未知主机的LAN中。
  3. 是否有某些状态可以在/ proc文件系统中使用(其他所有内容都在那里)?

    Linux世界是如何设置自己的Windows泡泡版本,从图标托盘弹出,表明您刚刚拔掉了网线?


    Kent Fredric lothar ,您的两个答案都满足了我的需求......非常感谢!我将使用哪一个......我仍然不知道。

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

16 个答案:

答案 0 :(得分:204)

您想查看

中的节点
/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对列表。

答案 1 :(得分:78)

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

答案 2 :(得分:24)

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

答案 3 :(得分:17)

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

接口必须是up,否则你会得到一个无效的参数错误。

首先:

ifconfig ethX up

然后:

cat /sys/class/net/ethX

答案 4 :(得分:8)

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

答案 5 :(得分:4)

有两个守护进程可以检测到这些事件:

ifplugd netplugd

答案 6 :(得分:2)

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

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

答案 7 :(得分:2)

我使用此命令检查电线是否已连接:

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

如果结果是向上或向下。有时它显示未知,那么你需要检查

eth0/carrier

显示0或1

答案 8 :(得分: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
    

    取决于状态,消息可能因使用的硬件和驱动程序而异。

    Nota:这可以写成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
    

    (点击输入退出循环)

    注意:这需要安装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

答案 9 :(得分:1)

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

答案 10 :(得分:0)

在arch linux上。 (我不确定在其他发行版上)你可以查看operstate。如果没有,那么如果没有,那就会显示出连接或关闭

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

答案 11 :(得分:0)

可以使用ifconfig。

# ifconfig eth0 up
# ifconfig eth0

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

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

答案 12 :(得分: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。

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

答案 13 :(得分:0)

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

答案 14 :(得分: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”。

答案 15 :(得分:0)

仅使用命令行。

我在一些答案中发现的一个问题是,并非每台计算机都存在 eth0!在我的笔记本电脑中,名称完全不同。例如:enp2s0f1

这是我的解决方案和脚本。如果您的计算机有多个以太网,请跳过步骤 1,直接在步骤 2 中传递所需的以太网名称:

1- 以编程方式获取以太网名称(对于只有一个的计算机):

$ ethname=`ifconfig | grep -E -o -m 1 "^[a-z0-9]+"`

2- 拥有正确的以太网名称,将其传递给 ifconfig,然后搜索“inet”字符串,表示插入电缆时的活动。

$ plugged=`ifconfig $ethname | grep -E -o -m 1 "inet"`