FreeBSD10: ネットワーク越しのfreebsd-update が出来ない

遠隔地で動いている FreeBSD サーバーを、今まで何度もネットワーク経由で freebsd-update コマンドを使うことにより更新してきました。ターゲットバージョンが、FreeBSD 9.x までであれば問題ないのですが、FreeBSD 8.x/9.x から FreeBSD 10.x へネットワーク経由で freebsd-update コマンドで上げようとすると、(遠隔地に協力者を確保できない場合)確実に失敗することが分かりました。初回のリブートをした途端、サーバーに接続できない~!と悲鳴を上げることになります。

FreeBSD 9.x 以下への更新の場合

ターゲットが FreeBSD 9.x までの場合は、リモートから、

  1. freebsd-update -r MM.m-RELEASE upgrade
  2. freebsd-update install
  3. リブート
  4. freebsd-update install
  5. パッケージを再構築
  6. freebsd-update install

という手順で、注意深く作業すれば、メジャーバージョンアップが可能です。

FreeBSD 10.x への更新の場合

しかし、ターゲットが FreeBSD 10.x(10.1, 10.2 で確認) の場合、

  1. freebsd-update -r MM.m-RELEASE upgrade
  2. freebsd-update install
  3. リブート
  4. (この段階で、ネットワークが使えない状態になる)
  5. freebsd-update install (このコマンドを発行するには、直接キーボード操作が必要になる)

のように、ネットワークが切断されてしまい、誰かに5の freebsd-update install コマンドを直接キーボードから発行してもらわないと、アップデート作業を継続できなくなります。

不具合現象

具体的に上記4のネットワークが使えない状態になったというのは、FreeBSD 8.4から10.1 に更新するための初回リブートを行った直後、リモートからアップデート中のホスト(実際にはvbox の仮想マシン)に接続できなくなりました。ホストコンソールから直接ログインして、NIC に割り当てられたはずにIPアドレスを確認したところ、

: flags=8802<BROADCAST,SIMPLEX,MULTICAST>
: flags=8008<LOOPBACK,MULTICAST>

または、

: flags=8802<BROADCAST,SIMPLEX,MULTICAST>
ifconfig: ioctl(SIOCGIFINFO_IN6): Device not configured
: flags=8008<LOOPBACK,MULTICAST>
ifconfig: ioctl(SIOCGIFINFO_IN6): Device not configured

となり、NIC, LOOPBACK とも IP アドレスを確保できていない模様。
ということは、カーネルがNICを認識していないの?と dmesg を確認してみたところ、次のようにVirtual Box の em0 インタフェースドライバーがちゃんと認識されてMACアドレスが表示されています。

Copyright (c) 1992-2014 The FreeBSD Project.
Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
        The Regents of the University of California. All rights reserved.
FreeBSD is a registered trademark of The FreeBSD Foundation.
FreeBSD 10.1-RELEASE-p16 #0: Tue Jul 28 11:41:12 UTC 2015
    root@amd64-builder.daemonology.net:/usr/obj/usr/src/sys/GENERIC i386
FreeBSD clang version 3.4.1 (tags/RELEASE_34/dot1-final 208032) 20140512
CPU: AMD Athlon(tm) 64 X2 Dual-Core Processor TK-57 (1898.93-MHz 686-class CPU)
  Origin = "AuthenticAMD"  Id = 0x60f82  Family = 0xf  Model = 0x68  Stepping = 2
  Features=0x783fbbf<FPU,VME,DE,PSE,TSC,MSR,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,MMX,FXSR,SSE,SSE2>
  Features2=0x1
  AMD Features=0xca000800<SYSCALL,FFXSR,RDTSCP,3DNow!+,3DNow!>
  AMD Features2=0x11<LAHF,CR8>
