ほっしーの技術ネタ備忘録

技術ネタの備忘録です。基本的に私が忘れないためのものです。他の人の役にも立つといいなぁ。

14.4-R に上げた時のメモ

アップデート作業

前回のメモを眺めてそのままなぞるだけ。

14.2-R に上げたときのメモ - ほっしーの技術ネタ備忘録

まずは今のバージョンを確認。

$ freebsd-version -uk
14.2-RELEASE
14.2-RELEASE

前回から…更新してない???ザワッ

そのままホスト環境のアップデート。

$ sudo freebsd-update upgrade -r 14.4-RELEASE
<snip>
$ sudo freebsd-update install
Installing updates...
Kernel updates have been installed.  Please reboot and run
'freebsd-update [options] install' again to finish installing updates.
$ sudo reboot

カーネルの更新完了!前回の反省を生かして、そのまま再起動。

実はここでトラブルが起きていたので後述。

続けてユーザランドの更新。

$ sudo freebsd-update install
Installing updates...
<snip>
 done.
$ sudo freebsd-update install
No updates are available to install.
Run 'freebsd-update [options] fetch' first.

はい、今回もホストはこれで終わりらしい。 ports の更新が必要になるのは 15.0-R を跨ぐときかな?

続けて ezjail 環境の更新。

$ sudo env UNAME_r="14.2-RELEASE" freebsd-update -b /usr/jails/basejail -r 14.4-RELEASE upgrade
<snip>
$ sudo env UNAME_r="14.2-RELEASE" freebsd-update -b /usr/jails/basejail install
<snip>
$ sudo env UNAME_r="14.2-RELEASE" freebsd-update -b /usr/jails/basejail install
<snip>
$ sudo env UNAME_r="14.2-RELEASE" freebsd-update -b /usr/jails/basejail install
src component not installed, skipped
No updates are available to install.
Run 'freebsd-update [options] fetch' first.

こちらは特に問題なく終了。

そして忘れないように etcupdate の準備。

$ cd /usr/git/src
$ sudo git fetch --depth 1
$ sudo git checkout releng/14.4
$ sudo etcupdate build -s /usr/git/src -d /tmp/work /usr/jails/basejail/etc_tarball/14.4-etcupdate.tbz

そして後は、各 jail で下記コマンドを打つだけ。

$ sudo jexec JNAME etcupdate -t /basejail/etc_tarball/14.4-etcupdate.tbz
$ sudo jexec JNAME etcupdate resolve

手動でマージが必要になったのは sshd_config だけで、後は全自動。 うーん、素晴らしい。

sshd が bind できないらしい

カーネル更新の後、待てど暮らせど ssh がつながらない。 なんでや???と思って物理コンソールを見ると……

sshd[xxxx]: error: Bind to port XX on XXXXXX failed: Can't assign requested address.

oh...

色々試してみたけれども、要するに NIC の IPv6 設定よりも早く sshd が起動しようとしてるみたい。 少し待ってから再起動すると問題なく ssh で接続できるようになったので。

という訳で今回の解決策はこれ。

sshd_setup="sleep 5"

/etc/rc.conf にこれを書くと起動を少し遅らせることができる。

XXX_setup 変数は /etc/rc.subr でも説明されている通り、rc 系の共通機能。 ここに書いたコマンドを実行してから本体を起動するので、 他にも同様の bind 失敗系エラーを吐いていたデーモンたちにも同じ処置を施していきます。

sshd_setup="sleep 5"
bsnmpd_setup="sleep 5"
openntpd_setup="sleep 5"

別に 5 秒という数字に意味はないし、みんな同じにするより少しバラつかせた方が良いのでは?説もあるけれども、 これで動いてるので良いということにしました。

ezjail の basejail を ISO イメージから作り直す

ezjail-admin update -u ばかりやってると、なんかだんだんゴミが溜まってくるのでたまには。

まずは disc1 の iso をダウンロードしてくる。 気が向いたら gpg 署名のチェックとかもする。

そのうえで、

$ sudo mdconfig -a -t vnode -f /tmp/FreeBSD-14.2-RELEASE-amd64-disc1.iso
md4
$ sudo mount -t cd9660 /dev/md4 /mnt/img
$ sudo ezjail-admin stop
$ cd /usr/jails
$ sudo mv basejail{,.old}
$ sudo mv newjail{,.old}
$ sudo ezjail-admin install -h file:///mnt/img/usr/freebsd-dist
$ sudo ezjail-admin start

ポイントは ezjail-admin install-h の記法。 あと、disc1 イメージの /usr/freebsd-dist に配布パッケージがあるみたい。

