Shell のコマンド実行回数を数える

Posted by yoosee on Debian at 2008-04-19 22:00 JST

*1  Shell History | Weboo! Returns.

このネタは定期的に出てくるけど、自分では書いたことが無かった気がするので試しに。awk の切り出しは extended history で保存している都合で、切り出しカラムを $2 から $4 に変えている。

直近1000回。
% history-all|tail -1000|awk '{a[$4]++ } END{for(i in a){print a[i] " " i}}' |sort -rn|head
95 lv
59 ls
51 edic
50 ruby
48 cd
43 rm
40 mv
38 sudo
33 jdic
32 w3m
edic, jdic はそれぞれ dic コマンドを 英和・和英 で起動するための alias。

普段使っているzshでは 横着プログラミング 第3回: 履歴マニア にあるように過去の履歴をひたすら蓄積しているので、その約2万回分でカウント。
% history-all|awk '{a[$4]++ } END{for(i in a){print a[i] " " i}}' |sort -rn|head
1431 lv
1212 google
1062 sudo
960 ls
860 edic
694 w3m
688 cd
657 rm
614 mv
569 grep
なんだかやけに sudo が多いような…。

ちなみに google と言うのはコマンドラインから w3m に google 検索パラメータを投げるだけのプログラム。
#!/usr/bin/perl

my $arg = join("+", @ARGV);
my $q=`echo $arg | nkf -w`;
system("w3m \"http://www.google.com/search?lr=lang_ja&q=$q\"");
コンソール上で生活していると、これが意外と便利。

*1  RecordMyDesktop で X 上の操作を録画

X 上で動作するアプリケーションのデモを PowerPoint に張り付けてやりたいと思い、ちょっと探したら RecordMyDesktop と言うツールが見つかった。録画形式は Ogg Theora 。PyGTK が入っていればGUIで録画設定できるが、手元では都合でコマンドラインで実行した。と言っても例えば単一ウィンドウの動作を録画するには xwininfo から Window id を抜きだし (例えば 0x2e0005 として)、コマンドラインで指定するだけ。
 % recordmydesktop -windowid 0x2e0005 -fps 30 -v_bitrate 50000 -o out.ogg
コマンド実行で録画を開始し、Control-C で中断するとエンコードする。Ogg Theora 形式では素の Windows 上で再生出来ないので ffmpeg で変換。
 % ffmpeg -an -vcodec mpeg1video -i out.ogg out.mpg
今回は音声はoffにした。

あとは Windows に持っていってパワーポイントのメニューから挿入 » ビデオとサウンド » ファイルからサウンドを選び、ファイルを指定すればいい。
ただこのやり方だと .ppt ファイルに埋め込まれるのは絶対パスのリンクだけらしく、動画ファイルを削除したりパスを変更すると再生出来なくなるので注意が必要。せめて相対パスで登録できればいいんだが、今のところやり方を見つけられてない。

ともあれデモなんかは現地で操作するより録画しておいた方が色々と安心だし、動作にあわせた解説も練習や録音が出来て楽。ちなみに Windows 上で似たようなことをするならばWink, CamStudio, Jing など色々あるらしい。

*1  SMTPレベルでのspam送信機能改善

数年前から MTA レベルの spam フィルタ技術として tarpitting + greylist 等を適用しているが、最近どうも効きが悪い感じがしたので、すり抜けてくる spam について少し調査をしてみた。結論としては spam 送信ソフトの実装レベルがかなり上がってきた事が伺える。
SMTP的な挙動が正常なMTAと区別が付かないspammerの増加
Greylist (わざと再送要求する) や Tarpit (応答コード送信を遅延させる) といった手法に普通の MTA と同じようにきちんと対応してくる spammer が増えてきている。元々 spam 送信者のソフトウェアが真面目に実装されていない事を利用した手法なので、真面目に実装した方が spam 送信率が高くなると認識された時点で対応されるのはある意味当然ではあるのだが、思ったより早く対応が進んでいる。
その他でも、HELO/EHLO できちんと FQDN を送信してきたり、セカンダリMXを参照して再送をかけてきたりと、全般的にSMTP的な振る舞いは正しいMTAと区別できないレベルのものが確実に増えてきている。特に英語spamに顕著。
ISPの真っ当なメールサーバを中継してくるspammerの増加
正当なISPのメールサーバから正当なFromで送りつけてくる spammer が最近は多少目立つようになってきた。ほぼ同じ内容のspamが複数の送信者・ISP経由から来ているのを見るに、恐らくはウィルス感染PCのbotnetから広く浅く送ってきているのだろう。これをやられるともうSMTPレベルではフィルタのしようがなく、本文の文章解析に頼るしかない。

