pkgdb – Segmentation fault

portupgrade をやろうとしたら

# portversion -vl”<"
—> Checking the package registry database
[Updating the pkgdb <format:dbm_hash> in /var/db/pkg … ** Database file locked. Waiting.
** Stale lock file was found. Removed.
– 635 packages found (-2 +1) (…)/usr/local/lib/ruby/site_ruby/1.8/pkgdb.rb:431: [BUG] Segmentation fault
ruby 1.8.6 (2008-08-11) [i386-freebsd7]

といわれてしまったので

# mv /var/db/pkg/pkgdb.db /tmp/pkgdb.db.bak
# pkgdb -F

で pkgdb.db を再構築して対応した。

トラブルシューティング – portsdb.rb で cross-thread violation on rb_gc()

ある日 portversion と portupgrade で ports をアップデートしようとしたところ、portsdb.rb で次のようなエラーが出るようになり portupgrade 関係のプログラムがまったく動作しなくなってしまった。

/usr/local/lib/ruby/site_ruby/1.8/portsdb.rb:116:[BUG] cross-thread violation on rb_gc()
ruby 1.8.6 (2007-09-24) [i386-freebsd7]
 
SIGABRT (Abort trap: 6)

ちなみに環境は FreeBSD 7.0 + ruby_1.8.6_p111_2,1。
ports から ruby, portupgrade 入れなおしても
ソースを辿ったところ, libpthread が有効になっている時のみこのエラーが出るようになっているということが判明したため、

# cd /usr/ports/lang/ruby18
# make config

で LIB_PTHREAD を無効化した上で make install しなおしたところ無事解決しました。

パーティション暗号化(gbde, geli)

 
http://hsdiary.blogspot.com/2007/03/comparison-of-gbde-and-geli.html
 
FreeBSD では FreeBSD 5 から使える gbde (GEOM bde)と、FreeBSD 6 から追加された geli (GEOM eli) の二つの暗号化されたファイルシステムが提供されていますが、geli のほうが圧倒的にパフォーマンスが上らしい。
 
geli を利用できるようにするには、/boot/loader.conf に以下の行を追加するのが簡単です。

geom_eli_load=”YES” # gbde の場合は geom_bde_load=”YES”

一時的なものでいいのであればもちろん

root# kldload geom_eli

でロードできます。
 
参考:
geli(8)
mdconfig の使い方色々
GEOM_ELI を PGPDisk や TrueCrypt のように使う方法。

jail が起動できない

rc.conf に設定を追加して /etc/rc.d/jail restart したところ

jail: getpwnam: root: No such file or directory

と出て起動できなかった。
 
/etc/passwd などアカウント関係のファイルが欠落しているのが原因。
 

# cp /etc/master.passwd /etc/group /path/to/jail/etc/

と、まずどこかから設定をコピーをして必要なアカウントだけ取捨選択した上で

pwd_mkdb -p -d /path/to/jail/etc /path/to/jail/etc/master.passwd

を実行して jail の /etc/passwd を作成してやれば解決です。

pf でルーティング

FreeBSD で pf を使ってルータを作るメモ。
 
目的:
ネットワークインターフェイスが二つあり、それぞれのインターフェイスに外部ネットワーク、内部ネットワークとして割り当てるとする。
内部→外部の通信は IP マスカレード(NAPT)で透過的に通信できるようにし、外部→内部の通信は特定のポートのみ NAT でサーバにマッピングする。
 
適用例:
A. FreeBSD をルータとして動作させる。
B. (応用) jail を仮想プライベートネットワークに入れ、外への通信を制御する。
 


設定方法(A):
…外部ネットワークインターフェイスを fxp0, 内部ネットワークインターフェイスを fxp1 としてルータとして設定する場合
/etc/rc.conf:

defaultrouter=”192.168.1.1″ # 外部のデフォルトゲートウェイ
 
# 外部インターフェイス
ifconfig_fxp0=”inet 192.168.1.2 192.168.1.255 netmask 255.255.255.0″
# 内部インターフェイス
ifconfig_fxp1=”inet 10.0.0.1 10.0.0.255 netmask 255.255.255.0″
 
# pf を有効化
pf_enable=YES
pf_rules=”/etc/pf.conf”
pf_flags=””
pflog_enable=”YES”
pflog_logfile=”/var/log/pflog”
pflog_flags=””

/etc/pf.conf:

# 外部ネットワークインターフェイス
ext_if=”fxp0″
# 内部ネットワークインターフェイス
int_if=”fxp1″
####
 
table <private> const { 10.0.0/24 }
 
# IP マスカレード
nat on $ext_if inet from ($int_if) to ! <private> -> ($ext_if)
 
# NAT 設定。外からの http(80), https(443) は内部の 10.0.0.5 に、smtp(25) は内部の 10.0.0.6 に割り当て
rdr pass on $ext_if proto tcp from any to ($ext_if) port {80, 443} -> 10.0.0.5
rdr pass on $ext_if proto tcp from any to ($ext_if) port 25 -> 10.0.0.6
 
# パケットフィルタ: 説明を簡単にするため全許可に。
pass in quick all
pass out quick all

 


設定方法(B):
…外部ネットワークインターフェイスを fxp0, 内部ネットワークインターフェイスを lo1 (ループバック) として jail を内部ネットワークインターフェイスで管理する場合。
/etc/rc.conf:

defaultrouter=”192.168.1.1″ # 外部のデフォルトゲートウェイ
 
# 外部インターフェイス
ifconfig_fxp0=”inet 192.168.1.2 192.168.1.255 netmask 255.255.255.0″
# 内部インターフェイス
ifconfig_lo1=”inet 10.0.0.1 10.0.0.255 netmask 255.255.255.0″
ifconfig_lo1_alias=”inet 10.0.0.2″
ifconfig_lo1_alias=”inet 10.0.0.3″
ifconfig_lo1_alias=”inet 10.0.0.4″
ifconfig_lo1_alias=”inet 10.0.0.5″
ifconfig_lo1_alias=”inet 10.0.0.6″
# : 以下略
 
# pf を有効化
pf_enable=YES
pf_rules=”/etc/pf.conf”
pf_flags=””
pflog_enable=”YES”
pflog_logfile=”/var/log/pflog”
pflog_flags=””
 
####
### Jail の設定 ###
jail_enable=”YES”
jail_list=”j1 j2 j3″ # 立ち上げる jail の名前のリスト
jail_set_hostname_allow=”NO”
jail_sysvipc_allow=”YES”
## jail_list で設定した jail インスタンスそれぞれについて設定 ##
# j1:
jail_j1_rootdir=”/var/jail/j1″
jail_j1_hostname=”jail_1″
jail_j1_ip=”10.0.0.2″
jail_j1_exec_start=”/bin/sh /etc/rc”
jail_j1_exec_stop=”/bin/sh /bin/rc.shutdown”
jail_j1_devfs_enable=”YES”
jail_j1_fdescfs_enable=”NO”
jail_j1_procfs_enable=”YES”
jail_j1_mount_enable=”NO”
# j2, j3 も同様に。

/etc/pf.conf:

# 外部ネットワークインターフェイス
ext_if=”fxp0″
# 内部ネットワークインターフェイス
int_if=”lo1″
####
# 以下 設定方法 A とまったく同じ
table <private> const { 10.0.0/24 }
 
# IP マスカレード
nat on $ext_if inet from ($int_if) to ! <private> -> ($ext_if)
 
# NAT 設定。外からの http(80), https(443) は内部の 10.0.0.5 に、smtp(25) は内部の 10.0.0.6 に割り当て
rdr pass on $ext_if proto tcp from any to ($ext_if) port {80, 443} -> 10.0.0.5
rdr pass on $ext_if proto tcp from any to ($ext_if) port 25 -> 10.0.0.6
 
# パケットフィルタ: 説明を簡単にするため全許可に。
pass in quick all
pass out quick all

 


参考:
FreeBSDでPacketFilter(pf)を使う

FreeBSD 7.0-RELEASE

昨日 7.0 がとうとうリリースされたようです。
 
– SMP 環境でのパフォーマンス向上(ベンチマークや DB 処理について FreeBSD 6.X 系の 350% 〜 1500%, Linux 2.6.24 の 115% の性能)
– ULE スケジューラの大幅な改善(ただし7.0では 4BSD スケジューラがデフォルトで選択される。7.1 以降は ULE スケジューラがデフォルトになる予定)
– ファイルシステム Sun ZFS の試験的サポート。
– ジャーナルファイルシステムのセットアップに gjournal が使えるようになり、仮想ストレージデバイスを扱うのに gvirstor が使えるようになった。
– ファイルシステム XFS で読み込みのみ(Read-only)モードをサポート。
– ファイルシステム unionfs をフィックス。
– iSCSI initiator
– いくつかのネットワークドライバで TSO, LRO をサポート
– SCTP(Stream Control Transmission Protocol)の試験的サポート
– ワイヤレス(802.11)サポートの多量な改善。
– OpenBSD のネットワークリンクアグリゲーション(lagg(4))を取り込んだ。
– メモリアロケータ(malloc(3))として新しく高性能な jemalloc を採用。
– freebsd-update(8) でセキュリティフィックス,不具合修正だけでなくリリースバージョンのアップグレードを正式にサポートするようになった。
– X.Org 7.3, KDE 3.5.8, GNOME 2.20.2 に対応
– GCC 4.2.1 に対応
– BIND 9.4.2 に対応
 
アナウンスに従い freebsd-update-upgrade.tgz を取得後

sh freebsd-update.sh -f freebsd-update.conf -r 7.0-RELEASE upgrade

としたら

Looking up update.FreeBSD.org mirrors… 1 mirrors found.
Fetching metadata signature for 6.3-STABLE from update1.FreeBSD.org… failed.
No mirrors remaining, giving up.

と怒られてしまった。
たしかに http://update1.freebsd.org/ には STABLE がない。
同じバージョンであれば(uname -r とか sysctl kern.version では) RELEASE = STABLE だったと思うので

$ cat freebsd-upgrade.sh.patch
534a535
> sed -E ‘s,-STABLE,-RELEASE,’ |

とパッチをあててやり、マニュアルどおり

$ uname -r
6.2-STABLE
$ su
# sh freebsd-update.sh -f freebsd-update.conf -r 7.0-RELEASE upgrade
# sh freebsd-update.sh -f freebsd-update.conf install
# shutdown -r now
(リブート後 root でログイン)
# portmanager -u -f
(ports リビルド)
(※他自分でビルドしていたものがあれば個別にリビルドする)
# sh freebsd-update.sh -f freebsd-update.conf install # もういちど。
# shutdown -r now
(リブート後 一般ユーザでログイン)
$ uname -r
7.0-RELEASE

と、これでいけました。
ただし、jail 環境がある場合、freebsd-update-upgrade スクリプトは jail 環境を考慮してないのか

# ./freebsd-update.sh -f freebsd-update.conf -r 7.0-RELEASE -b /path/to/jail upgrade
freebsd-update.sh: Cannot upgrade from 7.0-RELEASE to itself

と jail 環境を更新するときも uname -r を見てカーネルが既にアップグレード済みだから更新の必要がない、といわれてしまいました。
 
このため jail 環境を更新するのに結局 /usr/src からいつもの手順を踏んで更新しました。

# cat /etc/supfile
  
 *default host=cvsup1.jp.FreeBSD.org
 *default base=/usr
 *default prefix=/usr
 *default release=cvs tag=RELENG_7
 *default delete use-rel-suffix
 *default compress
 src-all
 
# csup /etc/supfile
# cd /usr/src
# make buildworld
# JAILDIR=/path/to/jail
# make installworld DESTDIR=$JAILDIR
# mergemaster -D $JAILDIR
 
# shutdown -r now

あとはホストと同様に portmanager -u -f で ports を更新します。

$ su
# mount_null /usr/ports /path/to/jail/usr/ports
# jls
   JID IP Address Hostname Path
     1 192.168.2.11 myjail /path/to/jail
# jexec 1 bash # jail に接続
# cd /usr/ports/ports-mgmt/portmanager/
# make install
# portmanager -u -y -f
# exit # jail から切断
# /etc/rc.d/jail restart

 
追記(2008-03-21):
portmanager では更新もれがある場合、Shared Library まわりで色々エラーが出ます。
たとえば、FreeBSD 6.2 のとき ports インストールした emacs を FreeBSD 7.0 にしてから実行しようとすると libz.so.3 がないと怒られる。あるいは新しく ports からプログラムをインストールしようとしたら lib*.so.* という共有ライブラリがないためにコンパイル中に色々エラーがでてインストールできなかった。というような現象です。
 
この場合の対策は

portupgrade -rf “問題のあるport”

でリビルドしてみる。それでだめなら

pkg_deinstall -r “パッケージ名”

でいったん該当のパッケージと依存パッケージを削除して

portinstall -r “パッケージ名”

で削除したものを再び入れなおすと解決します。

/tmp を自動で削除するには

FreeBSD は標準では /tmp の中身は削除されないようになっていますが、FreeBSD には削除処理を自動で行ってくれる二つの手段が提供されています。
 


– 起動時に中身をクリアする
 
/etc/rc.conf に以下の設定を追加すると FreeBSD の起動時に /tmp の中身を削除するようになります。

clear_tmp_enable=”YES” # Clear /tmp at startup

 
この機能は /etc/rc.d/tmp で実装されており、/etc/rc.d/rc.conf にデフォルト設定があります。

clear_tmp_enable=”NO” # 起動時に /tmp をクリアする
clear_tmp_X=”YES” # /tmp 内の X11 関連のディレクトリをクリアして再構築する


– 定期的に古いファイルを削除する
/etc/periodic.conf に以下の行を設定することで /tmp の中身のうち一定期間アクセスがないファイルを削除するようになります。

daily_clean_tmps_enable=”YES”

 
rc.conf の clear_tmp_enable を YES にすると起動時に /etc/rc.d/tmp が実行されて /tmp のすべてのファイルを削除します。
 
この機能は /etc/periodic/daily/110.clean-tmps で実装されており、/etc/default/periodic.conf にデフォルトの設定があります。

daily_clean_tmps_enable=”NO” # 不要ファイルを毎日削除する
daily_clean_tmps_dirs=”/tmp” # このディレクトリ以下を削除する
daily_clean_tmps_days=”3″ # 指定期間アクセスがないもののみ対象
daily_clean_tmps_ignore=”.X*-lock quota.user quota.group” # 削除対象外のファイル
daily_clean_tmps_ignore=”$daily_clean_tmps_ignore quota.user quota.group”
 
daily_clean_tmps_verbose=”YES” # 削除したファイル名を出力する

FreeBSD6 + jail + httpd22 + fcgid/fastcgi + Ruby on Rails

久しぶりにものすごくはまったのでメモ。
 
目的:
FreeBSD jail 上の httpd + suexec 環境に ruby on rails を入れたが、
CGI で動かすと遅いので fcgi 対応にしたい。
 
手順:
– jail host の /etc/rc.conf に以下の記述を追加

sysvipc_enable=”YES”
jail_sysvipc_allow=”YES” # jail 環境で httpd を動かしている場合のみ追加

fastcgi を追加(ruby_fcgi 用)

$ wget http://www.fastcgi.com/dist/fcgi-2.4.1-SNAP-0311112127.tar.gz # http://www.fastcgi.com/dist/ の fastcgi の最新版
$ tar xvzf fcgi-2.4.1-SNAP-0311112127.tar.gz
$ cd fcgi-2.4.1-SNAP-0311112127
$ ./configure –prefix=/usr/local/fastcgi # /usr/local/fastcgi 以下に展開(*1)
$ sudo make install

ruby_fcgi を追加(gem install fcgi では each_cgi がないと怒られる場合があるため、ソースからビルド)

$ wget http://rubyforge.org/frs/download.php/11368/ruby-fcgi-0.8.7.tar.gz
$ tar xvzf ruby-fcgi-0.8.7.tar.gz
$ cd ruby-fcgi-0.8.7
$ ruby install.rb config — –with-fcgi-dir=/usr/local/fastcgi # (*1) で指定したフォルダ。(*1)で –prefix を指定しなかった場合、ここで config を実行しなくてよい。
$ sudo ruby install.rb

– mod_fcgid または mod_fastcgi をビルド/インストール
mod_fastcgi の場合:

$ wget http://www.fastcgi.com/dist/mod_fastcgi-2.4.6.tar.gz
$ tar xvzf mod_fastcgi-2.4.6.tar.gz
$ cd mod_fastcgi-2.4.6
$ cp Makefile.AP2 Makefile
$ make
$ sudo make install
$ # httpd2 が /usr/local/apache2 になければ Makefile を編集して top_dir を変更するか、次のようにする
$ sudo make top_dir=/opt/httpd/2.0.40
$ sudo make install top_dir=/opt/httpd/2.0.40

mod_fcgid の場合:

$ wget http://downloads.sourceforge.net/mod-fcgid/mod_fcgid.2.2.tgz?modtime=1185976592&big_mirror=0
$ tar xvzf mod_fcgid.2.2.tgz
$ cd mod_fcgid.2.2
$ make
$ sudo make install
$ # httpd2 が /usr/local/apache2 にない場合はmod_fastcgi の場合と同様の手法で top_dir 変数を変更する。

– mod_fcgid または mod_fastcgi を httpd にロード/設定
httpd.conf:

# mod_fastcgi を使う場合コメントアウト:
#LoadModule fastcgi_module modules/mod_fastcgi.so
<IfModule fastcgi_module>
   AddHandler fastcgi-script .fcgi
# ソケットの場所(省略時は httpd の log/fastcgi/ )
# FastCgiIpcDir /var/run/fastcgi
   FastCgiConfig -autoUpdate -idle-timeout 20 -killInterval 3600 -maxClassProcesses 2
   # suexec を使う場合必要
   FastCgiWrapper /usr/local/apache2/bin/suexec
</IfModule>
# mod_fcgid を使う場合コメントアウト:
#LoadModule fcgid_module modules/mod_fcgid.so
<IfModule fcgid_module>
   AddHandler fcgid-script .fcgi
   SocketPath /tmp/fcgidsock
   SharememPath /tmp/fcgidshm
   IPCCommTimeout 40
   IPCConnectTimeout 10
   # suexec を使う場合も使わない場合も FCGIWrapper は設定しなくてよい
</IfModule>
 
# suexec 例(SuexecUserGroup が肝):
<VirtualHost 192.168.10.123>
    ServerAdmin webmaster@example.com
    DocumentRoot /usr/local/apache2/htdocs/
    ServerName example.com
    SuexecUserGroup john web
</VirtualHost>

 
– rails の設定を変更
{rails_root}/public/.htaccess

– AddHandler fastcgi-script .fcgi
– RewriteRule ^(.*)$ dispatch.cgi [QSA,L]
+ RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]
– DefaultInitEnv RAILS_ENV development
+ SetEnv RAILS_ENV development

