Un nouveau monde parfumé

香り立つ備忘録

特定のログが流れてきたときにコマンドを実行するやつをシェルスクリプトで書く

ログファイルの中身を追跡して、特定の文字列が流れてきたことを検知してコマンドを実行したい、ということがあり、

tail -n0 -f $1 | while read line
do
    if [[ $line =~ 正規表現 ]]
    then
        echo '(∪^ω^)わんわんお!'
        # do something else
    fi
done

こんな感じの watchdog じみたものを書いた。

しかし、ログファイルはローテートされるものである。しかも、監視対象のシステムは一定のタイミングで別名のファイルを新たに作成しそちらに書き込み始めるという挙動を行っていた(すなわち、tail --follow=nametail --follow=descriptor による追跡は行えない)。

というわけで上記処理をシェル関数に切り出し、別の while : ループからバックグラウンドタスクとして & つけて実行、一定期間 sleep したのちそのタスクを kill して新しいファイル名を与えて実行しなおす、という感じにしたのだが、何がいけないのかプロセスを殺しきれず2重に処理を実行してしまうことがあった。親プロセスから逃れて PID1 に匿われる様子はさながら逃げ出した犬である。

結果的に上記 tail ループを watchdog-worker.sh として切り出し、dumb-init 経由で起動する形にすることで問題を解決した。

# watchdog-master.sh
SCRIPTDIR=$(cd $(dirname $0); pwd)

get_latest_logfile() {
}

while :
do
    file=$(get_latest_logfile)
    dumb-init $SCRIPTDIR/watchdog-worker.sh $file &
    pid=$!
    # 5分でリロード
    sleep 360
    kill $pid 
done

watchdog-worker.sh 側の while ループをコマンド実行後に break するようにすれば若干クールダウンタイムっぽいものを設けることもできた。今のところはそれでどうにかなっている。

バイクを買った ~3日目までの日記

バイクを買いました。中古のジクサー150(2017年式)。

f:id:pikatenor:20210621040427j:plain

もともと引っ越しの際にバイク駐輪場付き物件を視野にいれたりと、買う心づもりはなんとなくしていたものの、やれ緊急事態だなんだのですっかり期を逃してしまっていた。

とはいえ、いつまで虚無(駐輪場代)に月いくらも払っとんねんという気が大きくなったのでフッと勢いをつけて買った。

f:id:pikatenor:20210621040451j:plain

ジクサー150は端的にいうとすごく安くてすごく軽い。150ccのエンジンはパワフルではないものの街乗りに十分な性能を有しており、初心者の自分にとっても「扱いきれる」という感触は大変気に入った。値段も相まって、ひとまず買って気持ちが高まったら乗り換えればいいというのもあった。中でも2017年モデルの赤黒の配色がドストライクだった。赤黒好きなんです、厨二病なので……。新車でも値段に大差はないのだが、ジクサーはインド生産なので残念ながら入荷予定が破滅しているということもあり、走行距離1000km強、状態の良さそうな中古をネットで見つけて購入に走った。

というわけで納車から今日までの日記です。なお雨の日はカウントしません。

0日目 6月15日(火)

前日に配送時間の連絡を業者から受ける。もともと当車は熊谷の某バイクチェーン店舗にあったのだが、そもそも免許を取ってから公道に出た回数はまだ数回、しかもこの1年近くは巣ごもり生活を送っていて全く乗ってないペーパー状態の自分にとって、熊谷から都内まで乗って帰るというのは納車即心中と呼べる行為である。てなわけで近隣の店舗へ配送しての納車を希望したところ、同じ値段で自宅までの配送にしてもらえたのでそのようになった。

朝11時、時間通り到着。リモート勤務の朝会を同じ時刻に行っているのだが途中抜けさせてもらう。前日には「大型荷物の配送」としか伝えていなかったので「何買ったの?」「バイクです」「え、バイク!?」せやな。

配送業者の人なので納車時説明とかは特になし。まあ各部の機能とかは概ね分かるので別に良かったんだが、説明書が付いてなかったので点検整備はまだよく分からない……。まあ調べたり聞いたりすればいいか。

マンションの前の道路から駐輪場にしまおうとしたところで少し困る。入口にスロープがあるのだが、上げられない。いくら軽いとはいえ130kgはある。道路自体もゆるい坂になっているので自由に取り回せない。ヘルメットを取ってきてエンジンを掛けてみたが、結局狭いスロープを上がるわけにもいかない。

最終的には道路の坂を利用して少しだけ勢いをつけ、一気に押し上げることで無事駐輪場へ移動できた。駐輪場を占拠していたママチャリをどかす(どけよそこは俺が地代を払ってる枠なんだ)。

その後 times や Twitter で My new gear... の儀を執り行った。

この日の夜は小雨で、まあ乗れなくはない気がしたけど初日から雨ってのもなということで初乗車は順延した。

1日目 6月16日(水)

車通りの少ない深夜に練習することにする。住宅地なので近所迷惑ではないかという話はあるが、走行音は原二と大差ない程度だし一瞬だから許して……という気持ち。

改めて1年半ぶりのバイクだったが、発進と停止はなんとかなった。大通りには出ず、10分ほどのところにあるコンビニへ行って帰った。

6月17日(木)

雨でした。元々梅雨〜夏にかけては練習期間との位置づけで考えているので、乗れないことに問題はなく、むしろ晴れてるならやれという動機づけになるので丁度いいなと思った。

2日目 6月18日(金)

夜中、雨が止んだタイミングを見計らって出ることにする。まだ少し路面は濡れているだろうけど、そういうのも知っておかないといけないので。

駅の周りを数周した。坂道になってる交差点があるのだが、雑にやりすぎて1度エンストしたり、2速に上げたと思ったらニュートラルだったり。全体的に丁寧にやれという感じを学んだ。

しばらくして小雨になったが、特に問題は起きなかった。時候を考えてタイチの WR パーカを買ったのですが最適解でしたね。

6月19日(土)

晴れてましたが休みです。

3日目 6月19日(日)

例によって駅の周りの道を周回したあと、予報も良さそうなので大通りへ出てみることにする。スピードが出ると涼しいし気持ちいい!大型トラックの風は確かにすごいが怖いほどではなかった。

まだしばらくは夜間中心に練習したいなあという気持ちです。

ネオンライト 構文

(Flanger FX)。

What's ネオンライト 構文?

有史以前より存在したと考えられており、現在確認される最古の記録は以下の音声記録である。

原典

(Flanger FX)(ネオンライト イントロ)行け行け行け行け!行け行け行け行け!オイオイオイオイオイ!オーーイ!FOOOOOO おいリワインドしろリワインド!リワインドしろ(リワインドする音)FOOOOOイエイエイエイエイエイFOOパーッパパパーパッパパッパーパッパッパー(イントロ合唱)

字数削減