*2  From / To / Subject / Body の工夫

SMTPレベル以外でも、From / To や Subject, 本文自体にも色々と工夫が見られる。
From が自分自身 (To と同一) であったりランダムであったりする
SpamAssassin では blacklist_from と言う From 固定フィルタがあるが、これが使えなくなる。From が自分自身と言うケースに付いては SPF のような送信サーバ認証を使う手はあり、SpamAssassin 等でも whitelist_from_spf と言った SPF 認証された From のみを Whitelist として扱う設定がある。
個人的な問題は私の主メールアドレスのドメインを登録している NSI が未だに TXT レコードの編集に対応していないという所だが、SPF 対応サーバ自体は去年のドコモの PSF フィルタ開始から増加している
Subject や本文にスペルミスを入れてくる
英語spamでの話になるが、固定文字列フィルタをすり抜けるためにわざとキーワードをスペルミスしてくる。よくあるのは Viagra を Viagara や Viarga と言ったようなもの。

今のところはまだこうしたインテリジェントなspammerは大多数ではないため、既存の手法もそれなりの割合では効いているが、出来のいいツールが出回るようになると現行の手法では対処が難しくなるだろう。まめにメンテナンスされた DNSRBLs 、ドメイン認証、フロー制御、あとはコンテンツレベルでのより賢いフィルタリング等の重要性が増していくだろうが、より CPU リソースを消費する方向に進んでいると言うのはかなり憂鬱な話ではある。

どちらにせよ大量のサンプルと申告者を持っているサービスは有利になるので、個人レベルならば例えば「Gmailへフォワード→POP3で取得」などという方法を使うのも手かもしれない。

*1  日本語ファイル名をローマ字に変換する ruby + kakasi script

Palm TX で使っている pTunes が例によってSDカード上の日本語ファイルを扱ってくれない(id3tagは大丈夫だがファイルリストに表示されない)ので、ディレクトリ名・ファイル名をローマ字に変換するスクリプトを書いた。引数にディレクトリを指定すると recursive に日本語ファイル名をローマ字に変換する。処理には libkakasi を使用して、前段では -w での分かち処理もしている。また空白はアンダーラインに変換。割と破壊的なので利用には注意を。
#!/usr/bin/ruby

require 'kakasi'
require 'find'
require 'nkf'

def romanize_dir dir
  Find.find(dir) do |fpath|
    next if NKF.guess(fpath) == 5 && !/\s+/ =~ fpath # ascii or whitespace
    begin
      filename = Kakasi.kakasi('-w', NKF.nkf('-e',fpath)).gsub(/\s*\/\s*/, '/')
      filename_roman = Kakasi.kakasi('-Ha -Ka -Ja -Ea -ka', filename)
      filename_roman.gsub!(/\s+/, '_').gsub!(/\^/,'-')
    rescue
      puts "failed to convert string #{fpath} - #{$!}:#{$@}"
      next
    end

    begin
      File.rename(fpath, filename_roman)
      puts fpath + " to " + filename_roman
    rescue
      puts "failed to convert filename #{fpath} - #{$!}:#{$@}"
    end
    if(File.directory? filename_roman)
      puts " + into directory #{filename_roman}"
      romanize_dir filename_roman
    end
  end
end

