特定のログが流れてきたときにコマンドを実行するやつをシェルスクリプトで書く
ログファイルの中身を追跡して、特定の文字列が流れてきたことを検知してコマンドを実行したい、ということがあり、
tail -n0 -f $1 | while read line do if [[ $line =~ 正規表現 ]] then echo '(∪^ω^)わんわんお!' # do something else fi done
こんな感じの watchdog じみたものを書いた。
しかし、ログファイルはローテートされるものである。しかも、監視対象のシステムは一定のタイミングで別名のファイルを新たに作成しそちらに書き込み始めるという挙動を行っていた(すなわち、tail --follow=name
や tail --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年式)。
もともと引っ越しの際にバイク駐輪場付き物件を視野にいれたりと、買う心づもりはなんとなくしていたものの、やれ緊急事態だなんだのですっかり期を逃してしまっていた。
とはいえ、いつまで虚無(駐輪場代)に月いくらも払っとんねんという気が大きくなったのでフッと勢いをつけて買った。
ジクサー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 ネオンライト 構文?
ネオンライト構文
— 星宮とと (@hoshimiya_toto) 2020年4月17日
(Flanger FX)(ネオンライト イントロ)行け行け行け行け!行け行け行け行け!オイオイオイオイオイ!オーーイ!FOOOOOO おいリワインドしろリワインド!リワインドしろ(リワインドする音)FOOOOOイエイエイエイエイエイFOOパーッパパパーパッパパッパーパッパッパー(イントロ合唱)
有史以前より存在したと考えられており、現在確認される最古の記録は以下の音声記録である。
このシーンとても好き #RIP0526 pic.twitter.com/75dOhDwW4H
— COCOA*☕️ (@v_cocoa_) 2019年5月26日
原典
(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 (جوقة المقدمة)
診断
その他の改変例/追加案ありましたらコメントまでお寄せください。
0pxの画像ファイル
序
0px.org というドメインを持っています。このドメインはなるべく短く、かつ意味ありげなドメインが欲しいと思って選んだだけで、特に意味はありません。専らサーバーの alias や短縮 URL に使っています。
さて、0px.org で配布すべきリソースとはなんでしょうか。当然 0px×0px の画像ファイルです。しかし、どんな画像編集ソフトでも大抵キャンパスサイズの最小は 1px×1px です。そもそも 0px の画像を許すフォーマットなどあるのでしょうか。というか画像を2次元的なものとするなら、0px×0px の画像は果たして画像なのでしょうか。
……とりあえず 0px 画像の哲学的な問いかけは一旦忘れることとして、思いついたメジャーな画像フォーマットについて仕様上 0px×0px の画像が許されるのか、調べることにしました。
PNG
3章 File Structure には PNG ファイルは PNG file signature(固定8バイト)と chunks からなるとされています。そのうち必須となる chunks が 4.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 仕様書 を参照します。
JFIF フォーマットは JPEG の SOI
(Start of Image) マーカーセグメント、JFIF 情報を格納する APP0
セグメントから始まり、画像データをコードした後、EOI
(End of Image) マーカーで終わります。
JPEG の画像データは DCT による量子化情報を記述するテーブル DQT
セグメント、 ハフマン符号化による圧縮を行うためのテーブル DHT
セグメント、実際のスキャンデータを格納する SOS
セグメント、スキャンデータの形式を格納する SOF0
セグメントからなり、これらが合わさり画像データを形成します。(最も基礎的な Baseline DCT の場合)
このうち、画像サイズに直接関わるのはピクセルアスペクト比を決める APP0
の Xdensity, Ydensity (両方 1
で PAR 1:1 となる)と SOF
の X および 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
を見てみます。
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
も見てみます。
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 Width と Logical 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
ちゃんと読み込んでいませんが、TIFF の ImageWidth と ImageLength はデータ型(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"/>
例えばこのように書けると思います。
そのほか参考になったサイト
様々なファイルフォーマットについて、仕様上許される最小サイズのものを集めたリポジトリです。GIF ファイルはこの記事の解説によるもののようで、1px×1pxを Logical Screen Descriptor に書いているようです*2。JPEG は最低限 1px が表示できるような DCT テーブルとフレームのみを含んだ 107 バイトのものなのですが、前述のように JFIF には SOI
直後の APP0
が必須なので JFIF 準拠ではない生 JPEG ストリームです。逆にフレームを含まず JFIF 準拠な最小*3を提案できる気がするんですが…… Issue 立ててみようかな
JPEG フォーマット、GIF フォーマットに関する日本語文献です。特に JPEG は重厚でちゃんと読めてる自信がないので助かりました。
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 ルーティングでことを済ませたい、というのが本記事の背景となります。
構成
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 の実装はこれを使わせてもらってます。
で、こいつを 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周りのデグレが問題で上げれてなかった。
-
ひかり電話がある場合、大体は NTT の HGW(ホームゲートウェイ)を利用することになると思うのですが、その場合 HGW が /56 を受け、その下流にルーターを置くことでさらに /60 が移譲されます。↩
-
工事費が安くなるという口車に乗せられてSB光にしたが情弱プレイだったと思う / 内容はフレッツの再販なので大した違いはないがBB光ユニットとかいうやつの存在がウザかった(返却しないと他のv6オプションが使えない)↩
-
なんか
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 入れてください。現場からは以上です。