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

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

ディスク内総検索その2(高速化してみた)

FreeBSD システムのディスク全体から特定の記述を探したい場合、ありますよね。 例えば IPv6 プレフィックスが変わったので全体の設定を変えなきゃいけない時とか。どこに設定したっけ…?みたいな。

そんな時はざっくり全体から検索してしまいましょう。

$ sudo find / -path '*/dev/*' -prune -o -path '*/proc/*' -prune -o -path '*/var/log/*' -prune -o -name '*.log' -prune -o -path '*/basejail/*' -prune -o -type f -print0 | sudo xargs -0 grep "search target" | tee result.txt

…いやなっげぇよ!!

まぁ、以前同じ内容の記事を書いたときのやり方そのままですね。 hoshizuki.hateblo.jp

やってることは、 find/ 起点で実行して、別に探さなくてもいいパスを -path '*/var/log/*' -prune -o でどんどん落としています。 -o つまり OR の短絡評価によって途中でマッチしたパスを間引いていって、最後に残ったものを -print0 します。 前回の記事と違って、最近は -path を使ってワイルドカードでの一致にしていますね。正規表現面倒で嫌いなので。

あとはおなじみ xargs からの grep です。まぁまぁ単純でシンプルなコマンドです。 出力結果は stdout でリアルタイムに眺めつつ、一応ファイルにもロギングしているおまけ付き。

なお、前回の記事に書いた通り、ディレクトリ名にスペースが含まれていると xargs につっこんだときに分解されて悲しい目に遭うので、 -print0 で出して xargs -0 で受けます。

シンプルだけれども、できればマウントポイントごとフィルタ除外したいっていうか、 grep の前の find は一応全ディレクトリを見に行くので、その無駄すらも何とかしたい。

そこでこんな改良。

$ ls / | grep -v -e home -e sys -e mnt | sudo xargs -n 1 -I {} find {} -type f | sudo xargs grep "search target" | tee ~/grep_result.txt

/ 直下のディレクトリ一覧を ls で取得して、 grep でざっくりフィルタリング。 /home とか /sys とか /mnt とか探しても仕方ないマウントポイントはいくつもあります。 ここでは -vgrep の論理を反転します。 -e で検索対象を複数書くのと組み合わせると、「いずれにもマッチしないもの」のみを抽出できます。

んでそれを xargs で順に find に投げて、全ファイルの一覧から grep します。

しかし、特に ezjail でありがちな、いろんな所でいろんな所を nullfs でマウントしてると、これだけだとまだ弱い。マウントポイントはイマドキ / だけじゃない。

そんな訳でこんなパターンが最近のお気に入り。

$ mount -p | awk '{print $2}' | grep -v -e '/basejail$' -e '/dev$' -e '/dev/fd$' -e '/proc$' -e '/home$' -e '/var/ports$' -e '^/mnt/external$' | sudo xargs -n 1 -I {} find {} -mount -path '/usr/src/*' -prune -o -path '/usr/ports/*' -prune -o -path '*/basejail/*' -prune -o -path '*/var/log/*' -prune -o -type f -print0 | sudo xargs -0 grep 'search_target' | tee result.log

さらに長くなったナァ……

mount -p で現在のマウント状況を fstab フォーマットでダンプしてくれます。 awk で第2フィールド、つまりマウントポイントのみのリストにして、これをさっきの例のように grep -v -e ... -e ... でフィルタします。最初の grep ではマウントポイントしか出てこないので、例えば末尾のディレクトリ名などでパターンパッチングします。

次は同じように xargs からの find ですが、最初に -mount を付けるのがミソ。これでマウントポイントになってるディレクトリで検索を打ち切ります。そのマウントポイントが検索対象ならば別途 xargs に入ってくるレコードによって補完されますし、対象外ならそのまま無視になります。

後は同じように -path '...' -prune -o でマウントポイント以外のフィルタリングをしてから、 xargsgrep に流して終わり。

これでだいぶ高速になりました。コマンドは長いけどなー……

自宅ネットワークが不安定だった話