DefaultInitEnv とか SetEnv で変数がわたらない環境の場合は
{rails_root}/config/environment.rb の次の項目をコメントアウトして編集する

# Uncomment below to force Rails into production mode when
# you don’t control web/app server and can’t set it the proper way
#ENV[‘RAILS_ENV’] ||= ‘production’

 
– エラーが出る場合のヒント
http://ontherails.jp/2007/10/13/25 などを参考に。
ログファイルを見る:

httpd の error_log, suexec_log
rails の log/fastcgi.crash.log, log/development.log, log/production.log

など。
特に fastcgi/fcgid をかませた時のみ

Application error
Rails application failed to start properly

とページ表示される場合は rails の fastcgi のログを見るのが有効そうです。
 
参考:
configuration – The mod_fcgid Home Page
Apache2 + fcgid + Ruby on Railsメモ – sakuramateo
FreeBSD + Apache2 + mod_fcgid + Ruby On Rails(ふわふわな毎日)
_ fcgid(valda’s diary)
FastCGI 化(ふぇみにん日記)
Rails Apache + FastCGI 環境構築のはまりパターン
lighttpd + fcgi で each_cgi なるメソッドは知らないといわれる(Don’tStopMusic)

mdconfig の使い方色々(tmpfs, .iso のマウント, GEOM など)