(Flanger FX)(ネオンライトイントロ)行け行け行け行け!行け行け行け行け!オイオイオイオイ!オーーーイ!FOOおいリワインドしろリワインド!リワインドしろ(リワインドする音)FOOOOイエイエイエイFOOパーッパパパーパッパパッパーパッパッパー(イントロ合唱)

トドを叩く

(Flanger FX)(トドを叩く イントロ)おうおうおうおう!おうおうおうおう!おうおうおうおう!おうっ!FOOOOOO おうリワインおうしろリワインおうっ!リワインおうしろ(トドを叩く 音)FOOOOOおうおうおうおうFOOパーッパパパーパッパパッパーパンッパァンッパァンッ(トド合唱)

六甲おろし

(Flanger FX)(六甲おろし イントロ)行け行け行け行け!行け行け行け行け!オイオイオイオイオイ!オーーイ!FOOOOOO おい優勝しろ優勝!優勝しろ(藤川が被弾する音)FOOOOOイエイエイエイエイエイFOOパーッパパパーッパッパッパッパッパッパーッ(イントロ合唱)

デカネオンライト

(デカFlanger FX)(デカネオンライト デカイントロ)行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行け行

韓国語

(Flanger FX) (네온 등 소개) 아자 가라 가라! 아자 가라 가라! 오이 오이오이오이오이! 오이! FOOOOOO두고 되감기하라 되감기! 되감기하라 (되감기하는 소리) FOOOOO 아니오 아니오하자 예 FOO 팟 파파 파 파파 파파 조치 확 파파 조치 (인트로 합창)

英語 (DeepL 翻訳)

(Flanger FX)(neon light intro) Go, go, go, go! Go, go, go, go, go! Oi, oi, oi, oi, oi, oi, oi, oi, oi Oy, FOOOOOOO! Hey, rewind! Rewind (sound to rewind) FOOOOO YAYAYAYAYAYAYAYAYAYAYAYAY FOOPAPPAPPAPPAPPAPPAPPAPP (intro chorus)

アラビアン

(Flanger FX) (مقدمة ضوء النيون) Go Go Go Go! إنطلق إنطلق إنطلق إنطلق! Oioioioioi! يا! FOOOOOO يا ترجيع شيرو الترجيع! هامش الترجيع (صوت اللف) FOOOOO YAE AIA FOO Pappa Pappa Pappa Pappa (جوقة المقدمة)

診断

shindanmaker.com

その他の改変例/追加案ありましたらコメントまでお寄せください。

0pxの画像ファイル

0px.org というドメインを持っています。このドメインはなるべく短く、かつ意味ありげなドメインが欲しいと思って選んだだけで、特に意味はありません。専らサーバーの alias や短縮 URL に使っています。

さて、0px.org で配布すべきリソースとはなんでしょうか。当然 0px×0px の画像ファイルです。しかし、どんな画像編集ソフトでも大抵キャンパスサイズの最小は 1px×1px です。そもそも 0px の画像を許すフォーマットなどあるのでしょうか。というか画像を2次元的なものとするなら、0px×0px の画像は果たして画像なのでしょうか。

……とりあえず 0px 画像の哲学的な問いかけは一旦忘れることとして、思いついたメジャーな画像フォーマットについて仕様上 0px×0px の画像が許されるのか、調べることにしました。

PNG

www.libpng.org

3章 File Structure には PNG ファイルは PNG file signature(固定8バイト)と chunks からなるとされています。そのうち必須となる chunks4.1 Critical chunks に定められています。この中にある IHDR ヘッダーに画像サイズが入っています。

The IHDR chunk must appear FIRST. It contains:

Width: 4 bytes
Height: 4 bytes
Bit depth: 1 byte
Color type: 1 byte
Compression method: 1 byte
Filter method: 1 byte
Interlace method: 1 byte

Width and height give the image dimensions in pixels. They are 4-byte integers. Zero is an invalid value.

したがって、残念ながら画像サイズは 1px×1px が最小であり、PNG では 0px×0px の画像は表現できないことになります。

JPEG

厳密には、 JPEG (ISO/IEC 10918 | ITU-T T.81) は画像の符号化についてのフォーマットであり、今日 .jpg .jpeg の拡張子でやり取りされるファイルフォーマットについては JFIF (JPEG File Interchange Format) として ISO/IEC 10918 Part.5 および ITU-T T.871 に規定されています。また、これを拡張した Exif も広く普及しています。

今回はこちらの W3C 掲載のJPEG 仕様書 および JFIF 仕様書 を参照します。

www.w3.org

JFIF フォーマットは JPEGSOI (Start of Image) マーカーセグメント、JFIF 情報を格納する APP0 セグメントから始まり、画像データをコードした後、EOI (End of Image) マーカーで終わります。

JPEG の画像データは DCT による量子化情報を記述するテーブル DQT セグメント、 ハフマン符号化による圧縮を行うためのテーブル DHT セグメント、実際のスキャンデータを格納する SOS セグメント、スキャンデータの形式を格納する SOF0 セグメントからなり、これらが合わさり画像データを形成します。(最も基礎的な Baseline DCT の場合)

このうち、画像サイズに直接関わるのはピクセルアスペクト比を決める APP0Xdensity, Ydensity (両方 1 で PAR 1:1 となる)と SOFX および Y(スキャンデータのサンプル数)ですが

B.2.2 Frame header syntax

Y: Number of lines – Specifies the maximum number of lines in the source image. This shall be equal to the number of lines in the component with the maximum number of vertical samples (see A.1.1). Value 0 indicates that the number of lines shall be defined by the DNL marker and parameters at the end of the first scan (see B.2.5).
X: Number of samples per line – Specifies the maximum number of samples per line in the source image. This shall be equal to the number of samples per line in the component with the maximum number of horizontal samples (see A.1.1).

後続の表 B.2 に X および Y の範囲が記されていますが、X = 1~65535 Y = 0~65535 です。一応 DNL セグメントの定義も覗いてみますが

B.2.5 Define number of lines syntax

...The DNL (Define Number of Lines) segment provides a mechanism for defining or redefining the number of lines in the frame (the Y parameter in the frame header) at the end of the first scan. ...
NL: Number of lines – Specifies the number of lines in the frame (see definition of Y in B.2.2).

この NL の値も 1~65535 です。よってJPEG でも 0px×0px の画像は表現できません。

一応 JPEG それ自体の仕様では Annex. B.5 Abbreviated format for table-specification data にフレームデータを持たない JPEG フォーマットというのも規定されており、一方 JFIF には APP0 が必須であるため、これに従えば SOI APP0 EOI からなる JPEG ファイルというのも考えることはできます。が、これは画像を持たないということであり、0px×0px を正しく表しているとは言えないのではないでしょうか。

BMP

BMP(Windows bitmap) のファイルフォーマットの仕様について調べようとしたんですが、正直 Wikipedia が一番詳しかったです。Windows の GDI による実装が事実上の標準として扱われているんだと思いますが、正式な仕様のありかを知っている方は教えてください……

