はじめに
最近スリープ(Suspend)後にネットワークが繋がらなく事案が多発。
PCを開きっぱなしで放置してスリープにしていたのが悪いと思って放置していたが、コマンドできちんとスリープにしてもネットが繋がらなくなったため、こりゃあいかんと思いググって直しました。
ちなみにこのバグは、ネットワークの再起動を行っても意味がなく、PC自体を再起動しないと直らないらしいです。
なので、以下のコマンドは効きません。
$ sudo service network-manager restart
環境
Ubuntu 18.04
解決方法
r8169を利用しているかの確認
調べてみると、ネットワークカーネルモジュールがr8169を利用しているとこのバグが起きるらしい。
なので、ネットワークカーネルモジュールを調べてみる。
$ sudo lshw -C network
*-network
description: Ethernet interface
product: RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller
vendor: Realtek Semiconductor Co., Ltd.
physical id: 0
bus info: pci@0000:03:00.0
logical name: enp3s0
version: 10
serial: 8c:16:45:0f:1c:3f
size: 100Mbit/s
capacity: 1Gbit/s
width: 64 bits
clock: 33MHz
capabilities: pm msi pciexpress msix vpd bus_master cap_list ethernet physical tp mii 10bt 10bt-fd 100bt 100bt-fd 1000bt 1000bt-fd autonegotiation
configuration: autonegotiation=on broadcast=yes driver=r8169 driverversion=2.3LK-NAPI duplex=full firmware=rtl8168g-3_0.0.1 04/23/13 ip=192.168.11.26 latency=0 link=yes multicast=yes port=MII speed=100Mbit/s
resources: irq:137 ioport:d000(size=256) memory:f1304000-f1304fff memory:f1300000-f1303fff
*-network DISABLED
description: Wireless interface
product: Realtek Semiconductor Co., Ltd.
vendor: Realtek Semiconductor Co., Ltd.
physical id: 0
bus info: pci@0000:05:00.0
logical name: wlp5s0
version: 00
serial: 98:22:ef:ee:87:fb
width: 64 bits
clock: 33MHz
capabilities: pm msi pciexpress bus_master cap_list ethernet physical wireless
configuration: broadcast=yes driver=rtl8821ce latency=0 multicast=yes wireless=unassociated
resources: irq:141 ioport:c000(size=256) memory:f1100000-f110ffff
*-network
description: Ethernet interface
physical id: 2
logical name: docker0
serial: 02:42:ce:64:a6:c0
capabilities: ethernet physical
configuration: broadcast=yes driver=bridge driverversion=2.3 firmware=N/A ip=172.17.0.1 link=no multicast=yes
Ethernet interfaceのdriverを探します。
1つ目の-network
→configuration
→driver
ですね。
そうすると、driver=r8169
となっており、例のr8169が使用されてることが確認できました。
スクリプトファイルの作成
システムがスリープ状態になる前後に、/lib/systemd/system-sleep
以下にある実行可能なスクリプトをすべて実行しているらしい。
この辺の話は、$ man systemd-suspend.service
で確認できる。
今回は/lib/systemd/system-sleep
に、Ethernetのインターフェイスをリロードするスクリプトを作成することで、スリープ後にEthernetを再起動してネットが再度つながるようにする。
スクリプトは以下の通り。
#!/bin/bash
PROGNAME=$(basename "$0")
state=$1
action=$2
function log {
logger -i -t "$PROGNAME" "$*"
}
log "Running $action $state"
if [[ $state == post ]]; then
modprobe -r r8169 \
&& log "Removed r8169" \
&& modprobe -i r8169 \
&& log "Inserted r8169"
fi
これを/lib/systemd/system-sleep/r8169-refresh
として保存。
更に、実行可能にするために、権限を変更しておく。
$ sudo chmod +x /lib/systemd/system-sleep/r8169-refresh
挙動確認
一度スリープ状態にした後、解除してネットが繋がるかを確認したところ、問題なくネットが通じた。
ログで確認してみる。
tk@tk-ThinkPad-E480:~$ grep r8169-refresh /var/log/syslog
Nov 14 21:20:00 tk-ThinkPad-E480 r8169-refresh[4187]: Running suspend pre
Nov 14 21:20:05 tk-ThinkPad-E480 r8169-refresh[4296]: Running suspend post
Nov 14 21:20:05 tk-ThinkPad-E480 r8169-refresh[4305]: Removed r8169
Nov 14 21:20:06 tk-ThinkPad-E480 r8169-refresh[4310]: Inserted r8169
きちんと作動していることが確認できた。
おわりに
最近Network Disable Errorが起こるのでUpdateしてくれって警告を無視していたのがダメだったのかもしれない。
こういうスクリプトをさっとかけるようになりたい。(全部コピペ)