md (/sbin/mdconfig) を使うと任意のファイルやメモリ領域をファイルシステム化することができます。
これを使うと、 Linux の tmpfs のようにメモリ領域にファイルを置いたり、CD イメージデータなどを仮想ファイルシステムとしてマウントすることができます。
 


■Linux の tmpfs (/dev/shm) のように使う
書式:

mdconfig -a -t swap -s <サイズ> [ -u <デバイス番号>] # swap 込みで確保(推奨)
mdconfig -a -t malloc -o reverse -s <サイズ> [ -u <デバイス番号>] # malloc (9)によるメモリ確保。大容量には向かない

 例:

$ su
# mdconfig -a -t swap -s 10m # あいているデバイス番号でメモリ 10MB を割り当て(0 〜 )
md0 # /dev/md0 が作成された
# newfs /dev/md0 # /dev/md0 に結びついた領域にファイルシステム作成
# mount /dev/md0 /mnt # アクセスできるようにマウント
# df -h | grep md0 # マウントできたか確認。
/dev/md0 9.4M 4.0K 8.7M 0% /mnt
# dd if=/dev/zero of=/mnt/foo.txt bs=1m count=5 # 適当にデータ書き込み
5+0 records in
5+0 records out
5242880 bytes transferred in 0.063932 secs (82007207 bytes/sec)
# dd if=/dev/zero of=/tmp/foo2.txt bs=1m count=5 # 比較用。/tmp より /mnt に書くほうが早くなっているはず
5+0 records in
5+0 records out
5242880 bytes transferred in 0.159325 secs (32906800 bytes/sec)
# ls -l /mnt
total 5138
drwxrwxr-x 2 root operator 512 2 4 17:15 .snap
-rw-r–r– 1 root wheel 5242880 2 4 17:18 foo.txt

 開放手順:

# umount /mnt # マウントポイントから切り離す
# mdconfig -d -u 0 # /dev/md0 をデタッチ


■任意のファイルをファイルシステムとして扱う
 (CD イメージ,ハードディスクイメージなどをマウントする)
 書式:

mdconfig -a -t vnode -f <ファイル名> [ -u <デバイス番号> ] # 指定したファイルをファイルシステムとして扱う

 例:

$ su
# ls /root/cd.iso # マウント対象の CD-ROM イメージ
cd.iso
# mdconfig -a -t vnode -f /root/cd.iso -u 1 # cd.iso を /dev/md1 に結びつける(今回は -u 1 で md1 を明示的に確保)
# mount -t cd9660 /dev/md1 /mnt # CD-ROM なので cd9660 をファイルシステムに指定してマウント。
# ls /mnt # CD-ROM の中身へのアクセス成功。
boot.cat f2.txt f6.txt initrd.gz splash.rle
boot.txt f3.txt f7.txt isolinux.bin
f1.txt f4.txt f8.txt isolinux.cfg
f10.txt f5.txt f9.txt linux

 開放手順: (前述の例と同じ)

# umount /mnt
# mdconfig -d -u 1 # /dev/md1 をデタッチ


■ zip 圧縮してサイズを節約する(geom_uzip: GEOM の利用例)
GEOM_UZIP を使うと、vnode 用イメージファイルをZIP圧縮してサイズを節約することができます。読み込み専用でしかマウントできないという欠点はありますが、CDイメージの保存やデータのバックアップなどの用途には有用です。
 例:

$ dd if=/dev/acd0 of=cdimg.iso bs=2352 # ファイルシステムのイメージデータ(なんでもよいがここでは CDドライブから吸出し(cd9660形式)) (1)
$ mkuzip -o cdimg.uzip cdimg.iso # 元のファイルシステムを geom_uzip で使える形式(*.uzip) に圧縮(2)
$ rm cdimg.iso # cdimg.iso はもう不要 (3)
$ su
# kldload geom_uzip # geom_uzip がカーネルに組み込み済みでなければここでロードする(4)
# mdconfig -a -t vnode -f cdimg.uzip # cdimg.uzip を vnode 形式で仮想ディスク化
md0
# ls /dev/md0* # geom_uzip が認識されていれば,geom_uzip 用イメージを mdconfig すると /dev/md*.uzip が同時に作成される
/dev/md0 /dev/md0.uzip /dev/mdctl
# mount -t cd9660 -r /dev/md0.uzip /mnt # /dev/md*.uzip を元のファイルシステム(この例ではcd9660)で read-only (-r)でマウントする。

 開放手順: (前述の例と同じ)

# umount /mnt
# mdconfig -d -u 1 # /dev/md1 をデタッチ

 
(1) 〜 (3) をまとめて次のように記述することもできます。

dd if=/dev/acd0 bs=2352 | mkuzip -o cdimg.uzip /dev/stdin