BMP ファイルは BITMAPFILEHEADER ヘッダから始まり、直後に画像情報を格納する DIB ヘッダ、ピクセルデータと続きます。まずはメジャーな DIB ヘッダである BITMAPINFOHEADER を見てみます。

docs.microsoft.com

BMP は他の多くのデジタル画像フォーマットと異なり、左下を原点としてボトムアップピクセルデータを記述するのが特徴的です。

biWidth
The width of the bitmap, in pixels.

biHeight
The height of the bitmap, in pixels. If biHeight is positive, the bitmap is a bottom-up DIB and its origin is the lower-left corner. If biHeight is negative, the bitmap is a top-down DIB and its origin is the upper-left corner.

この biWidth および biHeight が画像サイズですが、ここに正の値が入ればボトムアップに、負の値ならトップダウンBMPとしては一般的ではない)になります。ということは0は……?たぶん未定義動作でしょう。

より古い DIB ヘッダーの BITMAPCOREHEADER も見てみます。

docs.microsoft.com

bcWidth
The width of the bitmap, in pixels.
bcHeight
The height of the bitmap, in pixels.

こちらは特に負数についての規定はありません。暗に正の値でボトムアップとなるようです。

とはいえ、値の型としては WORD なので、0を入れられます。よって、0px×0px の画像は

         |-------------BITMAPFILEHEADER-------------|-----
00000000  42 4d 1e 00 00 00 00 00  00 00 1a 00 00 00 0c 00
          BITMAPCOREHEADER--------------|---pixel---|
00000010  00 00 00 00 00 00 01 00  01 00 00 00 00 00
                ^^W^^ ^^H^^

こうなります!*1(強調した部分が bcWidth, bcHeight

(誰か Windows プログラミング環境ある人に GDI で実際何が起きるのか確かめてみてもらいたい)

GIF

https://www.w3.org/Graphics/GIF/spec-gif89a.txtwww.w3.org

GIF ファイルフォーマットで必須とされているのはバージョンを示す Header ブロック(GIF87a or GIF89a 6バイト)と画像情報を格納した Logical Screen Descriptor ブロック、ファイル終端の Trailer (0x3B 固定)のみです。

Logical Screen Descriptor の定義は以下です。

c. Syntax.

      7 6 5 4 3 2 1 0        Field Name                    Type
     +---------------+
  0  |               |       Logical Screen Width          Unsigned
     +-             -+
  1  |               |
     +---------------+
  2  |               |       Logical Screen Height         Unsigned
     +-             -+
  3  |               |
     +---------------+
  4  | |     | |     |       <Packed Fields>
     +---------------+
  5  |               |       Background Color Index        Byte
     +---------------+
  6  |               |       Pixel Aspect Ratio            Byte
     +---------------+

i) Logical Screen Width - Width, in pixels, of the Logical Screen
where the images will be rendered in the displaying device.

ii) Logical Screen Height - Height, in pixels, of the Logical
Screen where the images will be rendered in the displaying device.

この Logical Screen WidthLogical Screen Height が画像サイズを規定します。入れられる値について Unsigned とある以外は特に記述は見当たりませんが、0を入れてもいいはずです!

         |-----Header------|----Logical S.D.-----|tr.
00000000  47 49 46 38 39 61 00 00  00 00 00 00 00 3b
          G  I  F  8  9  a  ^^W^^  ^^H^^ pf bc ar ;

0px 画像に表示すべきデータもなにもないわけですから、Logical Screen Descriptor 以降の画像データは含みません。仕様にも "the entity Data may be repeated any number of times, including 0 times."(Appendix.B) と明記されていますから、これで最低限 GIF の仕様は満たしているはずです。

そういうわけで、 0px.org ではより小さく、より正しそうな上記14バイトの GIF 画像を配布することにしました。適当なパスの GET でも固定で 200 と GIF を返すので ping 代わりにお使いください。

画像フォーマットも改めて厳密に調べてみると色々分かって面白かったです。まあ大抵 0px×0px の画像は画像ではないとして考慮されていない雰囲気でしたが…… 当然大半のデコーダ/ライブラリで上に示した例はエラーになると思います。ちゃんちゃん

おまけ

TIFF

ちゃんと読み込んでいませんが、TIFFImageWidthImageLength はデータ型(SHORT or LONG)の指定があるのみで値域が明示されていないので、0px 画像を表現できる可能性があります。TIFF の中に JPEG を入れることも一般的なため、SOI~EOI だけの JPEG を入れて 0px JPEG をつくれるかも知れません。

SVG

ラスター画像でなければ、SVG は 0px×0px の画像を表現可能です。

<svg version="1.1" width="0" height="0" xmlns="http://www.w3.org/2000/svg"/>

例えばこのように書けると思います。

そのほか参考になったサイト

github.com

様々なファイルフォーマットについて、仕様上許される最小サイズのものを集めたリポジトリです。GIF ファイルはこの記事の解説によるもののようで、1px×1pxを Logical Screen Descriptor に書いているようです*2JPEG は最低限 1px が表示できるような DCT テーブルとフレームのみを含んだ 107 バイトのものなのですが、前述のように JFIF には SOI 直後の APP0 が必須なので JFIF 準拠ではない生 JPEG ストリームです。逆にフレームを含まず JFIF 準拠な最小*3を提案できる気がするんですが…… Issue 立ててみようかな

CGファイル概説 目次

GIFフォーマットの詳細 - とほほのWWW入門

JPEG フォーマット、GIF フォーマットに関する日本語文献です。特に JPEG は重厚でちゃんと読めてる自信がないので助かりました。

*1: 表示はしてほしくないが1px分のデータが入っており(001A~001E 1ピクセルあたりのバイト数は4の倍数にアライメントされる)そのオフセットを BITMAPFILEHEADER の bfOffBits に記している

*2:Image Data を含まないためデコーダによってはエラーになる / 特に IE でエラーになることが報告されている

*3:たぶん合計22バイト

LVM on md 容量拡張作業ログ

pikatenor@Juno3C:~⟫ df -h /dev/mapper/Hayate-lvol0
Filesystem                Size  Used Avail Use% Mounted on
/dev/mapper/Hayate-lvol0  5.5T  5.4T  118G  98% /media/Hayate

はい、というわけでおうちサーバーで NAS として活躍しているディスクアレイの容量が枯渇しつつあったので拡張しました。

こいつは5年ほど前に大学生活初のバイト代を片手に組んだもので、1TBずつに切ったパーティションごとに mdadm で RAID5 を組み、そいつらを LVM でまとめて xfs を乗せるという構図になっています。名前は Hayate。 はーちゃんだ*1

この構成は当時こちらの記事を参考にさせていただきました。 ruzia.hateblo.jp

当初は WD Blue 2TBx4 = 6TB の構成でしたが、幾度かのディスク交換を経て現在3つは WD Red 3TBディスクに交換済みです(最後の1つもさっさと交換しろ)。すなわち、1TBずつ3つの未使用領域があります。今回はここに新たに RAID5 をつくり、既存 LVM LV に追加します。

パーティショニング

