Skip to main content

ログ取得ツール

Category: GNU/Linux

GNU tarでのインクリメンタルバックアップ

tarの–listed-incrementalオプション。これまで-Nを使ったり、findで新しいファイル名を探していたけど、tarの実行中はどうなるんだ、というのがあった。しょうがないので余裕を持たせて、

  1. LC_ALL=C date > timestamp.new
  2. tar cfz outXXXX.tar.gz -N "$(cat timestamp)"
  3. mv timestamp.new timestamp

のようにしていた。厳密じゃないけどなくなるよりはずいぶん良い。そう思っていたのだが、tarの–listed-incrementalというオプションはこれを厳密にやってくれるみたいだ。上記の3行は以下のように1コマンドになる。

  1. tar cfz outXXXX.tar.gz --listed-incremental out.stamp

short optionは-gです。 問題は、ディレクトリについてはやってくれないらしく、たとえ変更されていないディレクトリであってもアーカイブに入ってしまうことだ。であるからして、

  1. tar tfz outXXXX.tar.gz | grep -vq '/$' || rm outXXXX.tar.gz

みたいにディレクトリのみのアーカイブを削除することになる。これだと空ディレクトリを作ったという情報だけだと保存されなくなってしまうが。

mkdir, cd

bashやzshでユーザが定義した関数は状態が中に閉じていない。設定した環境変数やシェル変数は有効だしカレントディレクトリも移してしまえば戻った後も移ったままだ。つまり、「ディレクトリがなければ作ってcd」みたいなことも書けるわけだ。

cdm(){
  [ -d $1 ] || mkdir $1
  [ -d $1 ] && cd $1
}

これは果たして便利なのか否か。 (追記) 2004-04-28 15:35 cdmじゃなくてcddかccdあたりにしたほうが使いやすいことは確かだ。

Fatal error, run database recovery

rpmがいきなり以下のようなメッセージを出して落ちるようになった。

rpmdb: PANIC: 無効な引数です
rpmdb: fatal region error detected; run recovery
rpmdb: fatal region error detected; run recovery
rpmdb: fatal region error detected; run recovery
rpmdb: fatal region error detected; run recovery
rpmdb: fatal region error detected; run recovery
エラー: db4 error(-30982) from dbcursor->c_put: DB_RUNRECOVERY: Fatal error, run database recovery
rpmdb: fatal region error detected; run recovery
エラー: db4 error(-30982) from db->sync: DB_RUNRECOVERY: Fatal error, run database recovery
rpmdb: fatal region error detected; run recovery
エラー: db4 error(-30982) from dbcursor->c_close: DB_RUNRECOVERY: Fatal error, run database recovery
rpmdb: fatal region error detected; run recovery
  :

解決方法などわかろうはずもなく、rpmdb --rebuilddbとやってみたら直った。rpmdbが

int
DB_ENV->txn_recover(DB_ENV *dbenv, DB_PREPLIST preplist[],
    long count, long *retp, u_int32_t flags);

あたりを呼んでくれたのだろうか?

yum-arch