14.2-R に上げたときのメモ

アップデート作業

基本的には先日のメモを参考に作業を進める。

14.0-R に上げたときのメモ - ほっしーの技術ネタ備忘録

まずは今のバージョンの確認。

$ freebsd-version -uk
14.0-RELEASE-p6
14.0-RELEASE-p8

これで、実際にはいつ頃書いたメモなのかわかってしまいそうですね。

続けてホスト環境のアップデート。

$ sudo freebsd-update upgrade -r 14.2-RELEASE
$ sudo freebsd-update install
$ sudo ezjail-admin stop
$ sudoedit /etc/rc.conf  # 一時的に ezjail_enable をコメントアウトする
$ sudo reboot

念のため(というか手癖で) jail 環境を全部止めてから再起動していますが、 よく考えると実は必要なかったかも。

再起動したら続きを実行。

$ sudo freebsd-update install
Installing updates...gunzip: invalid compressed data--crc error
<snip>
$ sudo freebsd-update install
No updates are available to install.
Run 'freebsd-update [options] fetch' first.

おや?なんか変なメッセージが出てますね……後で要確認。( ..)φメモメモ

あと、今回は ports/pkg のアップデートは必要なさそう。

という訳でこのまま ezjail 環境も更新してしまいます。

$ sudo env UNAME_r="14.0-RELEASE" freebsd-update -b /usr/jails/basejail -r 14.2-RELEASE upgrade
$ sudo env UNAME_r="14.0-RELEASE" freebsd-update -b /usr/jails/basejail -r 14.2-RELEASE install
$ sudo env UNAME_r="14.0-RELEASE" freebsd-update -b /usr/jails/basejail -r 14.2-RELEASE install

で、前回の反省から etcupdate を忘れないよう実施。 前回の作業で gitclone を作ってあるのでそれを使って……

$ cd /usr/git/src
$ sudo git fetch --depth 1
$ sudo git checkout releng/14.2
$ sudo etcupdate build -s /usr/git/src -d /tmp/work /usr/jails/basejail/etc_tarball/14.2-etcupdate .tbz

これで準備完了。

あとはそれぞれの jail 環境で

$ sudo jexec JAILNAME etcupdate -t /basejail/etc_tarball/14.2-etcupdate.tbz
$ sudo jexec JAILNAME etcupdate resolve

を順に実行すれば OK。 mergemaster してた頃を考えるとあっという間に終わってしまいました。

はい、全部終わったら再起動して終わり。

$ sudoedit /etc/rc.conf # 忘れないうちに ezjail_enable を再び有効化
$ sudo reboot

謎のエラーについて調査

gunzip コマンドが出してそうに見えるので、 どうやら落としてきた .gz ファイルが壊れてるという話っぽい。

という訳で、 /var/db/freebsd-update/files の中を捜索……

# cd /var/db/freebsd-update/files
# find . -type f -name \[0-3]\*\.gz | xargs -n 1 gunzip -t
gunzip: invalid compressed data--crc error
gunzip: 2614b5b63adc36b7a6c1a3ee8d000c09ad4904c86de38585dfa230148637aaec.gz: uncompress failed

おっ、いたいた。 少しずつ区間を分けて確認していこうかな……と思ったら初っ端でヒットしたのでラッキー。

gunzip -t は展開結果を保存しない、テストモードでの実行。 過去の記録だと .xz でやってたので共通っぽいね。 .xz ファイルの破損チェック - ほっしーの技術ネタ備忘録

freebsd-update の実装を読んで、同様にリダイレクトで処理してみる。

# gunzip < 2614b5b63adc36b7a6c1a3ee8d000c09ad4904c86de38585dfa230148637aaec.gz > /dev/null
gunzip: invalid compressed data--crc error

ほほう、同じメッセージになるじゃないか。

……で、おまえ誰や???

ここまでやった所で、よく考えるとシステムファイルがどっか更新できてないハズなので、 freebsd-update IDS でチェックをかければ済むことに気付いたのでした。

$ sudo freebsd-update IDS
/usr/lib/debug/usr/bin/lldb.debug has SHA256 hash 31e75c746d8686547ea2a8e810bda80ab51333599881688c5552435e165774fa, but should have SHA256 hash 2614b5b63adc36b7a6c1a3ee8d000c09ad4904c86de38585dfa230148637aaec.

lldb.debug が壊れてるってさ。

ファイルがわかれば、以前調べた方法で正常なファイルが手に入ります。 ディスク破損でシステムファイルが壊れたら - ほっしーの技術ネタ備忘録