real memory  = 536805376 (511 MB)
avail memory = 502546432 (479 MB)
pnpbios: Bad PnP BIOS data checksum
kbd1 at kbdmux0
random: <Software, Yarrow> initialized
acpi0:  on motherboard
acpi0: Power Button (fixed)
acpi0: Sleep Button (fixed)
attimer0:  port 0x40-0x43,0x50-0x53 on acpi0
Timecounter "i8254" frequency 1193182 Hz quality 0
Event timer "i8254" frequency 1193182 Hz quality 100
Timecounter "ACPI-fast" frequency 3579545 Hz quality 900
acpi_timer0:  port 0x4008-0x400b on acpi0
pcib0:  port 0xcf8-0xcff on acpi0
pci_link2: BIOS IRQ 9 for 0.7.INTA does not match previous BIOS IRQ 10
pci0:  on pcib0
isab0:  at device 1.0 on pci0
isa0:  on isab0
atapci0:  port 0x1f0-0x1f7,0x3f6,0x170-0x177,0x376,0xd000-0xd00f at device 1.1 on pci0
ata0:  at channel 0 on atapci0
ata1:  at channel 1 on atapci0
vgapci0:  mem 0xe0000000-0xe0ffffff irq 11 at device 2.0 on pci0
vgapci0: Boot video device
em0: <Intel(R) PRO/1000 Legacy Network Connection 1.0.6> port 0xd010-0xd017 mem 0xf0000000-0xf001ffff irq 10 at device 3.0 on pci0
em0: Ethernet address: 08:00:27:f8:c6:ca
pcm0:  port 0xd100-0xd1ff,0xd200-0xd23f irq 11 at device 5.0 on pci0
pcm0: 
ohci0:  mem 0xf0804000-0xf0804fff irq 11 at device 6.0 on pci0
usbus0 on ohci0
pci0:  at device 7.0 (no driver attached)
battery0:  on acpi0
acpi_acad0:  on acpi0
atkbdc0:  port 0x60,0x64 irq 1 on acpi0
atkbd0:  irq 1 on atkbdc0
kbd0 at atkbd0
atkbd0: [GIANT-LOCKED]
psm0: <PS/2 Mouse> irq 12 on atkbdc0
psm0: [GIANT-LOCKED]
psm0: model IntelliMouse Explorer, device ID 4
pmtimer0 on isa0
orm0:  at iomem 0xc0000-0xc7fff,0xe2000-0xeefff pnpid ORM0000 on isa0
sc0:  at flags 0x100 on isa0
sc0: VGA 
vga0:  at port 0x3c0-0x3df iomem 0xa0000-0xbffff on isa0
atrtc0:  at port 0x70 irq 8 on isa0
Event timer "RTC" frequency 32768 Hz quality 0
ppc0: parallel port not found.
Timecounters tick every 10.000 msec
pcm0: ac97 link rate calibration timed out after 1989685 us
usbus0: 12Mbps Full Speed USB v1.0
ugen0.1:  at usbus0
uhub0:  on usbus0
ada0 at ata0 bus 0 scbus0 target 0 lun 0
ada0:  ATA-6 device
ada0: Serial Number VBdc200793-1ceb90d3
cd0 at ata0 bus 0 scbus0 target 1 lun 0
cd0:  Removable CD-ROM SCSI-0 device
cd0: Serial Number VB1-01f003f6
cd0: 33.300MB/s transfers (UDMA2, ATAPI 12bytes, PIO 65534bytes)
cd0: Attempt to query device size failed: NOT READY, Medium not present
ada0: 33.300MB/s transfers (UDMA2, PIO 65536bytes)
ada0: 10240MB (20971520 512 byte sectors: 16H 63S/T 16383C)
ada0: Previously was known as ad0
random: unblocking device.
Timecounter "TSC" frequency 1898928374 Hz quality 800
Root mount waiting for: usbus0
uhub0: 12 ports with 12 removable, self powered
Trying to mount root from ufs:/dev/ad0s1a [rw]...
ipfw2 (+ipv6) initialized, divert loadable, nat loadable, default to deny, logging disabled

(環境は、DELL Vostro 1000 上のWindows7 Pro でvbox 5.0.2を動かし、その上でFreeBSD 10.1 への更新テストを行っています。)

NIC は認識されているが、ネットワークは動かない ということなので、ネットワークを起動するスクリプトに問題がありそうだと考えました。FreeBSD 10.1 の場合は、/etc/rc.d/netif がネットワーク起動スクリプト。
このスクリプトを単体で起動してみたところ、