作業前は以下。

pikatenor@Juno3C:~⟫ lsblk
NAME               MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINT
sda                  8:0    0   1.8T  0 disk  
├─sda1               8:1    0 931.3G  0 part  
│ └─md0              9:0    0   2.7T  0 raid5 
│   └─Hayate-lvol0 252:0    0   5.5T  0 lvm   /media/Hayate
└─sda2               8:2    0 931.3G  0 part  
  └─md1              9:1    0   2.7T  0 raid5 
    └─Hayate-lvol0 252:0    0   5.5T  0 lvm   /media/Hayate
sdb                  8:16   0   2.7T  0 disk  
├─sdb1               8:17   0 931.3G  0 part  
│ └─md0              9:0    0   2.7T  0 raid5 
│   └─Hayate-lvol0 252:0    0   5.5T  0 lvm   /media/Hayate
└─sdb2               8:18   0 931.3G  0 part  
  └─md1              9:1    0   2.7T  0 raid5 
    └─Hayate-lvol0 252:0    0   5.5T  0 lvm   /media/Hayate
sdc                  8:32   0   2.7T  0 disk  
├─sdc1               8:33   0 931.3G  0 part  
│ └─md0              9:0    0   2.7T  0 raid5 
│   └─Hayate-lvol0 252:0    0   5.5T  0 lvm   /media/Hayate
└─sdc2               8:34   0 931.3G  0 part  
  └─md1              9:1    0   2.7T  0 raid5 
    └─Hayate-lvol0 252:0    0   5.5T  0 lvm   /media/Hayate
sdd                  8:48   0   2.7T  0 disk  
├─sdd1               8:49   0 931.3G  0 part  
│ └─md0              9:0    0   2.7T  0 raid5 
│   └─Hayate-lvol0 252:0    0   5.5T  0 lvm   /media/Hayate
└─sdd2               8:50   0 931.3G  0 part  
  └─md1              9:1    0   2.7T  0 raid5 
    └─Hayate-lvol0 252:0    0   5.5T  0 lvm   /media/Hayate

このうち /dev/sd[bcd] の3つが交換済み3TBディスクです。

パーティション追加。

pikatenor@Juno3C:~⟫ sudo parted /dev/sdc
/dev/sdd を使用
GNU Parted へようこそ! コマンド一覧を見るには 'help' と入力してください。
(parted) print                                                            
モデル: WDC WD30 EFRX-68EUZN0 (scsi)
ディスク /dev/sdd: 3001GB
セクタサイズ (論理/物理): 512B/4096B
パーティションテーブル: gpt
ディスクフラグ: 

番号  開始    終了    サイズ  ファイルシステム  名前  フラグ
 1    1049kB  1000GB  1000GB                    md0
 2    1000GB  2000GB  1000GB                    md1

(parted) unit s                                                           
(parted) print                                                                                                                                                  
モデル: WDC WD30 EFRX-68EUZN0 (scsi)
ディスク /dev/sdd: 5860533168s
セクタサイズ (論理/物理): 512B/4096B
パーティションテーブル: gpt
ディスクフラグ: 

番号  開始         終了         サイズ       ファイルシステム  名前  フラグ
 1    2048s        1953128447s  1953126400s                    md0
 2    1953128448s  3906254847s  1953126400s                    md1

(parted) mkpart                                                           
パーティションの名前?  []? md2                                            
ファイルシステムの種類?  [ext2]?                                          
開始? 3906254848
終了? 5859381247                                                          
(parted) print                                                            
モデル: WDC WD30 EFRX-68EUZN0 (scsi)
ディスク /dev/sdd: 5860533168s
セクタサイズ (論理/物理): 512B/4096B
パーティションテーブル: gpt
ディスクフラグ: 

番号  開始         終了         サイズ       ファイルシステム  名前  フラグ
 1    2048s        1953128447s  1953126400s                    md0
 2    1953128448s  3906254847s  1953126400s                    md1
 3    3906254848s  5859381247s  1953126400s  ext2              md2

(parted) quit                                                             
通知: 必要であれば /etc/fstab を更新するのを忘れないようにしてください。

残りも同様にやって。

mdadm

pikatenor@Juno3C:~⟫ sudo mdadm --create --assume-clean /dev/md2 --level=5 --metadata=1.2 --raid-devices=3 /dev/sdb3 /dev/sdc3 /dev/sdd3
mdadm: array /dev/md2 started.

作業後。

pikatenor@Juno3C:~⟫ lsblk
NAME               MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINT
sda                  8:0    0   1.8T  0 disk  
├─sda1               8:1    0 931.3G  0 part  
│ └─md0              9:0    0   2.7T  0 raid5 
│   └─Hayate-lvol0 252:0    0   5.5T  0 lvm   /media/Hayate
└─sda2               8:2    0 931.3G  0 part  
  └─md1              9:1    0   2.7T  0 raid5 
    └─Hayate-lvol0 252:0    0   5.5T  0 lvm   /media/Hayate
sdb                  8:16   0   2.7T  0 disk  
├─sdb1               8:17   0 931.3G  0 part  
│ └─md0              9:0    0   2.7T  0 raid5 
│   └─Hayate-lvol0 252:0    0   5.5T  0 lvm   /media/Hayate
├─sdb2               8:18   0 931.3G  0 part  
│ └─md1              9:1    0   2.7T  0 raid5 
│   └─Hayate-lvol0 252:0    0   5.5T  0 lvm   /media/Hayate
└─sdb3               8:19   0 931.3G  0 part  
  └─md2              9:2    0   1.8T  0 raid5 
sdc                  8:32   0   2.7T  0 disk  
├─sdc1               8:33   0 931.3G  0 part  
│ └─md0              9:0    0   2.7T  0 raid5 
│   └─Hayate-lvol0 252:0    0   5.5T  0 lvm   /media/Hayate
├─sdc2               8:34   0 931.3G  0 part  
│ └─md1              9:1    0   2.7T  0 raid5 
│   └─Hayate-lvol0 252:0    0   5.5T  0 lvm   /media/Hayate
└─sdc3               8:35   0 931.3G  0 part  
  └─md2              9:2    0   1.8T  0 raid5 
sdd                  8:48   0   2.7T  0 disk  
├─sdd1               8:49   0 931.3G  0 part  
│ └─md0              9:0    0   2.7T  0 raid5 
│   └─Hayate-lvol0 252:0    0   5.5T  0 lvm   /media/Hayate
├─sdd2               8:50   0 931.3G  0 part  
│ └─md1              9:1    0   2.7T  0 raid5 
│   └─Hayate-lvol0 252:0    0   5.5T  0 lvm   /media/Hayate
└─sdd3               8:51   0 931.3G  0 part  
  └─md2              9:2    0   1.8T  0 raid5

pikatenor@Juno3C:~⟫ cat /proc/mdstat 
Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10] 
md2 : active raid5 sdd3[2] sdc3[1] sdb3[0]
      1952864256 blocks super 1.2 level 5, 512k chunk, algorithm 2 [3/3] [UUU]
      bitmap: 0/8 pages [0KB], 65536KB chunk