$ fetch http://update.freebsd.org/14.2-RELEASE/amd64/f/2614b5b63adc36b7a6c1a3ee8d000c09ad4904c86de38585dfa230148637aaec.gz
$ gunzip -c 2614b5b63adc36b7a6c1a3ee8d000c09ad4904c86de38585dfa230148637aaec.gz | sha256
2614b5b63adc36b7a6c1a3ee8d000c09ad4904c86de38585dfa230148637aaec

ヨシッ!

これを /usr/lib/debug/usr/bin/lldb.debug として配置すれば完了。

ping のログの drop 検知

ping をざざーっと流して、drop してないかなー?って確認する機会は稀にあります。

まぁ、落ちてるか否か?だったら wc -l とかで行数数えればいいんだけれども、いつ頃落ちたのか(何パケット目で落ちたのか?)を計算しようとすると目 grep 力が必要になります。

そういう作業はワンライナーにやらせましょうねー。

まぁこんな感じに。

$ cat ping.log | awk -F '[ =]' 'BEGIN{nxt=0}$5=="icmp_seq"{if($6!=nxt){printf("%s (expected: %d)\n",$0,nxt)}nxt=$6+1}'

んで。

64 bytes from 8.8.8.8: icmp_seq=103 ttl=255 time=8.638 ms (expected: 101)

実行するとこんな風に、本来のログの後ろにちゃんと連番になっていた場合に期待されているシーケンス番号をつけてくれます。

毎回入力するのもだるいので、スクリプトにしておいておきます。

#!/bin/sh
# ~/bin/scan_ping

for i in $@; do
        echo $i
        cat $i | awk -F '[ =]' 'BEGIN{nxt=0}$5=="icmp_seq"{if($6!=nxt){printf("%s (expected: %d, drop: %d)\n",$0,nxt,$6-nxt)}nxt=$6+1}'
done

使い方はこんな感じ。

$ scan_ping gw_ping.log
gw_ping.log
64 bytes from 8.8.8.8: icmp_seq=103 ttl=255 time=8.638 ms (expected: 101, drop: 2)

ついでに何パケット連続で落ちたのか表示できるようにしました。毎回計算するのダルいし。 あとせっかくなので複数ファイル入力も受け付けます。

ezjail の simple イメージの拡張

毎回ググってる気がするので。

$ sudo ezjail-admin stop ${NAME}
$ sudo truncate -c -s +100M /usr/jails/${NAME}.img
$ sudo mdconfig -a -t vnode -f /usr/jails/${NAME}.img
md2
$ sudo growfs /dev/md2
$ sudo mdconfig -d -u 2
$ sudo ezjail-admin start ${NAME}

truncate-c は don't create。 -s でサイズの加減をする。 この時に、 + をつけ忘れるとそのサイズ自体になるのでうっかりしないこと。

今回はマジで備忘録。

jail の devfs ルールを名前で指定したい

もうメンテが止まって長いこと経っている ezjail の例ですが。 他の管理ツールを使っていても、環境変数から jail の設定ファイルを錬成してるなら応用できそうな気はします。

dhcpd を jail 内で動かしたい時とか、 /dev から隠してたデバイスを見せるために devfs のルールを作成することになります。

まずはホストの /etc/devfs.rules に新規ルールを追加します。