yumを普通に使う方法。

  • RPMをてきとうに持ってくる。
  • RPMが入ったディレクトリか、それよりも上位のディレクトリに対して、yum-arch dirnameを実行
  • headers/*.hdrやheaders/header.infoができる。
  • そのディレクトリをftpやhttp等で公開する。
  • クライアントでyum.confをいじってそのリポジトリを見にいくようにする。
  • あとはyum check-updateやyum updateをするだけ。

headerファイルがないとyumは使えないのだが、headerはyum-archというコマンドを使えばカンタンに作れる。 誰かがyum用のリポジトリを用意してくれないような場合でも、rsyncやらftpmirrorで自力でミラーを作って、yum-archでheaderファイルを生成すれば、yumで最新に保つことができるのであります。

記憶の片隅

Linux/IA32のmallocは一度に2GB弱まで。2GB「弱」というのは、2GBは取れないからだ。2GB制限の理由はずいぶん前にも見たことがあるこのへん(sse.co.jp)を参照のこと。これはファイルサイズの2GB制限と違って時代錯誤的なことではなく、現実に起きて納得の現象だ。そんな制限を承服するかどうかは考え方次第だ。 ではmallocではなくstaticな配列なら2GB以上取れるのか? 同じくらいのサイズまでしか取れないのです。

char mem[1024*1024*1024*2];
int main(int argc, char **argv){}

gcc曰く、「警告: 式の整数がオーバーフローしました」「配列 mem' の大きさが負です」…そうかintだから駄目なのか、と思ってunsignedにキャストすると正しい警告が出る。曰く、「配列 mem’ の大きさが大きすぎます」「`mem’ の領域サイズがわかりません」。 しかしgccが配列のサイズで文句を言うのは気に食わん! 1GBで配列を取ってコンパイルし、アセンブラコードを直して

        .comm   mem,1073741824,32
        .section        .note.GNU-stack,"",@progbits
                           ↓
        .comm   mem,1073741824*2,32
        .section        .note.GNU-stack,"",@progbits

これでコンパイル、リンクは成功する。で、できたバイナリを実行するとsegmentation fault。デバッガからも起動できない…そんなのはあたりまえだ(笑)。 じゃmmap(2)は? /dev/zeroへのmmap(2)を使えばメモリを確保できる。やはりこれも2GB制限があるのだ。MAP_FAILEDが返ってきて、Cannot allocate memoryと言われる。 スタックの場合は実はアセンブラコードを直すと2GBを越えられる。どっかでオーバーフローしてマイナスになっちゃってるのかもしれないし、たぶん動作はしないだろう。ただ、確保する(したつもり)だけでは落ちない。 …我ながら意味のないことばかりやってるな。

zshのバグ?

かなり前からそうで、マイナーバグだと思っていたのだが、今のバージョンでも起こるようだ。どこかに報告したほうがよいだろうか? zshで

 # cat =(df)

としてみてほしい。zshが戻ってこなくなる。ずっとRunning状態のまま。不思議なのは、cat =(df -T)だとOKだったりすることだ。 私はこの現象を説明できる気がしない。 zshを知らない人のためのメモ。=(cmd)というのはcmdの標準出力をテンポラリファイルに書き込んでファイル名を返します。なので、cat =(cmd)というのはcmdの標準出力をテンポラリファイルに書き込んで、catの引数にテンポラリファイルの名前を与えます。viとかは標準入力を編集できなかったりするし、複数のコマンドを書けるので、2つのコマンドの出力のdiffをとったりするときにものスゴく便利ですよ!! テンポラリファイルは当然のように勝手に消えます。偉い。 (追記) 2004-04-12 21:21 そうだ思い出した。=(cmd)を一番使うのはnetpbmを使うときだ。 pnmcat -lr =(jpegtopnm hoge1.jpg) =(jpegtopnm hoge2.jpg) =(pngtopnm hoge3.png)とかって。生活の知恵だ。良い子のみんなは覚えておこうね。 (追記) 2004-05-07 14:22 思いついてdfのaliasを解いてcat =(df)をやったらちゃんと戻ってきた。なんなんだろう。=(cmd)の中ではaliasが無限ループしてんのかな。私のdfはなんとなく以下のようにaliasしてある。

難しい…

mozex(mozdev.org)をインストールしてtextareaの編集にエディタを起動することができるようになったが、エディタは今までgeditを使っていた。本当はxemacsを使いたい。なんでこんなハメになっていたかというと、mozexはUTF-8のテキストファイルで受け渡しをするのだが、xemacsでUTF-8のファイルを編集する方法が難しかった。以前調べた限りでは

(load-library "un-define")
(set-buffer-file-coding-system-for-read 'utf-8)

で読み込みができ、バッファを読み込み後に(set-buffer-file-coding-system 'utf-8)を実行すると良い(以前の関数名とは微妙に変わっていた)。要はこれをやればいいのだが、mozexのコマンドラインのクオートも面倒だし、結局は

#! /bin/sh

to_utf8="(progn (load-library \"un-define\")
(set-buffer-file-coding-system-for-read 'utf-8)
(add-hook 'text-mode-hook (function (lambda() (set-buffer-file-coding-system 'utf-8)))))"

#if /sbin/pidof gnuserv > /dev/null; then
  #exec gnuclient -eval "$to_utf8" $*
#else
  exec xemacs -eval "$to_utf8" $*
#fi

のようなスクリプトにしている。gnuclientで起動したいところだが、別に開いているxemacsで勝手に(add-hook 'text-mode-hook)なんてやったら迷惑…だよね。閉じるときに(remove-hook 'text-mode-hook ....)が走るようにすればいいのかもしれないけど。 おかげで起動が遅いのなんのって(笑)。まあちょっと込み入った話はxemacsで書いたほうがskk-azikも使えるので効率が良い。まあ、skkinputをazik(vector.co.jp)に対応させるのが一番素直だとは思うんだけどね。

ELFにID3は入るか?

…と、今日の仕事中にふと思った。ELFにダミーのセグメントを作ってID3のデータ(別に曲名とかじゃなくていいけど)を入れて、言わば「インプラント」することは可能だと思われた。 でもこれって意味ないよね(笑)。やったとして、実行バイナリやライブラリをインデックス化して検索するとかってするのかな。だから、どうやったらいいのかは全く調べてない。

メモ:mplayer、ffmpeg

ウェブ上の映像の保存についてのメモ。

 # mplayer -vo mpegpes -ao mpegpes URL
 # ffmpeg -sameq -i grab.mpg output.mpg

で、たぶん特に情報をロスせずに保存できると思う。mplayerは画面に出力しなければコマ落ちさせることはないみたいだ。ffmpegは-sameqでソースと同じクオリティになるらしい。本当かな。MPEG-PESというのはビデオカードでMPEGのデコードをするときのためのデータフォーマットで、mplayerはビデオカードに書く代わりにファイルに書き出してくれるらしい。普通のMPEGプレイヤーはMPEG-PESを入力にはできないみたいだけど、mplayerとffmpegは理解できるみたいだ。ffmpegで普通のMPEGに変換&そこそこの圧縮ができる。もちろん-sameqなどつけなければもっと小さくなる。 で、wmaファイルをMP3ファイルに変換するのもmplayerでできる。

 # mplayer -ao pcm input.wma -aofile temp.wav
 # lame temp.wav output.mp3
 # rm temp.wav

mplayerはなんでフィルタにならないんだ。…別にいいけど。 (追記) 2004-04-06 22:31 フィルタか…名前つきFIFO(「名前つきパイプ」だっけ? どっちでもいいや)でできないかな。ディスク容量が足りないときとかに。

ねむい…

sleep(1)で待つときに、何も表示されないので自分まで眠くなってしまうことがある。じゃあ、しょうがない。これだ。完成度は低いが。

#! /bin/sh

SL=$1
TARGETDATE=$(expr $(date +%s) + $SL)
PRE=""
POST=" "

tmdiff(){
  NOW=$(date +%s)
  expr $1 - $NOW
}

while [ $(tmdiff $TARGETDATE) -gt 0 ] ; do
  echo -ne "\r"
  echo -n $PRE$(tmdiff $TARGETDATE)$POST
  sleep 1
done

echo -ne "\r${PRE}Go${POST}"