md1 : active raid5 sdd2[4] sdc2[5] sdb2[6] sda2[0]
      2929296384 blocks super 1.2 level 5, 512k chunk, algorithm 2 [4/4] [UUUU]
      bitmap: 0/8 pages [0KB], 65536KB chunk

md0 : active raid5 sdc1[5] sda1[0] sdb1[6] sdd1[4]
      2929296384 blocks super 1.2 level 5, 512k chunk, algorithm 2 [4/4] [UUUU]
      bitmap: 0/8 pages [0KB], 65536KB chunk

unused devices: <none>

無事に2TBのディスクが見えている

LVM

作業前。

pikatenor@Juno3C:~⟫ sudo pvdisplay
  --- Physical volume ---
  PV Name               /dev/md0
  VG Name               Hayate
  PV Size               2.73 TiB / not usable 5.00 MiB
  Allocatable           yes (but full)
  PE Size               4.00 MiB
  Total PE              715159
  Free PE               0
  Allocated PE          715159
  PV UUID               Z57254-XJ9c-2auv-KXdz-nKjd-F0d5-h38rWJ
   
  --- Physical volume ---
  PV Name               /dev/md1
  VG Name               Hayate
  PV Size               2.73 TiB / not usable 5.00 MiB
  Allocatable           yes (but full)
  PE Size               4.00 MiB
  Total PE              715159
  Free PE               0
  Allocated PE          715159
  PV UUID               GSe9lz-WBde-oEi1-4Zzo-GOBO-IBa2-L0LIxZ
  
pikatenor@Juno3C:~⟫ sudo vgdisplay
  --- Volume group ---
  VG Name               Hayate
  System ID             
  Format                lvm2
  Metadata Areas        2
  Metadata Sequence No  3
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                1
  Open LV               1
  Max PV                0
  Cur PV                2
  Act PV                2
  VG Size               5.46 TiB
  PE Size               4.00 MiB
  Total PE              1430318
  Alloc PE / Size       1430318 / 5.46 TiB
  Free  PE / Size       0 / 0   
  VG UUID               OWPo9U-ILf1-cQLv-PUOA-peo6-KODX-LyMi30
   
pikatenor@Juno3C:~⟫ sudo lvdisplay
  --- Logical volume ---
  LV Path                /dev/Hayate/lvol0
  LV Name                lvol0
  VG Name                Hayate
  LV UUID                4pXE1Y-33Cn-jRu0-fAgq-R2Sc-hRu5-Rg5wW5
  LV Write Access        read/write
  LV Creation host, time Juno3C, 2016-01-02 07:53:16 +0900
  LV Status              available
  # open                 1
  LV Size                5.46 TiB
  Current LE             1430318
  Segments               2
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     6144
  Block device           252:0

PV 作って既存 VG と LV に突っ込んでドーン

pikatenor@Juno3C:~⟫ sudo pvcreate /dev/md2
  Physical volume "/dev/md2" successfully created

pikatenor@Juno3C:~⟫ sudo vgextend Hayate /dev/md2
  Volume group "Hayate" successfully extended

pikatenor@Juno3C:~⟫ sudo lvextend -l +100%FREE /dev/Hayate/lvol0
  Size of logical volume Hayate/lvol0 changed from 5.46 TiB (1430318 extents) to 7.27 TiB (1907091 extents).
  Logical volume lvol0 successfully resized.

よさそう

pikatenor@Juno3C:~⟫ sudo pvdisplay
  --- Physical volume ---
  PV Name               /dev/md0
  VG Name               Hayate
  PV Size               2.73 TiB / not usable 5.00 MiB
  Allocatable           yes (but full)
  PE Size               4.00 MiB
  Total PE              715159
  Free PE               0
  Allocated PE          715159
  PV UUID               Z57254-XJ9c-2auv-KXdz-nKjd-F0d5-h38rWJ
   
  --- Physical volume ---
  PV Name               /dev/md1
  VG Name               Hayate
  PV Size               2.73 TiB / not usable 5.00 MiB
  Allocatable           yes (but full)
  PE Size               4.00 MiB
  Total PE              715159
  Free PE               0
  Allocated PE          715159
  PV UUID               GSe9lz-WBde-oEi1-4Zzo-GOBO-IBa2-L0LIxZ
   
  --- Physical volume ---
  PV Name               /dev/md2
  VG Name               Hayate
  PV Size               1.82 TiB / not usable 2.00 MiB
  Allocatable           yes (but full)
  PE Size               4.00 MiB
  Total PE              476773
  Free PE               0
  Allocated PE          476773
  PV UUID               LgwqGc-5AB6-iZMG-Zxdz-hWTG-wqeE-bNVF9P
   
pikatenor@Juno3C:~⟫ sudo vgdisplay
  --- Volume group ---
  VG Name               Hayate
  System ID             
  Format                lvm2
  Metadata Areas        3
  Metadata Sequence No  5
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                1
  Open LV               1
  Max PV                0
  Cur PV                3
  Act PV                3
  VG Size               7.27 TiB
  PE Size               4.00 MiB
  Total PE              1907091
  Alloc PE / Size       1907091 / 7.27 TiB
  Free  PE / Size       0 / 0   
  VG UUID               OWPo9U-ILf1-cQLv-PUOA-peo6-KODX-LyMi30
   
pikatenor@Juno3C:~⟫ sudo lvdisplay
  --- Logical volume ---
  LV Path                /dev/Hayate/lvol0
  LV Name                lvol0
  VG Name                Hayate
  LV UUID                4pXE1Y-33Cn-jRu0-fAgq-R2Sc-hRu5-Rg5wW5
  LV Write Access        read/write
  LV Creation host, time Juno3C, 2016-01-02 07:53:16 +0900
  LV Status              available
  # open                 1
  LV Size                7.27 TiB
  Current LE             1907091
  Segments               3
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     6144
  Block device           252:0

xfs grow

最後は xfs の拡張。オンラインリサイズが効きます。

pikatenor@Juno3C:~⟫ sudo xfs_growfs /media/Hayate
meta-data=/dev/mapper/Hayate-lvol0 isize=256    agcount=32, agsize=45770240 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=0        finobt=0 spinodes=0
data     =                       bsize=4096   blocks=1464645632, imaxpct=5
         =                       sunit=128    swidth=384 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=0
log      =internal               bsize=4096   blocks=521728, version=2
         =                       sectsz=512   sunit=8 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
data blocks changed from 1464645632 to 1952861184
pikatenor@Juno3C:~⟫ lsblk
NAME               MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINT
sda                  8:0    0   1.8T  0 disk  
├─sda1               8:1    0 931.3G  0 part  
│ └─md0              9:0    0   2.7T  0 raid5 
│   └─Hayate-lvol0 252:0    0   7.3T  0 lvm   /media/Hayate
└─sda2               8:2    0 931.3G  0 part  
  └─md1              9:1    0   2.7T  0 raid5 
    └─Hayate-lvol0 252:0    0   7.3T  0 lvm   /media/Hayate