自宅のネットワークがめちゃくちゃ不安定で、まともに仕事ができなかったので真面目に調査して対応した話。

結論から言うと、NTT からレンタルの PR-600KI がアレという所に着地したんですけどね。 ただそこにたどり着くまでにいろいろなトラップにハマって延々半年以上かかってやっとこさ安定したのです。

最終的な対応策

  1. PR-600KI と ELECOM ハブの間に Aterm の無線ルータを挟む
    • どちらも Aterm下流ポートにつなぐ。ハブ…というかリピータ的な使い方?
  2. PR-600KI の Wi-Fi を無効化
  3. 代わりに Aterm の無線ルータに Wi-Fi 親機の仕事を押し付ける
  4. さらに PR-600KI を適当なファンで冷却する

これだけやって完全に安定したネットワークになりました。ゼェゼェハァハァ

あとは、安定度を測定するために ping を送るとき、分母を時間にするのを諦めて -c で回数を指定しましょうというバッドノウハウを得ました。

なお、サポートに連絡して PR-600KI を新品に交換してもらいましたが、今回は効果なかったです残念。

いろいろな不具合

そこにたどり着くまでにいろいろな罠を踏んだのですよ。

  1. ELECOM のハブと PR-600KI を 1000Base で直結すると頻繁に link down する
    • そもそも最初に発覚したトラブルはたぶんこいつ。
    • 外から来てる光ファイバーを NTT の HGW で受けている訳ですが、PR-600KI の有線 LAN ポートは 4 つしかないので一旦 ELECOM のハブにつないでそこから各部屋に分岐している配線でした。
    • で、ELECOM ハブの LED を眺めていると唐突に上流側のポートだけが link down している訳ですね。キェー
    • そして切り分けのために調達してきた Buffalo や NETGEAR のハブでも症状は変わらない……
    • 最終的にどうやら熱暴走では?という結論。Wi-Fi 切ってファンで冷やしたら安定したので。(#^ω^)ピキピキ
  2. サーバに使ってる IntelNIC 82574L という超化石は 100Base で動かすと不安定っぽい
    • これもなんか頻繁に link down したりします。ドウシテ……
    • 1000Base だと問題ないだよねぇ……逆にナンデ??
  3. PR-600KI は Wi-Fi 親機にすると熱暴走が加速する
    • というか Wi-Fi アダプタがめっちゃ熱い。発熱すげぇ。
    • ファンで冷やしてもこれじゃ足りない様子(変わらず link down する)だった……
  4. とはいえ別に Wi-Fi を無効化して運用してもやっぱり熱暴走する
    • いや……あの……ファン必須なのこの子……??
  5. 82574L には TSO 関連の errata がある
    • FreeBSD 純正のドライバだとドライバの実装で強制無効化されてました。
    • Intel 公式のドライバを試したら有効になって、errata を踏んで kernel panic。
    • ifconfig -tso em0 で殺せばよさそう?まぁわざわざ最新ドライバ使う必要もないか?
  6. ping を途中で止めると最後のパケットが drop 扱いになるタイミングがある
    • 詳しくは別記事にしました。冷静に考えればまぁ仕方ない仕様ではあるが……?
  7. PR-600KI とハブを直結すると数日に 1 回くらい link down が発生する
    • 熱暴走を解決してもなぜかこっちの症状が残る。
    • ELECOM ハブと PR-600KI を、Aterm 無線ルータの下流につないだら解決した。
    • なんだろう、電気的な GND とかノイズとかの都合で何かリピータみたいなのが必要だったってこと??

他にもなんか疑わしい謎挙動とかいろいろあったけど、結論として問題なのはこのあたりに集約されそう。

なんかルータとハブを同時にコールドスタートすると若干安定する??とか、PR-600KI 宛に ping を送ると急激に不安定になるっぽい??とか、PR-600KI の下流ポートは場所によって安定度が違う??とか、ケーブルによって安定度が違う??などなど……

よくわからない変な挙動でしたが、一応安定したのでこれでいいかなって。静電気とかノイズとかいろいろ影響してそうだけれども、Aterm 挟んで解決するならそれでいっか…みたいな気持ちで解決したことにしました。

ちなみに、Mauknci とかいうメーカーのファンが静かで常時稼働させるにはよかったです。 Amazon で適当にポチりました。

一定時間での ping 結果を見たいとき

こういうスクリプトを実行するとたまに悲しいことになります。

#!/bin/sh -x
ping 192.168.0.1 &
sleep 1.005
kill -INT %1

FreeBSD だと sleep の引数は小数点以下も有効なので。 ミリ秒の桁で発生頻度が変わりますが、うまく調整するとこうなります。

+ sleep 1.005
+ ping 192.168.0.1
PING 192.168.0.1 (192.168.0.1): 56 data bytes
64 bytes from 192.168.0.1: icmp_seq=0 ttl=64 time=0.764 ms
+ kill -INT %1

--- 192.168.0.1 ping statistics ---
2 packets transmitted, 1 packets received, 50.0% packet loss
round-trip min/avg/max/stddev = 0.764/0.764/0.764/0.000 ms

50% loss...oh...2個目を送ったのに帰ってくる前にタイムアウトしちゃったかぁ……

同系統の現象でこういうパターンも作れますね。

$ ping -t 1 8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: icmp_seq=0 ttl=118 time=5.834 ms

--- 8.8.8.8 ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 5.834/5.834/5.834/0.000 ms
$ ping -t 1 8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: icmp_seq=0 ttl=118 time=6.168 ms

--- 8.8.8.8 ping statistics ---
2 packets transmitted, 1 packets received, 50.0% packet loss
round-trip min/avg/max/stddev = 6.168/6.168/6.168/0.000 ms

FreeBSDping-t で所定時間後に終了するのですが、 宛先までの到達時間次第ではこんな風に。

実行するたびにランダムに(?)送れるパケットが 1 だったり 2 だったりして、 タイミング次第では 2 個目の応答は間に合わず……(´・ω・`)

また別パターンだとこう。

$ timeout -s SIGINT 1.005 ping 192.168.0.1
PING 192.168.0.1 (192.168.0.1): 56 data bytes
64 bytes from 192.168.0.1: icmp_seq=0 ttl=64 time=0.843 ms

--- 192.168.0.1 ping statistics ---
2 packets transmitted, 1 packets received, 50.0% packet loss
round-trip min/avg/max/stddev = 0.843/0.843/0.843/0.000 ms

timeout コマンドでも冒頭の fork & kill と同等のことが発生しますね。

教訓としては、ping を指定時間で止めるのはやめましょうということですかね。 素直に -c 300 とかやるしかなさそうです。これだとぴったり 5 分にはなりませんが。

誰かぴったり 5 分間 ping を送る方法、知りませんかね?

tcpdump するたびにログがでてうるさい

ネットワークトラブルなどのとき、FreeBSDtcpdump を使うとログに

kernel: lo0: promiscuous mode enabled
kernel: lo0: promiscuous mode disabled

とか出てきてうるさいです。

重要なログを見落とすやろ……

という訳で、そんな時は /boot/loader.conf にこの1行を追加します。

net.link.log_promisc_mode_change="0"

はい、静かになりました。

ちなみに、 /etc/sysctl.conf ではダメです。なぜなら

$ sudo sysctl net.link.log_promisc_mode_change=0
sysctl: oid 'net.link.log_promisc_mode_change' is a read only tunable
sysctl: Tunable values are set in /boot/loader.conf

こうなるからです。

daemon コマンドでコンソールログを残す方法

以前の記事で、 daemon コマンドを使うとシェルスクリプトとかを簡単に デーモンとして常時稼働させられるねーこれ便利ねーみたいな話を書きました。

認証エラーログを見て ipfw で ban するやつ - ほっしーの技術ネタ備忘録

そのデーモン化したいプログラムから stdout とかに出力したデータを ファイルに残しておく話です。

やり方は簡単で daemon の引数に -o /var/log/hoge_console.log とか書くだけ。 簡単ですね。

(ちゃんと)ログローテートもする

ただ、これだとログファイルが延々と増え続けて死にます(ストレージが)。 …いやイマドキなら死なないかな?

そんなときに使うのはもちろん、 newsyslog ですね。 /etc とか見てると、イマドキは .dディレクトリに設定ファイルを書くのが主流っぽいですね?

という訳で、 /usr/local/etc/newsyslog.conf.d/ に適当なファイル名+ .conf で設定ファイルを書きます。 こんな1行。

/var/log/hoge_console.log root:wheel 644 10 100 * CEXp /var/run/hoge.pid

先頭はさっき daemon-o に渡したファイル名。たぶんフルパスじゃないと死にそう。

で、ポイントになるのはオプション CEXp の後ろに daemon の PID ファイル名を書くこと。 これでローテートを行うときに SIGHUP を送ってくれます。

なので、対応するように daemon の引数には -H -P /var/run/hoge.pid を追加します。 -H を付けると daemonSIGHUP を受け取ったときにこのファイルを開きなおします。 あと、似た引数で -p だと子プロセス( daemon から起動する方)の PID が書かれるので間違えないこと。

間違うとローテートしてからのログが消滅したりして悲しいことになります。

screen のロック機能を殺す

みなさん screen 使ってますか? 私は未だに使ってますが、世の中的には tmux が主流なんでしょうかね。

こいつにはなぜかスクリーンロックって機能があって、 ワンタッチで画面(コンソールだけど)をパスワードロックできます。

まぁ、イマドキな環境ならパスワードなんて使わないですよね……何なら覚えてないまである。 乱数で作ってそのまま破棄しちゃう。

そんなわけで、誤爆して困ることになるのですが、なんとこいつ、 SSH コネクションを張りなおすと何事もなく再接続できます。

……ロックの意味???

前置きが長いですがやることはひとつ。 screen の起動前にこいつ。

setenv LOCKPRG /usr/bin/true
screen

sh 系を使ってるならこっちで。

export LOCKPRG=/usr/bin/true
screen

今回はこれだけ。ほんとに備忘録やね。

openntpd で時刻合わせ

ついうっかり設定を忘れていたものがあったので、設定の手順をメモ。

まずは openntpd をインストールします。

$ sudo pkg install openntpd

で、 /usr/local/etc/ntpd.conf を編集。

servers ntp.nict.jp

もうこの1行だけでいいんじゃないかな。

次は /etc/syslog.conf を編集。

!ntpd
*.*                                             /var/log/ntpd.log

以前はコメントアウトを解除するだけでよかったのに、 いつの間にか消えてしまっていた…… ていうか最近は /etc/syslog.d/ に書くべきなのかもしれない。

$ sudo touch /var/log/ntpd.log
$ sudo chmod 644 /var/log/ntpd.log
$ sudo /etc/rc.d/syslogd restart

ログファイルを作って記録を開始。 syslogdreload でもいいのかもしれない?

で、 /etc/rc.conf に以下の行を追加。

openntpd_enable="YES"

はい、実行開始。

$ sudo /usr/local/etc/rc.d/openntpd start

暇だったらログとか眺めるなど。

$ tail -f /var/log/ntpd.log
XXX XX 00:31:15 host ntpd[1278]: clock is now synced

よしっ。

あ、あんまり時刻がズレてると調整してくれなかったりするみたいなので、 そういう時は先に $ sudo ntpdate ntp.nict.jp とか打つといい(のかな?)。

ログローテートも忘れないこと

syslog の設定を変えたのはいいけど、 それだけだとログファイルが肥大化して泣くことになりました。

という訳で /usr/local/etc/newsyslog.conf.d/ntp.conf を作ります。

/var/log/ntpd.log       root:wheel      644     5       100     *       CEXp

最初に書くのはさっき syslog.conf に書いたファイル名。

で、後ろに続くのはファイルオーナー・パーミッション・連番で残すファイル数。 さらにローテートの条件になるファイルサイズと時刻。 オプションの CEXp は私の好み。

これでだいじょぶそう。