eval: ${ifconfig_^F...}: Bad substitution
eval: ${ifconfig_^X...}: Bad substitution
eval: ${ifconfig_^F...}: Bad substitution
eval: ${ifconfig_^X...}: Bad substitution
eval: ${ifconfig_^F...}: Bad substitution
eval: ${ifconfig_^F...}: Bad substitution
eval: ${ifconfig_^F...}: Bad substitution
eval: ${ifconfig_^F...}: Bad substitution
eval: ${ipv4_addrs_^F...}: Bad substitution
eval: ${ifconfig_^F...}: Bad substitution
eval: ${wlans_^F...}: Bad substitution
eval: ${vlans_^F...}: Bad substitution
eval: ${ifconfig_^X...}: Bad substitution
eval: ${ifconfig_^X...}: Bad substitution
eval: ${ifconfig_^X...}: Bad substitution
eval: ${ifconfig_^X...}: Bad substitution
eval: ${ipv4_addrs_^X...}: Bad substitution
eval: ${ifconfig_^X...}: Bad substitution
eval: ${wlans_^X...}: Bad substitution
eval: ${vlans_^X...}: Bad substitution

となって、インタフェース名が入るべき変数が空になってしまうためか、スクリプトがエラーになってしまうようです。

Virtual box の設定の問題か?と、いろいろ調べたけど症状の変化につながる設定は見つからず。freebsd-update コマンド実行中に、複数ファイルをエディットする必要がありましたので、その時の /boot 以下ファイルの編集ミス?などを疑いましたが、原因につながる情報を見つけることが出来ませんでした。

freebsd-update rollback コマンドにより、元のバージョンに戻せるため、2,3 回テストを行いましたけど、全部同じ結果で、FreeBSD 8.4 から直接 10.1 または 10.02 に上げても、一旦 FreeBSD 9.3 を経由して10.x に上げても症状は同じでした。

何度か検索したものの、症状を検索キーワードとして入力したためか該当結果無し。エラーメッセージで検索してみると、ヒントが見つかりました。というか、現象そのものの解決策が見つかりました

解決策

コンソールから、

# freebsd-update install

を実行すること。

“freebsd-update -r xx upgrade” で更新を行った後、リブートや freebsd-update install コマンドの複数回発行が必要になりますが、9.x まではリモートからでも発行できました。10.x ではコンソールからしか出来なくなっているようです。これが仕様なのか不具合なのかは分かりません。

2回目の “freebsd-update install” コマンドを発行した後、ネットワークは開通しました。

vwp1:/tmp % ifconfig
em0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=9b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM>
        ether 08:00:27:f8:c6:ca
        inet 192.168.1.24 netmask 0xffffff00 broadcast 192.168.1.255
        nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
        media: Ethernet autoselect (1000baseT <full-duplex>)
        status: active

今回の仮想マシンでの問題は回避できましたけど、今後リモートから freebsd-update コマンドによるメンテナンスを行う場合はどうしよう という不安は残ります。
また、「10.1 → 10.2 というマイナーバージョンアップの時はどうなのか?」という実験もしてみないといけません。

回避策

「freebsd-update install」 を行う cron スクリプトを書いて、再起動5分後くらいに自動に実行して、更に再起動するようにセットしておけば、コマンド発行可能なので、リモート更新が不能になったわけではありませんが、使い勝手は悪くなりました。

次のコマンドをリブートする時刻の5分後に合わせて、crontab にセットして、FreeBSD 10.1 → 10.2 への更新を試してみたところ成功。再起動後、15分くらいしてOSが勝手にリブート。そして、元に戻りました。

<post_install.sh>

#!/bin/sh
cd /
/usr/sbin/freebsd-update install
/sbin/shutdown -r now

上記スクリプトを 16:00 に動かしたい場合の crontab はこんな感じ。(root で crontab コマンドを発行したところ。)

# crontab -l
0    16    *    *    *    /root/bin/post_install.sh

10.1→10.2 更新の場合、ネットワークは利用不能にはなりませんでしたから、実際には上記コマンドは必要ありません。

2016/12/24 追記

FreeBSD10.3 → 11.0 への遠隔更新を試しましたが、ネットワークは利用可能でした。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です