ディスク内総検索その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
とか探しても仕方ないマウントポイントはいくつもあります。
ここでは -v
で grep
の論理を反転します。 -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
でマウントポイント以外のフィルタリングをしてから、 xargs
で grep
に流して終わり。
これでだいぶ高速になりました。コマンドは長いけどなー……
自宅ネットワークが不安定だった話
自宅のネットワークがめちゃくちゃ不安定で、まともに仕事ができなかったので真面目に調査して対応した話。
結論から言うと、NTT からレンタルの PR-600KI がアレという所に着地したんですけどね。 ただそこにたどり着くまでにいろいろなトラップにハマって延々半年以上かかってやっとこさ安定したのです。
最終的な対応策
- PR-600KI と ELECOM ハブの間に Aterm の無線ルータを挟む
- PR-600KI の Wi-Fi を無効化
- 代わりに Aterm の無線ルータに Wi-Fi 親機の仕事を押し付ける
- さらに PR-600KI を適当なファンで冷却する
これだけやって完全に安定したネットワークになりました。ゼェゼェハァハァ
あとは、安定度を測定するために ping を送るとき、分母を時間にするのを諦めて -c
で回数を指定しましょうというバッドノウハウを得ました。
なお、サポートに連絡して PR-600KI を新品に交換してもらいましたが、今回は効果なかったです残念。
いろいろな不具合
そこにたどり着くまでにいろいろな罠を踏んだのですよ。
- ELECOM のハブと PR-600KI を 1000Base で直結すると頻繁に link down する
- サーバに使ってる Intel 製 NIC 82574L という超化石は 100Base で動かすと不安定っぽい
- これもなんか頻繁に link down したりします。ドウシテ……
- 1000Base だと問題ないだよねぇ……逆にナンデ??
- PR-600KI は Wi-Fi 親機にすると熱暴走が加速する
- というか Wi-Fi アダプタがめっちゃ熱い。発熱すげぇ。
- ファンで冷やしてもこれじゃ足りない様子(変わらず link down する)だった……
- とはいえ別に Wi-Fi を無効化して運用してもやっぱり熱暴走する
- いや……あの……ファン必須なのこの子……??
- 82574L には TSO 関連の errata がある
- ping を途中で止めると最後のパケットが drop 扱いになるタイミングがある
- 詳しくは別記事にしました。冷静に考えればまぁ仕方ない仕様ではあるが……?
- PR-600KI とハブを直結すると数日に 1 回くらい link down が発生する
他にもなんか疑わしい謎挙動とかいろいろあったけど、結論として問題なのはこのあたりに集約されそう。
なんかルータとハブを同時にコールドスタートすると若干安定する??とか、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
FreeBSD の ping は -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 するたびにログがでてうるさい
ネットワークトラブルなどのとき、FreeBSD で tcpdump
を使うとログに
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
を付けると daemon
が SIGHUP
を受け取ったときにこのファイルを開きなおします。
あと、似た引数で -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
ログファイルを作って記録を開始。 syslogd
は reload
でもいいのかもしれない?
で、 /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
は私の好み。
これでだいじょぶそう。