portsnap, freebsd-updateにuser:password@proxy形式のHTTP_PROXYを読ませるには。(phttpgetを改造)
http://d.hatena.ne.jp/flageo/20060501/p1
でも書いたけど、phttpget、つまりはportsnap, freebsd-updateはhttp://user:password@proxy.server.com:8080形式の環境変数HTTP_PROXYを読んでくれない。
そこでportsnap, freebsd-updateを実行するときにはHTTP_PROXY, HTTP_PROXY_AUTHに付け替える必要があるわけだが、これが面倒くさい。
というわけで、phttpget自体を改造する。
ネタはhttp://www.freebsd.org/cgi/query-pr.cgi?pr=129431
$ uname -r 8.2-RELEASE-p3 $ grep FBSDID ./phttpget.c __FBSDID("$FreeBSD: src/usr.sbin/portsnap/phttpget/phttpget.c,v 1.14.2.1.6.1 2010/12/21 17:09:25 kensmith Exp $");
以上の/usr/src/usr.sbin/portsnap/phttpget/phttpget.cに対して以下のような修正を。
$ diff -u phttpget.c.orig phttpget.c --- phttpget.c.orig 2012-04-05 10:58:52.000000000 +0900 +++ phttpget.c 2012-04-05 11:04:25.000000000 +0900 @@ -44,7 +44,7 @@ #include <sysexits.h> #include <unistd.h> -static const char * env_HTTP_PROXY; +static char * env_HTTP_PROXY; static char * env_HTTP_PROXY_AUTH; static const char * env_HTTP_USER_AGENT; static char * env_HTTP_TIMEOUT; @@ -136,6 +136,11 @@ p = strchr(env_HTTP_PROXY, '/'); if (p != NULL) *p = 0; + if (strchr(env_HTTP_PROXY, '@')) { + proxy_auth_user = strsep(&env_HTTP_PROXY, ":"); + proxy_auth_pass = strsep(&env_HTTP_PROXY, "@"); + p = strchr(env_HTTP_PROXY, '@'); + } p = strchr(env_HTTP_PROXY, ':'); if (p != NULL) { *p = 0;
あとは/usr/src/usr.sbin/portsnap/phttpget/でmakeして、できたphttpgetを/usr/libexec配下にコピーすればOK。
当然ながらOSの更新(freebsd-updateやmake buildworld install)すると元に戻るので注意。
宅鯖FreeBSDを節電しよう
はいはいはいドーモそういうわけでですね、自宅鯖の節電をやっていきたいわけですけれども。
9.0-RELEASEのIntelで実施しましたので共有。
AMDでも9.xならなんとかできそう。
しかし8.xかつAMD CPUの方は解散で。
ただ、MLなどをつらつら見ていると、以下の設定を行っても効果がでないケースもあるようなので各自調整のこと。(例: C2よりC3の方がなぜかCPU温度が上がるとか)
やること。
やることをさっさと書く。
CPU throttlingを無効に。
/boot/loader.confで指定。
具体的にはp4tccを無効に。sysctlで調べて複数あればすべてつぶすこと。
以下の例では二つ。
$ sysctl -a|grep "p4tcc" dev.p4tcc.0.%desc: CPU Frequency Thermal Control dev.p4tcc.0.%driver: p4tcc dev.p4tcc.0.%parent: cpu0 dev.p4tcc.0.freq_settings: 10000/-1 8750/-1 7500/-1 6250/-1 5000/-1 3750/-1 2500/-1 1250/-1 dev.p4tcc.1.%desc: CPU Frequency Thermal Control dev.p4tcc.1.%driver: p4tcc dev.p4tcc.1.%parent: cpu1 dev.p4tcc.1.freq_settings: 10000/-1 8750/-1 7500/-1 6250/-1 5000/-1 3750/-1 2500/-1 1250/-1
以下のように。
/boot/loader.conf: hint.p4tcc.0.disabled=1 hint.acpi_throttle.0.disabled=1 hint.p4tcc.1.disabled=1 hint.acpi_throttle.1.disabled=1
C-states設定
/etc/rc.confに設定を加え、C3まで落ちるようにする。
RELEASE、CPUに応じて/boot/loader.confに追加の設定を加える。
9.x, intelの場合
/etc/rc.conf: performance_cx_lowest="C3" economy_cx_lowest="C3"
8.x, intelの場合
/etc/rc.conf: performance_cx_lowest="C3" economy_cx_lowest="C3" /boot/loader.conf: hint.apic.0.clock=0 kern.hz=100 hint.atrtc.0.clock=0
9.x、AMDの場合
/etc/rc.conf: performance_cx_lowest="C3" economy_cx_lowest="C3" /boot/loader.conf: hint.apic.0.clock=0
再起動。
sysctlで確認
p4tccが表示されない。
$ sysctl -a|grep p4tcc $
C3が有効になっていて、再起動直後ということもあるけど、システムがほとんどC3ステートにいることが分かる。
$ sysctl -a|grep cx hw.acpi.cpu.cx_lowest: C3 dev.cpu.0.cx_supported: C1/1 C2/1 C3/57 dev.cpu.0.cx_lowest: C3 dev.cpu.0.cx_usage: 0.00% 0.06% 99.93% last 432us dev.cpu.1.cx_supported: C1/1 C2/1 C3/57 dev.cpu.1.cx_lowest: C3 dev.cpu.1.cx_usage: 0.00% 0.10% 99.89% last 907us
上記設定の意味
ではその意味などを。
1: CPU throttlingの停止について
powerdはCPUの周波数変更(CPU throttling)とEISTの組み合わせ。
周波数変更は単純に周波数だけ変更する。
EISTは周波数と電圧を変更する。
前者の周波数変更は、どうも周波数を実際に「落とす」わけではなく、周波数はそのままに「動作をするのはクロック8回に1度な」というように単に動作タイミングを間引いているだけらしい。
したがって、発熱を抑える効果はあっても(CPU Frequency Thermal Control)、電力消費を抑える効果は薄い。
効果のない選択肢があっても無駄なだけなのでバッサリ切る。
2: C-statesの設定
C-statesは以下の通り。
下に行けば行くほど節電できる。システムは低負荷時にあらかじめ設定されたC-states(C状態)まで動作を落とす。
デフォルトはC1。C2, C3まで落とすようにするには/etc/rc.confで指定する。
C1: CPUコアの一部のクロックを停止する。
C2: CPUコアのクロックを停止する。
C3: CPUの内部クロック停止、電圧を下げ、システムバスから切り離す。
2-1: AMDの制限
AMDの場合、詳細なC StatesはOSに対して隠蔽される。代わりにC1Eというstateがある。
OSからはマシンがC2にいようが、C3にいようが、C1Eとしてしか分からない。
後述するようにC3ではタイマーに関しての考慮が必要になるのだが、OSから見えないのではどうにもできない。したがってAMDとRELEASEの組み合わせにより、具体的には8.xとAMD CPUではC1Eへの移行が抑止される。
2-2: OS, RELEASEの組み合わせごとのC3の設定
節電の観点ではC3が一番良いが、この状態だとAPICタイマーも機能しなくなる。
APICタイマーが止まるとスケジューリングが出来ず、復帰もできなくなる。
したがって、APIC以外のタイマーを使う必要がある。
RELEASE、CPUにより回避策に違いが生まれる。
8.x intelにおいては、APICを使うこと自体を止めれば別タイマ(i8254, RTC)を使ってくれる。
ただ、C3からの復帰に時間がかかってしまうので(といってもusのレベル)、/boot/loader.confで調整を行う。
9.x intelにおいては、eventtimersという適切なタイマを選んでくれる仕組みがあるので特に考慮不要。
8.x amdにおいては、
OSから分からないところでC3に遷移してAPICタイマを止められてはかなわないので、OSレベルでC1E機能が抑止される。
つまりC-statesによる節電は無理。これが解散の理由。
9.x amdにおいては、
APICタイマが有効なときのみC1E機能が抑止される。
だからAPICタイマを無効にすればOK。
参考
CPU throttling
http://en.wikipedia.org/wiki/Dynamic_frequency_scaling
C-States
http://okwave.jp/qa/q4539201.html
EIST
http://ja.wikipedia.org/wiki/Intel_SpeedStep_%E3%83%86%E3%82%AF%E3%83%8E%E3%83%AD%E3%82%B8
FreeBSDをインストールしたらやること。(no GUI編)
FreeBSDをインストールしてやることをまとめたよ。
まずrootでログイン
シェル、sudo、screen、vim-lite(日本語OKなvi)をインストール。
# pkg_add -r bash sudo screen vim-lite
以降、viはvim等と読み替えておくれ。
# vipw
自アカウントのシェルを変更。
# vi /etc/group
wheelに自アカウントを追加。
sudoが使えるように。
これ以降、原則としてrootは使わない。
# visudo (以下の%wheelの行をアンコメントする。) ## Uncomment to allow members of group wheel to execute any command %wheel ALL=(ALL) ALL
自分のアカウントでログイン。
ホームディレクトリの.profileに以下を追加。
言語設定とパッケージの取得先変更。
# # modified # LANG=ja_JP.UTF-8;export LANG PACKAGEROOT="ftp://ftp2.jp.freebsd.org";export PACKAGEROOT
上記設定を読み込み。
$ . ~/.profile
portsの更新
$ sudo vi /etc/portsnap.conf (portsnapの取得先をfreebsd.orgからallbsd.orgへ変更(感謝)) #SERVERNAME=portsnap.FreeBSD.org SERVERNAME=portsnap.allbsd.org
既存のportsは一回捨てる。
rmするのも時間がかかるので、いったんmvして消す。
で、portsnapで取り直し。
$ sudo mv /usr/ports /usr/ports.org $ sudo rm -Rf /usr/ports.org (このあとバックグラウンドにするとよい) $ mkdir /usr/ports $ sudo portsnap fetch extract
時間がかかるのでさらにターミナルを起動。
起動時のサービスの設定
$ sudo vi /etc/rc.conf 以下を(なければ)追加。 sshd_enable="YES" powerd_enable="YES" #低負荷の時にクロック等を下げる powerd_flags="-a adp -n adp" ntpdate_hosts="ntp.jst.mfeed.ad.jp" #時刻合わせ ntpdate_enable="YES" #sendmail swtich. see rc.sendmail(8) sendmailを止める。 sendmail_enable="NO" sendmail_submit_enable="NO" sendmail_outbound_enable="NO" sendmail_msp_queue_enable="NO"
powerd, ntpdateを起動。sendmailはまあ...後で再起動か。
$ sudo service powerd start $ sudo service ntpdate start
locateデータベースの作成
放っておけば一週間に一回更新してくれるのだが、すぐに使いたいので。
$ sudo /etc/periodic/weekly/310.locate
あとはports管理とか。
$ sudo pkg_add -r psearch pkg_replace portmaster portaudit
でかい言語系。
$ sudo pkg_add -r perl python
とりあえずこんなもん。
起動スクリプト操作コマンドservice(Linuxのchkconfigの簡易版)
FreeBSDにおいて、各種サーバソフトウェアの起動・停止を行う起動スクリプトは/etc/rc.d、/usr/local/etc/rc.dに格納されている。
いちいち/usr/local/etc/rc.d/apache22 startなどとキーを叩くのは面倒で仕方がない。
そこでportsにあるbsdadminscriptsなどを使っていたのだが、ふと気が付くと7.3あたりからserviceというコマンドが作られたようだ。
使い方。
書式。
service <起動スクリプト> start|stop|restart等々
使用例
$ sudo service dovecot status Password: dovecot is running as pid 1026. $ sudo service dovecot restart Stopping dovecot. Waiting for PIDS: 1026. Starting dovecot.
注意点としては、引数で与えるのはあくまでも起動スクリプト名であって、サーバソフトウェアの名前ではない、という点。
例えば、dhcpdだとisc-dhcpdで指定しないといけないが、それを思い出せないこともしばしば。
だから後述の使用法も使って、起動スクリプト名を調べるとよい。
そのほかの使い方:起動スクリプトに関する情報が得られる。
service -e 有効になっているサービスを表示する。 起動順(rcorder)に表示 service -r 無効になっているものも含めてサービスを表示する。 起動順(rcorder)に表示。 もちろん無効になっているものは、もしも有効だったら という仮定で。 service -l rc.dディレクトリの下にあるファイルをすべてリストする。 /etc/rc.dのほか、たとえば/usr/local/etc/rc.dなど。 -v ほんの少しだけ説明が増える。 (試してみたら本当に少しだけだった)
例えば。-rだと、-eのときにはない起動スクリプトも表示されていることが分かる。
$ service -e|grep "/usr/local" /usr/local/etc/rc.d/mrtg_daemon /usr/local/etc/rc.d/jenkins /usr/local/etc/rc.d/dovecot /usr/local/etc/rc.d/clamav-clamd /usr/local/etc/rc.d/clamav-freshclam /usr/local/etc/rc.d/apache22 $ service -r|grep "/usr/local" /usr/local/etc/rc.d/svnserve /usr/local/etc/rc.d/rsyncd /usr/local/etc/rc.d/rrdcached /usr/local/etc/rc.d/munin-node /usr/local/etc/rc.d/mrtg_daemon /usr/local/etc/rc.d/jenkins /usr/local/etc/rc.d/htcacheclean /usr/local/etc/rc.d/dovecot /usr/local/etc/rc.d/clamav-clamd /usr/local/etc/rc.d/clamav-freshclam /usr/local/etc/rc.d/apache22
ZFSの重複ファイル節約機能dedupがすげえ(ただしメモリ大尽に限る)
最初にお断りするが、十分なメモリ、あるいはSSDをお持ちでない方は帰っていただいて結構です。
Dedupとは
ZFSにはdedupという機能がある。
その機能を有効にすると、例えばここに1GBのファイルが一つあるとして、それをコピーしても、場所が同じpool内である限り、1GBのディスクしか消費しない。
何それただのハードリンクと思うのは早い。
仮に同一のファイルA, Bがあるとする。いずれも1GB。
ハードリンクすればディスク消費量は1GBだ。
さてここで、ファイルBの一部、1bitだけを変えたいとする。
もはやハードリンクはできず、別個のファイルとして扱うことになる。
したがってディスク消費は2GB。
ではdedupだとどうなるか。
1bit違う1GBのファイル二つがあっても、なんと1GBと128KBだけしかディスクを消費しないという驚きの仕組み。
どういうことかというと、dedupはファイルが同じかどうかをブロックごとに判断するということ。
先の例でいえば、異なる1bitを含むブロック分だけを追加で確保し、それ以外はファイルAと同じものを使う。
なお、ZFSでブロックサイズは512B〜128KB。
つまり大目に見積もっても1GBと128KBだけの消費でよいわけ。
種明かし:テーブルと大量のメモリ
なぜそんなことができるのか。
ZFSはプール上にあるデータのすべてのブロックのハッシュをメモリ上に持っている。
あるファイルをディスクに書き込む前に、ファイルをブロックに分解しハッシュテーブルと照合、書き込み要否を判断するという仕組み。
問題はメモリ上に置くテーブルのサイズだ。
dedupを有効に使うには、テーブルを置けるほど十分なメモリが必要になる。
しかし、のちほど見積もりをするが、数TBのディスクを考えるとメモリで賄うのは少々厳しい。
当然、メモリをこればっかりに使うわけにもいかないのだし。
もちろん、テーブルをハードディスクに置くことはできるが、ファイルを書き込むたびにディスク上のハッシュテーブルを参照することになる。
つまりすっごく遅くなる。
よろしい。ならばSSDだ。
とはいえ、Dedupの目的がディスクの容量節約ならば、安いHDDケチってメモリ、SSD無理して買うのも本末転倒という話になってくる。
月並みだけど、よく考えた方がいいよね。
Dedupの見積もり。
では仮に2TBのデータが詰まったZFSでDedupしたら、どれくらいのメモリが必要か。
ハッシュテーブルは1ブロックにつき320Bytes。
zfsのブロックサイズは512Bから128KBで可変。
ざっくり64KBとみなす。
では計算。
2TB=1024 * 1024 * 1024 * 2 = 2147,483,648KB。
2TB/64KB=33,554,432 blocks
2TBは33,554,432 blocks。
1blockあたり320Bytesなので、かければテーブルに必要なサイズが出る。
33,554,432 blocks * 320 Bytes = 10,737,418,240 = 10GBytes
はい解散。
と言いたくなるレベルですな。
念のため記載するが、上記は2TBのデータを使っているときのdedupテーブルの試算。
2TBのプールに100bytes程度のファイル一つ置いただけなら、ハッシュテーブルは320Bytes程度。
Dedupの活きる道
そもそも2TB全部にDedupするのが間違いであった。
Dedupを活かしたいなら、扱うファイルで決めるのも手。
ざっくり言えばオフィスドキュメント、仮想マシンイメージなど、重複が見込まれるファイルを多く保管するディレクトリに対してのみDedupするとよいでしょう。
一方で動画などはあまり有効ではないでしょう。
なお、プールでDedupするとどれくらい得か、というのは調べることができる。
zdbにプール名を与えてやればいい。
一番下に重複具合が表示される。以下の例では1.06。あまり意味はないってことですな。
ちなみに、あるプールに同一のファイルを3つだけ置くとここが3.00になる。
$ sudo zdb -S vault パスワード: Simulated DDT histogram: bucket allocated referenced ______ ______________________________ ______________________________ refcnt blocks LSIZE PSIZE DSIZE blocks LSIZE PSIZE DSIZE ------ ------ ----- ----- ----- ------ ----- ----- ----- 1 8.22M 1.02T 1.02T 1.02T 8.22M 1.02T 1.02T 1.02T 2 406K 50.6G 50.6G 50.6G 815K 102G 102G 102G 4 185 17.1M 17.1M 17.1M 835 73.6M 73.6M 73.6M 8 146 14.2M 14.2M 14.2M 1.75K 182M 182M 182M 16 17 8.50K 8.50K 8.50K 407 204K 204K 204K 32 150 16.7M 16.7M 16.7M 5.43K 600M 600M 600M 64 9 132K 132K 132K 820 9.49M 9.49M 9.49M 128 6 3K 3K 3K 1.02K 521K 521K 521K 256 3 129K 129K 129K 884 40.5M 40.5M 40.5M 64K 1 128K 128K 128K 73.4K 9.18G 9.18G 9.18G Total 8.62M 1.07T 1.07T 1.07T 9.10M 1.13T 1.13T 1.13T dedup = 1.06, compress = 1.00, copies = 1.00, dedup * compress / copies = 1.0
DedupのONのしかた
まあzfs set dedup=ONとかすればいいんだけど、現状使う予定もないので詳しく調べてない。
trは一文字ごとに判断する件について
$ cat sample.txt <a><b>
上記のテキストに対して以下のtrを実行するとどうなるか。
tr "ab" "cd"
試してみる。
$ tr "ab" "cd" < ./sample.txt <c><d>
げえっ。
つまり、trは1文字ずつ判断する。
a→cに変わり、
b→dに変わる。
※「ab」を置換しない点に注意。
応用。
同じファイルに対して。
$ tr -d "<>" < sample.txt ab
「<>」ではなく「<」「>」を消去していることに注意。
/var/logの下がえらいことになっていたでござる。(あるいはFreeBSDでログのローテーション設定をするには(logrotateではなくnewsyslog))。
ある日、ふと/var/logの下を見てみたら、1.5GBytesに膨れ上がった某ログファイルがあって腰を抜かした件について。
思えば、サーバソフトウェアなどでは、インストールしたらまずそのものの設定で頭が一杯だ。
一方で、いわゆるシモの世話といいますか、吐き出すログの設定には頭が回ってなかったことに深く反省するのであります。
俺の例でいえば、apache、clamav、dhcpdのログが手つかずでありました(冒頭、1.5GBytesになっていたログはdhcpdのもの)。
portsから入れたサーバのログは、いちど確認したほうがいいだろう。
基本は/var/logの下に出力されるが、/usr/local/var/logが(あれば)見た方がいいし、場合によっては思わぬところに吐き出されてる可能性もある。
newsyslogd
さて、FreeBSDではログのローテートはnewsyslogdが行う。Linuxではlogrotateにあたるもの。
handbookではこのへん
英語(推奨)
http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/configtuning-configfiles.html
日本語
http://www.freebsd.org/doc/ja_JP.eucJP/books/handbook/book.html#CONFIGTUNING-CONFIGFILES
newsyslogの設定サンプル
man newsyslog.confを見ればだいたい分かる。以降、英文はここからの引用。
http://www.freebsd.org/cgi/man.cgi?query=newsyslog.conf&apropos=0&sektion=0&manpath=FreeBSD+9.0-RELEASE&arch=default&format=html
以下の順番で並べるだけ。間はスペースで埋めること(separated with whitespace)。
# filename [owner:group] mode count size when [ZB] [/pid_file] [sig_num]
以下、サンプル。
/var/log/local7.log 600 10 1024 * JC
/var/log/local7.logが、1MBytesを超えた時点でローテーション。
生成されたログのパーミッションは600で、bzip2で圧縮され(J)、10個保存される。
/var/log/httpd-access.log 644 7 * @T03 JC
apacheのログを毎日午前3時にローテーション、圧縮して7日分残す。
設定を変えたらnewsyslogdを再起動。
# /etc/rc.d/newsyslog restart Creating and/or trimming log files. #
設定について
filename
その名の通り。
[owner:group]
省略可。アーカイブ後ファイルの所有ユーザとグループ
mode
ログファイルとアーカイブ後ファイルのパーミッション。
サーバソフトが作るオリジナルのパーミッションと合わせておくのがよい。
というのも、newsyslogdがログをローテーションするときに新しいログファイルを作るから。
owner:groupにはなく、こちらにだけ「ログファイル」という記載があるのはなぜでしょうな。
count
残す「アーカイブ後の」ログファイル数。
3なら、アーカイブされたログが3つになる。
size
このサイズを超えたときにローテーションされる。
キロバイトで指定。
アスタリスク(*)の場合には、サイズベースでのローテーションはしない。
when
ローテーションする時間、時刻契機を指定。
インターバル、時刻を指定できる。
書式は二つ。後述する。
注意すべき点は、newsyslog自体が一時間に一回しか起動しないこと。
これはつまり以下のような動作となる、と理解した。
・仮に、newsyslogdが毎時0分に起動し、かつ
・毎時1分にローテーションする設定にした場合、
→例えば、1時1分ではなく、2時にローテーションが発生する。
newsyslog.conf(5)より抜粋
If a time is specified, the log file will only be trimmed if newsyslog(8) is run within one hour of the specified time. If an interval is specified, the log file will be trimmed if that many hours have passed since the last rotation.
書式
@で書くもの、$で書くものの二つ。
@は、[[[[[cc]yy]mm]dd][T[hh[mm[ss]]]]]
$は、[Dhh], [Ww[Dhh]]と[Mdd[Dhh]]
サンプルを見るのが一番よい。(これもmanから抜粋)$D0 毎日午前0時。@T00と同じ意味
$D23 毎日23時。@T23と同じ意味
$W0D23 毎週日曜23時
$W5D16 毎週金曜16時
$M1D0 毎月1日の午前0時。@01T00と同じ意味
$M5D6 毎月5日の午前6時。@05T06と同じ意味
flags 一部のみ。基本JCでよい。
J ログをbzip2で圧縮。Zならgzip。Xならxz。
C ログが存在しない場合に作る。
G パターンにマッチしたログファイルを対象にできる。
pid_file
通常、ログをローテーションした後はsyslogdにシグナルが送られる。
syslogd以外のプロセスにシグナルを送りたい場合には、プロセスの
pidが書かれたファイルをここで指定する。
以上