sdb                  8:16   0   2.7T  0 disk  
├─sdb1               8:17   0 931.3G  0 part  
│ └─md0              9:0    0   2.7T  0 raid5 
│   └─Hayate-lvol0 252:0    0   7.3T  0 lvm   /media/Hayate
├─sdb2               8:18   0 931.3G  0 part  
│ └─md1              9:1    0   2.7T  0 raid5 
│   └─Hayate-lvol0 252:0    0   7.3T  0 lvm   /media/Hayate
└─sdb3               8:19   0 931.3G  0 part  
  └─md2              9:2    0   1.8T  0 raid5 
    └─Hayate-lvol0 252:0    0   7.3T  0 lvm   /media/Hayate
sdc                  8:32   0   2.7T  0 disk  
├─sdc1               8:33   0 931.3G  0 part  
│ └─md0              9:0    0   2.7T  0 raid5 
│   └─Hayate-lvol0 252:0    0   7.3T  0 lvm   /media/Hayate
├─sdc2               8:34   0 931.3G  0 part  
│ └─md1              9:1    0   2.7T  0 raid5 
│   └─Hayate-lvol0 252:0    0   7.3T  0 lvm   /media/Hayate
└─sdc3               8:35   0 931.3G  0 part  
  └─md2              9:2    0   1.8T  0 raid5 
    └─Hayate-lvol0 252:0    0   7.3T  0 lvm   /media/Hayate
sdd                  8:48   0   2.7T  0 disk  
├─sdd1               8:49   0 931.3G  0 part  
│ └─md0              9:0    0   2.7T  0 raid5 
│   └─Hayate-lvol0 252:0    0   7.3T  0 lvm   /media/Hayate
├─sdd2               8:50   0 931.3G  0 part  
│ └─md1              9:1    0   2.7T  0 raid5 
│   └─Hayate-lvol0 252:0    0   7.3T  0 lvm   /media/Hayate
└─sdd3               8:51   0 931.3G  0 part  
  └─md2              9:2    0   1.8T  0 raid5 
    └─Hayate-lvol0 252:0    0   7.3T  0 lvm   /media/Hayate

pikatenor@Juno3C:~⟫ df -h /dev/mapper/Hayate-lvol0
Filesystem                Size  Used Avail Use% Mounted on
/dev/mapper/Hayate-lvol0  7.3T  5.4T  2.0T  74% /media/Hayate

ワシの勝ち!よかったですね

追記: タイトルが md on LVM になっててウケた(逆だろ)直した

*1:久川颯は無関係 | 先代が Nagisa だったのでナギ→ハヤテという連想 | キモい構成だったので速くなればいいなーという願いをこめた

Edgerouter X でひかり電話なし IPv6 をやる

表題のとおりですが、意外とがんばりが必要だったのと、同じような設定で悩む人が多いらしいので忘れないようにメモします

2年近く前の下書きを引っ張り出して焼き直してるので古かったり設定に齟齬があるかもしれません。ひらに

TL;DR

NGN から RA で降ってきた /64 のプレフィックスを Edgerouter で再び LAN 側に広報しつつどうにかして NDP プロキシをやるとできる。

背景

フレッツ光ネクストを使用して IPoE 方式による IPv6 接続を行う場合、ひかり電話契約の有無によってアドレス取得の方法が異なるというのは割と知られた事実だと思います。

具体的には、ひかり電話契約がある場合は DHCPv6-PD を用いてフレッツ網(NGN)から /56 の Prefix Delegation を受けることができ、NGNルーターは PD を受けたルーターにパケットを流してくれるようになります。1

一方、ひかり電話契約がない場合、PD は受けられず、NGNルーターから /64 の Router Advertisement が流れてきます。2 このとき、NTT が想定している使い方としては IPv6 のみ LAN 内のネットワークと L2 ブリッジ(a.k.a. IPv6 パススルー)してやることで LAN 内機器と NGN ルーターで直接通信するというものだと思います。

しかしながら、ウチのガバガバセキュリティの機器をインターネットに直接晒すのはやや怖い…… ので、なんとか L3 ルーティングでことを済ませたい、というのが本記事の背景となります。

構成

回線: Softbank光 マンション・ギガスピード3

ISP: インターリンク ZOOT NATIVE

ONU: GE-PON タイプD

ルーター: Edgerouter X (ER-X)

以降の設定例では次のインターフェイスを使用することとします。(適宜読み替えてください)

WAN側IF: eth0

LAN側IF: switch0 (eth2-4)

設定

1. WAN側インターフェイスIPv6 アドレスを当てる

これは単純で、RA を受けて SLAAC でアドレスを確定させるだけです。

set interfaces ethernet eth0 ipv6 address autoconf
set interfaces ethernet eth0 ipv6 dup-addr-detect-transmits 1

この段階で WAN 側インターフェイスにはグローバルアドレスがつき、ルーターから外へは IPv6 通信できるようになります。

4: eth0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether fc:ec:da:XX:XX:1e brd ff:ff:ff:ff:ff:ff
    inet6 2409:10:XXXX:XXXX:feec:daff:feXX:XX1e/64 scope global dynamic 
       valid_lft 2591862sec preferred_lft 604662sec
    inet6 fe80::feec:daff:fexx:xx1e/64 scope link 
       valid_lft forever preferred_lft forever

2. IPv4 接続性を確保する

本筋から外れるので設定だけ列挙して詳細な解説は割愛します。

2.1 DS-Lite

set interfaces ipv6-tunnel v6tun0 encapsulation ipip6
set interfaces ipv6-tunnel v6tun0 firewall in name DSLITE_IN
set interfaces ipv6-tunnel v6tun0 firewall local name DSLITE_LOCAL
set interfaces ipv6-tunnel v6tun0 local-ip '2409:10:XXXX:XXXX:feec:daff:feXX:XX1e'
set interfaces ipv6-tunnel v6tun0 mtu 1460
set interfaces ipv6-tunnel v6tun0 multicast disable
set interfaces ipv6-tunnel v6tun0 remote-ip '2404:8e00::feed:100'
set interfaces ipv6-tunnel v6tun0 ttl 64

出口は transix です local-ip に prefix を直打ちしない方法はまだ知らない

2.2 PPPoE

set interfaces ethernet eth0 description 'Internet(v4/v6)'
set interfaces ethernet eth0 duplex auto
set interfaces ethernet eth0 firewall in ipv6-name WAN6_IN
set interfaces ethernet eth0 firewall local ipv6-name WAN6_LOCAL
set interfaces ethernet eth0 ipv6 address autoconf
set interfaces ethernet eth0 ipv6 dup-addr-detect-transmits 1
set interfaces ethernet eth0 pppoe 0 default-route none
set interfaces ethernet eth0 pppoe 0 firewall in name WAN_IN
set interfaces ethernet eth0 pppoe 0 firewall local name WAN_LOCAL
set interfaces ethernet eth0 pppoe 0 mtu 1454
set interfaces ethernet eth0 pppoe 0 name-server auto
set interfaces ethernet eth0 pppoe 0 password XXXX
set interfaces ethernet eth0 pppoe 0 user-id XXX@sbb.ne.jp
set interfaces ethernet eth0 speed auto
set service nat rule 5010 description 'masquerade for WAN'
set service nat rule 5010 outbound-interface pppoe0
set service nat rule 5010 type masquerade

