「Wi-Fiまたはイーサネット経由」スクリプト[閉じる]

「Wi-Fiまたはイーサネット経由」スクリプト[閉じる]

Wi-Fiまたはイーサネットで接続できるホストがあります。リンクにしたがってアクションをとりたいです。

スクリプトでこれをどのように検出しますか?

答え1

各リンクタイプに使用されるインターフェイスは異なります。イーサネットインターフェイスは異なる場合があります。eth0WLANインターフェイスは無線LAN0。活動中の名前を知り、それに応じて行動します。

すべてのインターフェイスを一覧表示してそのステータスを表示するには、コマンドを使用しますip link show。このコマンドはLinuxの最新バージョンで動作するため、残りのユーティリティとBashシェルもすべてのOSに適用できると仮定します(Windowsではcygwinを使用することをお勧めします。アッまたはPythonで解析するIP構成またはNetsh出力またはPowerShell Get-NetAdapterモジュール)。

出力例:

user@host$ ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group     default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 00:50:56:9b:90:7d brd ff:ff:ff:ff:ff:ff

grepその後、数字で始まる行を見つけてインターフェイス名/ステータスをフィルタリングできます。

user@host$ ip link show | grep "^[0-9]"
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group     default qlen 1
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000

アクティブインタフェースにはUPという単語があるため、アクティブインタフェースを取得するにはローカルインタフェースlocalhost(見てください:):

user@host$ ip link show | grep "^[0-9]" | grep -v "lo: " | grep "UP"
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000

インターフェイス名、つまり2番目の単語だけが必要です。

user@host$ ip link show | grep "^[0-9]" | grep -v "lo: " | grep "UP" | cut -d ':' -f 2
 ens32

この結果を一部の変数(Bash)に保存できます。

ACTIVEIF=$(ip link show | grep "^[0-9]" | grep -v "lo: " | grep "UP" | cut -d ':' -f 2)

もちろん、アクティブなインターフェイスが複数ある場合は、結果の周りに括弧とスペースを追加して名前の配列にリストを保存します。これからは物理インターフェイスが 1 つだけなので lo: をフィルタリングしません。):

ACTIVEIFACES=( $(ip link show | grep "^[0-9]" | grep "UP" | cut -d ':' -f 2) )

配列変数の内容を確認するには:

user@host$ set | grep ^ACTIVEIFACES
ACTIVEIFACES=([0]="lo" [1]="ens32")

スクリプトにリストします。

ACTIVEIFACES=( $(ip link show | grep "^[0-9]" | grep "UP" | cut -d ':' -f 2) )
NIFACES=${#ACTIVEIFACES[@]}
if [ $NIFACES -ne 0 ] ; then
   echo "There exist $NIFACES active interfaces:"
   for ((i=0; i<NIFACES; i++)) ; do
       echo "${ACTIVEIFACES[$i]}"
   done
else
   echo "There is no active interfaces detected"
fi

(このforコマンドは数値式を使用するため、二重括弧の間の$ iと$NIFACESの$を省略できます。)

私の場合、スクリプトの出力は次のようになります。

There exist 2 active interfaces:
lo
ens32

この方法があなたにうまくいくことを願っています。頑張ってください!

答え2

素朴な答えはインターフェイスを監視することですが、接続(イーサネット)または接続(WiFi)の場合、レイヤ2インターフェイスは「上」に登録されますが、それ自体がトラフィックを転送するために使用されるかどうかはわかりません。 。

代わりに、デフォルトパスへの変更を監視する方が効果的です。

このip monコマンドを使用して変更を追跡できますが、変更がないように見えても定期的なステータス更新を提供するため、これらの変更を無視する準備ができている必要があります。

-o(各レポートが独自の行にあるようにこのオプションを使用することをお勧めします。これにより、解析が簡単になります。)

#!/bin/bash
ip -o mon |
sed -e 's/\\/ /g
        s/  */ /g
        s/^\(Deleted \|\)\([0-9]*\): \([^ :]*\) /\1addr \2 \3 / 
        s/^\(Deleted \|\)\([0-9]*\): \([^ :]*\): /\1link \2 \3 / ' |
while
    IFS=' ' read -ra line
do
    if [[ ${line[0]} = Deleted ]]
    then
        mode=delete
        line=( "${line[@]:1}" )  # shift(line)
    else
        mode=update
    fi
    case "${line[*]}" in
        addr)  # added by 'sed' above
            device_num=${line[1]}
            device_name=${line[2]}
            family=${line[3]}  # 'inet' or 'inet6'
            ip_address=${line[4]}
            # ... handle address changes  ...
            ;;
        link)  # added by 'sed' above
            device_num=${line[1]}
            device_name=${line[2]%:}
            state=${line[3]}   # eg '<BROADCAST,MULTICAST,UP,LOWER_UP>'
            # ... handle link UP/DOWN ...
            ;;
        default)
            # ... handle default route changes ...
            ;;
        prefix | local | broadcast | multicast | throw | unreachable | prohibit | blackhole )
            # ... handle other route changes ...
            ;;
    esac
done

関連情報