dir = ARGV.shift
romanize_dir dir
Windows だと同様の用途には Flexible RenamerGanmigi と言ったものがあるみたい。試してはいない。

*1  Re: IMAP filtering, how to mark my own messages read

メールを procmail で imap 用 Maildir フォルダに振り分ける際、一部メールに関しては最初から既読に出来ないものかと調べてみたら、Re: IMAP filtering, how to mark my own messages read と言う方法が見つかった。
Maildir ではファイル名で未読・既読状態等を管理しており、基本的には cur/ ディレクトリに :2,S と言う名前で終わっていれば既読とみなされる。そこで
:0
* conditions
{
  foldername=whatever

  :0c
  .$foldername/ # stores in .$foldername/new/

  :0
  * LASTFOLDER ?? /\/[^/]+$
  { tail=$MATCH }

  TRAP="mv $LASTFOLDER .$foldername/cur/$tail:2,S"

  HOST
}
のようなルールで、特定 conditions の場合に mv コマンドでファイル名を強制的に書き換えてしまう TRAP (procmail 実行終了時に実行される処理) を仕込む。直接 new/ から cur/ に mv をかけるあたりも Maildir の思想を完全に否定しているし、結構乱暴な方法ではあるけど、普通に使う分にはこれで問題になることはあまり無さそうなので、まぁ用には足るんじゃなかろうか。
procmail 以外の振り分けソフトならもっとスマートな方法があるだろうか?

fml → mailman 移行メモ

Posted by yoosee on Debian at 2008-01-10 21:00 JST

*1  fml → mailman 移行メモ

メモ書き。mailman で予め listname でメーリングリストを作成し、必要な設定をしておく。メンバーの移行は普通に fml の /var/spool/ml/listname/members などから Webインターフェイス経由で登録。

アーカイブの移行は fml 付随の packmbox.pl を使い
# cd /var/spool/ml/listname/spool/
# perl /.../packmbox.pl > /tmp/listname.mbox
# mv /tmp/listname.box /var/lib/mailman/archives/private/listname.mbox/
# cd /var/lib/mailman/archives/private/listname.mbox/
# /usr/lib/mailman/bin/arch listname listname.mbox
だーっと過去メールが流れて html の index が作成される。閲覧権限には要注意。