2.3 PBR

PBR で基本は全て DS-Lite に向けつつ、特定ホストやシステムのデフォルトルートは PPPoE に向けることにする。こうすると必要に応じてポート開放できたり、UPnP を喋らせたりできて便利

set firewall group network-group PRIVATE_NETS network 192.168.0.0/16
set firewall group network-group PRIVATE_NETS network 172.16.0.0/12
set firewall group network-group PRIVATE_NETS network 10.0.0.0/8
set firewall modify PBR-121 rule 10 action modify
set firewall modify PBR-121 rule 10 description 'これがないと VPN などが DS-Lite に吸われる'
set firewall modify PBR-121 rule 10 destination group network-group PRIVATE_NETS
set firewall modify PBR-121 rule 10 modify table main
set firewall modify PBR-121 rule 20 action modify
set firewall modify PBR-121 rule 20 destination group address-group ADDRv4_eth0
set firewall modify PBR-121 rule 20 modify table main
set firewall modify PBR-121 rule 91 action modify
set firewall modify PBR-121 rule 91 description 'ゲーム機とかはこうしてる'
set firewall modify PBR-121 rule 91 modify table main
set firewall modify PBR-121 rule 91 source address 192.168.XX.XX
set firewall modify PBR-121 rule 92 action modify
set firewall modify PBR-121 rule 100 action modify
set firewall modify PBR-121 rule 100 description 'Default to DS-Lite(table 121)'
set firewall modify PBR-121 rule 100 modify table 121

set interfaces switch switch0 firewall in modify PBR-121

set protocols static table 121 description 'default to v6tun0'
set protocols static table 121 interface-route 0.0.0.0/0 next-hop-interface v6tun0 distance 100

# デフォルトルート設定など
set port-forward wan-interface pppoe0
set protocols static interface-route 0.0.0.0/0 next-hop-interface pppoe0 distance 11
set protocols static interface-route 0.0.0.0/0 next-hop-interface v6tun0 distance 12
set service upnp listen-on switch0 outbound-interface pppoe0

3. LAN 内に IPv6 プレフィックスを広報する

1 で取得した /64 を RA で LAN 内に配ります。

set interfaces switch switch0 ipv6 address autoconf
set interfaces switch switch0 ipv6 dup-addr-detect-transmits 1
set interfaces switch switch0 ipv6 router-advert cur-hop-limit 64
set interfaces switch switch0 ipv6 router-advert link-mtu 0
set interfaces switch switch0 ipv6 router-advert managed-flag false
set interfaces switch switch0 ipv6 router-advert max-interval 600
set interfaces switch switch0 ipv6 router-advert other-config-flag false
set interfaces switch switch0 ipv6 router-advert prefix '2409:10:XXXX:XXXX::/64' autonomous-flag true
set interfaces switch switch0 ipv6 router-advert prefix '2409:10:XXXX:XXXX::/64' on-link-flag true
set interfaces switch switch0 ipv6 router-advert prefix '2409:10:XXXX:XXXX::/64' valid-lifetime 2592000
set interfaces switch switch0 ipv6 router-advert reachable-time 0
set interfaces switch switch0 ipv6 router-advert retrans-timer 0
set interfaces switch switch0 ipv6 router-advert send-advert true

できればここも autoconf だけで済ませて直打ちを避けたかったんですが、再起動するとアドレスが当たらなくなるので諦めています。4 フレッツの IPv6 プレフィックスは「半固定」とのことなので滅多なことでは変わらないと思いますが、過去1度再起動後に変わったことがあります。あと引っ越しでは(契約は引き継いだが)当然変わりました。

うまくいけば LAN 側インターフェイスにも IPv6 アドレスが付きます。

2: switch0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 1000
    link/ether fc:ec:da:XX:XX:23 brd ff:ff:ff:ff:ff:ff
    inet6 2409:10:XXXX:XXXX:feec:daff:feXX:XX23/64 scope global dynamic 
       valid_lft 2591805sec preferred_lft 604605sec
    inet6 fe80::feec:daff:feXX:XX23/64 scope link 
       valid_lft forever preferred_lft forever

LAN 内のクライアントも SLAAC で global IPv6 アドレスが取得できます。

 $ ip a

2: wlp60s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether a8:7d:12:XX:XX:XX brd ff:ff:ff:ff:ff:ff
    inet 192.168.XX.XX/24 brd 192.168.XX.255 scope global dynamic noprefixroute wlp60s0
       valid_lft 67359sec preferred_lft 67359sec
    inet6 2409:10:XXXX:XXXX:f6e3:2d57:97ba:a680/64 scope global dynamic noprefixroute 
       valid_lft 2591891sec preferred_lft 604691sec
    inet6 fe80::d234:29c:34:5381/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

4. NDP Proxy する

さてここまでで見かけ上 LAN 内には global IPv6 が当たりましたが、このままでは通信ができません。これは、上流の NGNルーターが LAN 内クライアントのアドレスを知らないためです。というわけで NDP Proxy で LAN 内クライアントのアドレス情報を上流ルーターに伝えてやります。

NDP Proxy の実装はこれを使わせてもらってます。

github.com

で、こいつを MIPS 向けにビルドする必要があるんですが、まあまあダルいのでビルドしたやつを置いておきます。無保証/自己責任でお願いします。 musl に static link しているので、環境を選ばず動くと思います。

https://minio.venusark.p1kachu.net/public/ndppd.zip

たぶん 2.x ファームなら Debian リポジトリからもインストールできるとは思いますが、これをやったのは 1.x ファームの時代で、 wheezy には ndppd なかった。

/config/user-data/ndppd に実行ファイルと設定を配置します。設定 ndppd.conf は以下です。

proxy eth0 {
      autowire yes

      rule ::/0 {
        iface switch0
      }
}

proxy switch0 {
      autowire yes
      router yes

      rule ::/0 {
        iface eth0
      }
}

起動スクリプト/etc/init.d/ndppd に配置します。こちらのコードは https://community.ui.com/questions/Set-up-IPv6-without-Prefix-Delegation/ea0998be-2d13-4747-ac1e-9a26cb1a2976 を参考にさせていただきました。

#!/bin/bash
ACTION=$1
NDPPD_DIR="/config/user-data/ndppd"
NDPPD_BIN="$NDPPD_DIR/ndppd"
NDPPD_CONF="$NDPPD_DIR/ndppd.conf"
NDPPD_PID="/run/ndppd.pid"