[devfsrules_dhcp=1025]
add include $devfsrules_hide_all
add include $devfsrules_unhide_basic
add path fd unhide
add path fd/* unhide
add path std* unhide
add path bpf* unhide

だいたいこんな感じ。

で、 /usr/local/etc/ezjail/dhcp とかで設定されている環境変数をいじります。

export jail_dhcp_devfs_enable="YES"
export jail_dhcp_devfs_ruleset="1025"

これで jail の方の /devbpf とかが出てきます。

……いや、これでいいと言えばいいんですけどね。

1025 ってなんやねん……どのルールなのか覚えられんわ。人間に優しくない。

という気持ちになったので今回の記事のテーマ。ここまで前置き。

本題

まずは /usr/local/etc/rc.conf.d/ezjail に以下のシェルスクリプトを置きます。

eval $(cat /etc/defaults/devfs.rules /etc/devfs.rules | sed -n -e 's/^\[\(.*\)]$/\1/p')

ワンライナー

これを置いておくだけで

export jail_dhcp_devfs_enable="YES"
export jail_dhcp_devfs_ruleset="$devfsrules_dhcp"

こう書けるようになります。素敵。

蛇足

どうやら、 /usr/local/etc/rc.d/ezjail を実行する時には事前に /usr/local/etc/rc.conf.d/ezjail を実行するらしいです。どっかにそんな仕様書いてあったっけ……?

/etc/rc.subr によると

# If a service name was specified, attempt to load
# service-specific configuration

だそうです。へー。

ワインライナーの中身は、GNUgrep とかで Perl 正規表現を使えれば (もちろん Perl で書いてもいい)、先読みとかを使ってスマートに書ける気がするけど……

仕方ないので sed で。 -n で一旦出力を無効化してから、置換後の p でマッチした行のみ表示してます。 これで grep を起動しなくて済むので、少しだけコンピュータに優しい…? (そもそもルール ID を数字で指定するのが一番優しい気がするけど)

14.0-R に上げたときのメモ

14.0-R の(私的)差分ピックアップ

もうすぐ 14.2-R が出ようとしてる時期ですが、当時のメモを発掘したので投稿しておきますね!

個人的には、おうちサーバのダウンタイムを可能な限り短くできる方法を模索しているので、 その手順の1つとして一応記録に残します。

ざっくりと手順

今のバージョンを確認してメモしておく。

$ uname -r
13.2-RELEASE-p9

ホスト環境のアップデート

$ sudo freebsd-update upgrade -r 14.0-RELEASE
$ sudo freebsd-update install
$ sudo reboot
$ sudo freebsd-update install
~ここで pkg/ports を一式アップデート~
$ sudo freebsd-update install

続けて basejail の更新を途中まで。

$ sudo env UNAME_r="13.2-RELEASE-p9" freebsd-update -b /usr/jails/basejail -r 14.0-RELEASE upgrade
$ sudo env UNAME_r="13.2-RELEASE-p9" freebsd-update -b /usr/jails/basejail -r 14.0-RELEASE install
$ sudo env UNAME_r="13.2-RELEASE-p9" freebsd-update -b /usr/jails/basejail -r 14.0-RELEASE install
Completing this upgrade requires removing old shared object files.
Please rebuild all installed 3rd party software (e.g., programs
installed from the ports tree) and then run "/usr/sbin/freebsd-update install"
again to finish installing updates.
$ sudo reboot

この段階で一旦止めれば、古いライブラリが残っているので、ezjail 環境はそのまま起動可能。

……と思ったら、実は etcupdate が必要だったのを忘れていて泣くことに。 今回の更新では /etc/pam.d/system で参照している opie を消さないと、 su とかできなくなるトラップがあったのでした……。

気を取り直して、まずは git で元のバージョンのソースを持ってきて、下記コマンドでアップデート前後の tarball を作成する。

$ sudo git clone -o freebsd --depth 1 --no-single-branch https://git.freebsd.org/src.git /usr/git/src
$ sudo git checkout releng/13.2
$ sudo etcupdate build -s /usr/git/src -d /tmp/work /usr/jails/basejail/etc_tarball/13.2.tbz
$ sudo git checkout releng/14.0
$ sudo etcupdate build -s /usr/git/src -d /tmp/work /usr/jails/basejail/etc_tarball/14.0.tbz

私の環境の保守が雑過ぎて、どこから mergemaster してないか不明だったので、 他にも 13.1 とか 13.0 とかの tarball を作ることになった(←まぬけ)。

それぞれの jail 環境の中で以下のコマンド。

# etcupdate extract -t /basejail/etc_tarball/13.1.tbz
# etcupdate diff

何種類かのバージョンを試して、 etcupdate diff で出てくる差分が一番少なそうな (つまり現状の etc に一番近そうな)バージョンの tarball を使うことにする。非常に頭が悪い。

# etcupdate extract -t /basejail/etc_tarball/13.1.tbz
# etcupdate -t /basejail/etc_tarball/14.0.tbz
# etcupdate resolve

一番近かったのが 13.1 だったらこんなん。 resolvemergemaster の時と同じ感じで使えた。 これを、ホストで飼ってる全 jail マシンに対して実施する。

あとは、ぼちぼちと各 ezjail の中の pkg/ports を更新する。これが毎度メンドクサイ……。 毎回めっちゃ手間がかかるけれども、 freebsd-update を途中で止めてるおかげでのんびり時間をかけていられるのは助かる。

最後に、全ての jail 環境で pkg/ports の更新が完了したら、 freebsd-update の続きを実行。

$ sudo env UNAME_r="13.2-RELEASE-p9" freebsd-update -b /usr/jails/basejail -r 14.0-RELEASE install
Installing updates... done.

これで終わり。おつかれさまでした~。

newjail の方も更新しないといけないのだけれども、まぁそのうち……いずれ……。