恒常的に geom_uzip を使う場合は、(4)のかわりに geom_uzip をカーネルバイナリに組み込むか /boot/loader.conf に次の一文を追加すると起動時に自動でロードされます。

geom_uzip_load=”YES”

 
(4)以降については *.uzip が代用される以外は前述の vnode の例と同じです。


■ geli を使った仮想ファイルシステムの暗号化:
mdconfig を geli(GEOM_ELI) や gdbm(GEOM_DBM) と組み合わせると、TrueCrypt や pgpdisk のように暗号化仮想ファイルシステムを構築することができます。今回は geli の例を紹介します。
 
geli を使うと既存のストレージがファイルシステムごと暗号化され、専用のラッパデバイス(/dev/*.eli) からしかアクセスできなくなります。/dev/*.eli をアタッチするには認証(パスフレーズ+鍵ファイル)が必要なため、必要な時のみアタッチ、マウントすることでデータの機密性を保つことができます。/dev/*.eli を使うユーザからは暗号化がされていない時と同様に利用できるため、大きな変更なしで簡単に利用できます。
 
 /boot/loader.conf:

geom_eli_load=”NO” # Disk encryption driver (see geli(8))

例:

# dd if=/dev/random of=/root/eli.key bs=64 count=1 # geli での認証用鍵ファイル(64byte)
# dd if=/dev/zero of=img.eli count=10 bs=1m # 仮想ファイルシステム用イメージファイル作成(ここでは 10MB=10*1m)。
# su
# mdconfig -at vnode -f img.eli
md0
# geli init -s 4096 -K /root/eli.key /dev/md0 # /dev/md0 を geli 用のファイルシステムとして初期化(暗号化)
Enter new passphrase:
Reenter new passphrase:
# geli attach -k /root/eli.key /dev/md0 # /dev/md0 に透過的にアクセスするためのデバイス取得(/dev/md0.eli が作成される)
Enter passphrase:
# newfs /dev/md0.eli # ファイルシステムは UFS 形式として初期化(暗号化された領域内)
/dev/md0.eli: 10.0MB (20472 sectors) block size 16384, fragment size 4096
        using 4 cylinder groups of 2.50MB, 160 blks, 192 inodes.
super-block backups (for fsck -b #) at:
 160, 5280, 10400, 15520
# mount /dev/md0.eli /mnt # あとは普通に(UFSとして)マウント。

 解放手順:

# umount /mnt # /dev/md0 のマウント先をアンマウント
# geli detach md0.eli # /dev/md0.eli を解除
# mdconfig -du 0 # /dev/md0 を解除

 
最初に作成した鍵ファイル(例では/root/eli.key) はフラッシュメモリなど暗号化デバイスとは別の場所に保存するのが望ましいです。
また、

geli init

の引数に -K <keyfile> を含めない場合はキーレス認証(パスフレーズのみ)での暗号化になり、 -P を追加するとパスフレーズレス認証(鍵ファイルのみ)での暗号化になります。
注意点として、geli init をするとデバイスに結びついたファイルシステムが初期化されることにも気をつけて下さい。詳細については geli(4) を参照のこと。
 


参考:
– mdconfig(8)
mdだって凄いんです。(404 Blog Not Found)
Linux で仮想 CD ドライブをマウントする(Hermit Complex 楽天支店)

# mount -t iso9660 -o loop /home/tagosuck/tagosucd.iso /mnt/tagosucd0

tips – ltrace で共有ライブラリの関数呼び出しをトレースする

http://0xcc.net/blog/archives/000103.html
より。

ltrace [ {オプション} ] {実行するプログラム} [ {引数..} ]

のようにすると、任意のプログラムを動的にブレークポイントを挿入して実行し、共有ライブラリとシステムコールの呼び出しをトレースすることができます。
簡単にいうと GDB より高級なデバッガのような感じです。
 
Linux の場合は標準でインストールされることが多そうですが、yum や apt-get を使う場合は

yum install ltrace

または

apt-get install ltrace

でインストールできます。
また FreeBSD の場合も ports に含まれているため、

portinstall sysutils/ltrace

とすることでインストールできます。
 
利用例:
ls / を実行しライブラリ関数をトレースし、log.txt にトレース結果を出力する(-o)。

$ ltrace -o log.txt ls / # プログラムの実行とトレース
bin dev home lib media mnt proc sbin tmp var
boot etc initrd lost+found misc opt root sys usr
$ cat log.txt # トレース結果参照
_start(0xbff1abd4, 0xbff1abd7, 0, 0xbff1abd9, 0xbff1abf0 <unfinished …>
__libc_start_main(0x804ea41, 2, 0xbfe34df4, 0x8056f58, 0x8056fac <unfinished …
setlocale(6, “”) = “en_US”
bindtextdomain(“coreutils”, “/usr/share/locale”) = “/usr/share/locale”
textdomain(“coreutils”) = “coreutils”
__cxa_atexit(0x8053701, 0, 0, 0x805b570, 0xbfe34d68) = 0
is_selinux_enabled(0x8053701, 0xd1bbe4, 0x32206e75, 0x34312036, 0x3a30333a) = 0
isatty(1) = 1
# 以下略

利用例2:
ライブラリのトレースだけでなくシステムコールもトレース(-S)し、
関数呼び出しの関係を階層構造で出力する(-n {number})。

$ ltrace -o log2.txt -S -n 2 ls /
# 略

$ cat log2.txt
SYS_uname(0xbfe4106c) = 0

SYS_brk(NULL) = 0x99ca000
SYS_access(0xbffdc1, 4, 0xc03fd4, 0xbffdc1, 4) = -2
SYS_open(“/etc/ld.so.cache”, 0, 00) = 3
# 中略
SYS_munmap(0xb7f92000, 4096) = 0
_start(0xbff20bd4, 0xbff20bd7, 0, 0xbff20bd9, 0xbff20bf0 <unfinished …>
    __libc_start_main(0x804ea41, 2, 0xbfe412c4, 0x8056f58, 0x8056fac <unfinished
 …>
        setlocale(6, “” <unfinished …>
            SYS_open(“/usr/lib/locale/locale-archive”, 32768, 01540) = 3
            SYS_fstat64(3, 0xd301a0, 0xd2eff4, 0xd301a0, 0xd0fc60) = 0
            SYS_mmap2(0, 0x200000, 1, 2, 3) = 0xb7d82000
            SYS_mmap2(0, 204800, 1, 2, 3) = 0xb7d50000
            SYS_mmap2(0, 4096, 1, 2, 3) = 0xb7d4f000
            SYS_close(3) = 0
        <... setlocale resumed> ) = “en_US”
# 以下略

利用例3: プログラムの経過時間を一緒に出力する(パフォーマンスチューニング用途など)

$ ltrace -tt -o log.txt ls / # マイクロ秒単位
19:56:53.267749 SYS_uname(0xbff417dc) = 0
19:56:53.267865 SYS_brk(NULL) = 0x9e12000
19:56:53.267917 SYS_access(0xbffdc1, 4, 0xc03fd4, 0xbffdc1, 4) = -2
# 以下略

-t にすると 19:56:53 のように秒単位、-tt にすると例のようにマイクロ秒単位、 -ttt にすると マイクロ秒単位で 1201517930.289331 のような UNIX タイムスタンプ形式になります。