do_stop(){
        if [ -f $NDPPD_PID ]; then
                kill `cat $NDPPD_PID` > /dev/null 2>&1
                rm -f $NDPPD_PID
        fi
        echo 0 > /proc/sys/net/ipv6/conf/all/proxy_ndp
        echo 0 > /proc/sys/net/ipv6/conf/default/proxy_ndp
        /sbin/ifconfig switch0 -promisc
        /sbin/ifconfig eth4 -promisc
        /sbin/ifconfig eth3 -promisc
        /sbin/ifconfig eth2 -promisc
        /sbin/ifconfig eth1 -promisc
        /sbin/ifconfig eth0 -promisc
}
do_start(){
        if [ -f $NDPPD_CONF ]; then
                echo "Starting NDP Proxy Daemon ..."
                /sbin/ifconfig eth0 promisc
                /sbin/ifconfig eth1 promisc
                /sbin/ifconfig eth2 promisc
                /sbin/ifconfig eth3 promisc
                /sbin/ifconfig eth4 promisc
                /sbin/ifconfig switch0 promisc
                echo 1 > /proc/sys/net/ipv6/conf/default/proxy_ndp
                echo 1 > /proc/sys/net/ipv6/conf/all/proxy_ndp
                $NDPPD_BIN -d -c $NDPPD_CONF -p $NDPPD_PID
        else
                echo "ERROR: $NDPPD_CONF not found"
                exit 1
        fi
}
case "$ACTION" in
        start)
                do_start
        ;;
        restart)
                do_stop
                do_start
        ;;
        stop)
                do_stop
        ;;
        *)
                echo "$1 start|stop|restart"
        ;;
esac
exit 0

/etc/rc.local に追記すると自動起動できます。

service ndppd start

なお、 /config/user-data 外に配置したファイルについてはファームウェアアップデート時に失われるので、 /etc 以下をいじる際にはアップデート後に再度設定を行うことをお忘れなく。

できた

全てが上手く行っていれば LAN 内から IPv6 通信ができる状態になっていると思います。お疲れ様でした。あと v6 側のファイアウォール設定とかはよしなにやってください。

この記事を下書きから救い出した理由ですが、まだファームが1.xで止まってるのでいい加減2.xに上げようと思います。VPN周りのデグレが問題で上げれてなかった。


  1. ひかり電話がある場合、大体は NTT の HGW(ホームゲートウェイ)を利用することになると思うのですが、その場合 HGW が /56 を受け、その下流ルーターを置くことでさらに /60 が移譲されます。

  2. ひかり電話ありでも RA は送出されるが managed Flag 付きで DHCPv6 の利用が必須

  3. 工事費が安くなるという口車に乗せられてSB光にしたが情弱プレイだったと思う / 内容はフレッツの再販なので大した違いはないがBB光ユニットとかいうやつの存在がウザかった(返却しないと他のv6オプションが使えない)

  4. なんか net.ipv6.conf.switch0.accept_ra = 2 するとか色々頑張ってた気がするんだけど今見たらその設定どこにも見当たらないしすっかり忘れてしまった

HAProxy のログを journald のみで保存する

どうも。systemd シンパです。

で、rsyslogd がいない Ubuntu でデフォルト設定よろしく /var/lib/haproxy に chroot などしていると、/var/log/haproxy.log が出ません。

 # cat /etc/haproxy/haproxy.cfg 
global
        log /dev/log    local0
        log /dev/log    local1 notice
        chroot /var/lib/haproxy
        stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
        stats timeout 30s
        user haproxy
        group haproxy
        daemon
...

 # cat /var/log/haproxy.log
cat: /var/log/haproxy.log: No such file or directory

これは、ログをファイルに書き出すのが実際には RSyslog の役目*1で、その設定の中で chroot 先に rsyslogd のソケットを作っているためです。

 # cat /etc/rsyslog.d/49-haproxy.conf 
# Create an additional socket in haproxy's chroot in order to allow logging via
# /dev/log to chroot'ed HAProxy processes
$AddUnixListenSocket /var/lib/haproxy/dev/log

# Send HAProxy messages to a dedicated logfile
if $programname startswith 'haproxy' then /var/log/haproxy.log
&~

当然 rsyslogd が動作していない環境では /dev/log への送信ができなくなります。

 # ls -l /var/lib/haproxy/dev
total 0

ではどうするか。当然一番簡単なのは RSyslog をインストールして起動することですが、そうしたくない人はせっかく動いてる systemd-journald に送りつけましょう。

そんなわけでこんな感じの .mount ユニットを書く:

 # cat > /etc/systemd/system/var-lib-haproxy-dev-log.mount
[Unit]
Description=Mount /run/systemd/journal/dev-log to haproxy chroot
ConditionPathExists=/var/lib/haproxy/dev/log
PartOf=haproxy.service
Before=haproxy.service

[Mount]
What=/run/systemd/journal/dev-log
Where=/var/lib/haproxy/dev/log
Type=none
Options=bind

[Install]
WantedBy=haproxy.service

.mount は Where ダイレクティブに書いた内容が存在しないとディレクトリを新たに切っちゃうので、空のファイルを置いておきます。 *2

 # touch /var/lib/haproxy/dev/log

後はイネェーブルしておけば PartOf の効果で haproxy の起動時にこいつも起動される:

 # systemctl daemon-reload
 # systemctl enable var-lib-haproxy-dev-log.mount
 # systemctl restart haproxy

後は haproxy.cfg 側の log 設定を好きにしてください。 local1 つけて送ってる設定はもう要らないと思います。

アクセスログ(info/option httplog)だけ見たいときはこうじゃ:

 # journalctl SYSLOG_FACILITY=16 -u -p info..info
-- Logs begin at Fri 2020-04-04 01:47:14 JST, end at Sun 2020-04-12 10:05:01 JST. --
Apr 12 09:10:44 Mars1B haproxy[11947]: 192.168.21.50:56676 [12/Apr/2020:09:10:44.043] http_in~ darkhttpd_local/main 0/0/7/1/8 304 136 - - ---- 1/1/0/1/0 0/0 "GET "
Apr 12 09:24:07 Mars1B haproxy[25282]: 192.168.21.50:57080 [12/Apr/2020:09:24:07.289] http_in~ darkhttpd_local/main 0/0/6/1/7 304 136 - - ---- 1/1/0/1/0 0/0 "GET "
Apr 12 09:24:09 Mars1B haproxy[25282]: 192.168.21.50:57080 [12/Apr/2020:09:24:09.708] http_in~ darkhttpd_local/main 0/0/0/2/2 404 390 - - ---- 1/1/0/1/0 0/0 "GET "

めんどくせえやっぱファイルでくれやって人は素直に RSyslog 入れてください。現場からは以上です。

*1:HAProxy はログを syslog デーモンに送る機能しか持っておらず、ファイルに書き出す機構を持ちません

*2:例では ConditionPathExists も付けてる ちゃんとしたい人(?)は systemd-tmp-files を使ってください