mailman 1:2.1.9-9 では fml 風の [listname:01234] 的な通番付き Subject を作ることが標準で出来る。fml で使っていた通番をそのまま引き継ぐにはホームサーバー非定期日記(風) を参考に
# /var/lib/mailman/bin/withlist listname
listname のリストを読み込中 (ロック解除)
変数 `m' が mlname の MailList インスタンスです
>>> m.Lock()
>>> m.post_id = (/var/spool/ml/listname/seq より1多い数字)
>>> m.Save()
>>> m.Unlock()
>>> ^D
最終処理中 
とする。

*1  Debian lenny での postfix + mailman install 備忘録 (専用サブドメイン利用型)

ここでは 素のドメイン名 (listname@example.com) ではなく、mailman 専用サブドメイン (@lists.example.com) を利用する。全ての専用サブドメイン宛メールは mailman が処理するものとして扱われる。サブドメインを使わず aliases を用いる方法は GNU Mailman インストールマニュアル 等を参照の事。

導入は例によって aptitude 一発で完了。
 # aptitude install mailman
...
 # dpkg -l mailman
ii  mailman        1:2.1.9-9      Powerful, web-based mailing list manager
導入時に利用する言語を聞かれるので、en と ja を選択し ja をデフォルトにしておく。ja で利用すると cli の日本語が euc-jp で出力されてしまい、utf-8 等の terminal 環境では文字化けするのが難だが、それ以外は特に問題ないようだ。

*2  Postfix の設定

設定は /usr/share/doc/mailman/README.Debian にある通り、/etc/mailman/postfix-to-mailman.py の記述に従う。

/etc/postfix/main.cf
    relay_domains = ... lists.example.com
    transport_maps = hash:/etc/postfix/transport
    mailman_destination_recipient_limit = 1
/etc/postfix/transport
lists.example.com   mailman:
これで @lists.example.com 宛のメールは全て postfix の mailman service に渡される。mailman service は master.cf で定義される。lenny では external service として標準で入っていた。

/etc/postfix/master.cf
mailman   unix  -       n       n       -       -       pipe
  flags=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py
  ${nexthop} ${user}
/etc/mailman/mm_cfg.py は以下のようにする。
MTA = None # No MTA alias processing required
# alias for postmaster, abuse and mailer-daemon
DEB_LISTMASTER = 'postmaster@example.com'
MTA = Postfix での alias 共有は利用しないので注意。

*3  Webインターフェイスの設定

apache では特定の VirtualHost でのみ mailman interface を表示させたいので、sites-available/lists.example.com に以下の行を入れる。
Include /etc/mailman/apache.conf
URL から /cgi-bin/ を省略したい場合は /etc/mailman/mm_cfg.py を以下のように設定しておく。
DEFAULT_URL_PATTERN = 'http://%s/mailman/'
併せて /etc/mailman/apache.conf も編集
ScriptAlias /mailman/ /usr/lib/cgi-bin/mailman/
この設定をする前にメーリングリストを作成した場合は、メーリングリスト個別の設定の方も変更する必要があるようだ。

*4  短いドメインパート形式への対応

ちなみにこうした @lists... を使う設定の上で listname@example.com のように lists. を省いたメールアドレス形式を使いたい場合、当該 listname のメールアドレスやそれに付随する listname-action@ コマンドメール類を @lists. へ流し込む virtual map / regexp virtual map を書く必要がある。後者には postfix-pcre が必要。

/etc/postfix/virtual
listname@example.com  listname@lists.example.com
/etc/postfix/virtual_regexp
/^(.+)-(unsubscribe|off|leave)@example\.com$/ $1-$2@lists.example.com
/^(.+)-(post|admin|request|owner|join|leave|confirm)@example\.com$/ $1-$2@lists.example.com
メールアドレスを regexp match させての処理は色々と危険なので、動作を理解していない場合はやらない方がいいだろうし、新しい list を作る度に virtual の方は編集が必要だし、こんなケレン味のある方法より素直に aliases/virtual を使った方がいい気もするが、まぁ移行上の都合と趣味の問題ということで。

*1  Debian の PermitRootLogin が yes なのは意図的らしい

Debian lenny の openssh-server で、/etc/ssh/sshd_config の default では PermitRootLogin yes になっていた。今時 ssh での root login が有効になっているのはどうかと思ったんだが、/usr/share/doc/ssh-client/README.Debian には
この設定は upstream の default に従っている。(中略) root での ssh login を禁止しても su で root になれるアカウントがある限り、攻撃者は簡単にそこから root 権を奪取できるんだから安全性は向上しないよ。
これはバグじゃないからデフォルト設定が間違ってるなんていうバグレポートを送ってくるなよ! (超訳)
とある。言われてみればその通りではあるんだが、まぁ知られたユーザ名 (root) で brute force attack を喰らっても嬉しくないので私は no にしておく。

*1  リモートサーバに ssh pubkey を登録するワンライナー

そういうものが欲しくてちょっと試した。
 % cat ~/.ssh/id_dsa.pub | ssh remotehost "xargs echo >> .ssh/authorized_keys"
で一応うまくはいった。もちろんこの時点では remotehost 側が PasswordAuthentication yes になっている必要はある。xargs を使うのが美しくない気がするが、他にいい手はあるだろうか。

メールサーバの再移行

Posted by yoosee on Debian at 2008-01-08 10:00 JST

*1  メールサーバの再移行

先月前半にトラブルがあった際にメールサーバだけ一時的に他所に移していたが、ハードウェアを更新した後は特に問題なく稼働しているので、新サーバに再移行した。今回のサーバ移行手順は以下の通り。
  1. 旧サーバの設定・メール・HOMEを新サーバに移行
  2. 新サーバで一通りの MTA 設定等を完了して稼働開始
  3. 現サーバの MTA を停止 (セカンダリMXサーバはそのまま稼働)
  4. 現サーバの Maildir 内メールを新サーバにrsync
  5. DNS で Primary MX の Aレコード向け先を現サーバから新サーバに切り替え
  6. 外部 MTA 及びセカンダリMXから新サーバに向けてメールが流れ出すのを確認
作業は昨晩 0時には完了。spamd が動いてなかったり、 courier-imap/pop3d & cyrus-saslauthd を dovecot に移行統合したりした都合で幾つか小さな問題はあったが、特に大きな問題なく移行できたと思う。特に設定に変更は無いはずだが、パスワードが旧サーバのものに戻っているので注意されたし。利用者・メール送信者で不具合がある人はご連絡ください。なおメーリングリストは fml から mailman に移行した上で近日中に動かします。

*1  Debian lenny/sid での utf-8 環境移行メモ

サーバを入れ替えたタイミングで、なんとなしに terminal 環境を今までの euc-jp 中心から utf-8 に切り替えたのだが、結構あちこち変更するハメになったので、まだ完璧ではないが設定を記録しておく。文字コードの問題はまだしも、East Asian ambiguous char width 周りの問題が鬱陶しい上にスマートで包括的な解決方法が無い。最新の環境にしたのに Bad Knowhow が増えるというのは困ったもんだ。

locale: /etc/locale.gen に以下の行が無い場合は追加して locale-gen を実行
ja_JP.UTF-8 UTF-8
zsh: .zshrc
export LANG=ja_JP.UTF-8
export OUTPUT_CHARSET=utf-8
export LV="-Ou8"
screen: .screenrc
defencoding     UTF-8
vim: .vimrc
set termencoding=utf-8
set fileencodings=iso-2022-jp,cp932,utf-8,japan
set ambiwidth=double
emacs21 では mule-ucs パッケージを入れて un-define を require する。emacs22 では無くても utf-translate-cjk-mode があるので(CJKだけなら)一応使える。
emacs21/22: .emacs
(when (<= emacs-major-version 21)
   (require 'un-define))
(set-language-environment "Japanese")
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(set-buffer-file-coding-system 'utf-8)
(set-selection-coding-system 'utf-8)
(setq default-buffer-file-coding-system 'utf-8)
(prefer-coding-system 'utf-8)
これで概ね問題ないが、ambiguous char width を回避するために Emacs22 + UTF-8 における文脈依存な文字幅の問題について のような設定を入れておく。

w3m
特に設定しなくても LANG(LOCALE) に追従して「表示用文字コード」が Unicode (UTF-8) になってくれた。しかし画面表示とカーソル位置がずれていたり画面にゴミが残ったり(再描画すると直る)と、鬱陶しいことになっている。

Gnome, gnome-terminal
特に設定しなくても .xsession から X を LANG=ja_JP.UTF-8 で起動したら対応した。ただ困ったことに、gnome-terminal で utf8 の EastAsian Ambiguous char width 問題の解決策が見当たらない。VTE_CJK_WIDTH を設定する方法は etch では機能せず。仕方がないので xterm -cjk_width ないし mlterm -a 2 の方を使う方針にする。mlterm の方が antialias が綺麗なんだけど、URL link 等の右クリックメニュー機能が無くなったのがちょっと痛い。

PuTTY on Windows
設定から Window > Transrations を [UTF-8] に、Treat CJK ambiguous character as wide をチェック。PuTTY Tray を使っているけどこれで特に問題は無い。CJK以外の多国語を使う場合・terminal の文字コードが混在する場合には問題が出るのかもしれない。

参考

About W.W.Walker

World Wide Walker は yoosee による blog です。PDA, Web・サーバ技術, 美味しい食べ物などの話題を取り上げています... read more

Monthly Archives

Select Month to read
  

Ads

Recent Entries

Related Sites