Personal tools
You are here: Home ブログ matsuyama Categories linux
Document Actions

linux

Up one level

Document Actions

History command in practice

ヒストリコマンドをマスターして心も体もDRYになろう。

一つ前のコマンドを実行

% echo a b c
a b c
% !!
echo a b c
a b c

n個前のコマンドを実行

% echo a b c
% touch me
% !-2
echo a b c
a b c

n番目のコマンドを実行

% history
1 echo a b c
2 touch me
% !1
echo a b c
a b c

コマンド履歴からコマンドを検索して実行

% echo a b c
a b c
% touch me
% !ech
echo a b c
a b c

コマンド履歴からインクリメンタルにコマンドを検索して補完

% echo a b c
% touch me
% [C-r]
ech
% echo a b c
a b c

一つ前のコマンドの最初の引数を取り出す

% echo a b c
a b c
% echo !^
echo a

n個前のコマンドの最初の引数を取り出す

% echo a b c
a b c
% touch me
% echo !-2:^
echo a
a

一つ前のコマンドの最後の引数を取り出す

% echo a b c
a b c
% echo !$
echo c
c

n個前のコマンドの最後の引数を取り出す

% echo a b c
a b c
% touch me
% echo !-2:$
echo c

一つ前のコマンドの全ての引数を取り出す

% echo a b c
a b c
% echo !*
echo a b c
a b c

一つ前のコマンドのnから最後までの引数を取り出す

% echo a b c
a b c
% echo !:2*
echo b c
b c

x個前のコマンドのnから最後までの引数を取り出す

% echo a b c
a b c
% touch me
% echo !-2:2*
echo b c
b c

一つ前のコマンドのnからmまでの引数を取り出す

% echo a b c d e f g
a b c d e f g
% echo !:2-4
echo b c d

x個前のコマンドのnからmまでの引数と取り出す

% echo a b c d e f g
a b c d e f g
% touch me
% echo !-2:2-4
echo b c d
b c d
% echo !-3:2-4
echo b c d

一つ前のコマンドのコマンド部を取り出す

% echo a b c
a b c
% echo !:0
echo echo
echo

n個前のコマンドのコマンド部を取り出す

% echo a b c
% touch me
% echo !-2:0
echo echo
echo

ちょっとtypoしたときにすばやく修正する

実際は普通に修正したほうが速いってのは秘密。

% echo xy
xy
% !:s/xy/yx
echo yx
yx

あるいはこちら。当方HHKB Proを使っておりハットが非常にうちづらいので滅多に使いません。

% echo xy
xy
% ^xy^yx
echo yx
yx

いちいちC-rするのは面倒だけど!xxxのxxxの部分がわからない

そんなときは!?xxx?を使います。

% echo very long command is here
very long command is here
% !?long?
echo very long command is here
very long command is here
% !?long #省略可能
echo very long command is here
very long command is here

履歴からrm -rf *とか実行されたら恐いです

素直に打ちなおすか、以下の方法を取るべきです。

% ls *
aaa bbb ccc
% rm -rf !$
rm -rf aaa bbb ccc

どうしても履歴から実行したい場合は以下のようにしましょう。

% !rm:p
rm -rf *
% #実際には実行されません

個人的にヒストリコマンドの文法が非常に覚えにくかったので、in practice形式で冗長に列挙してみました。これだけ読めばどのような文法か理解できるでしょう。ヒストリコマンドは非常に便利なので是非活用してみてください。

Category(s)
linux
The URL to Trackback this entry is:
http://dev.ariel-networks.com/Members/matsuyama/history-command-in-practice/tbping

Enjoy source code reading

Namazuをインストールしてから単なる全文検索エンジンであることに気づき、gonzuiをインストールして使いはじめようと思ったらNotImplementedErrorと怒られ、流行に弱い僕があえてetagsのような古いツールを使うわけもなく、結局GNUに帰してgtagsでソースコードを読むことになりました。

インストール

Gentooのパッケージ管理は結構ちゃんとしてるからうれしい。

emerge global

設定

できるだけかぶらないようなキーバインディングを考えて以下のように設定。

;; gtags mode
(autoload 'gtags-mode "gtags" "" t)
(setq gtags-mode-hook
  '(lambda ()
    (local-set-key "\C-xtt" 'gtags-find-tag)
    (lobal-set-key "\C-xtr" 'gtags-find-rtag)
    (local-set-key "\C-xts" 'gtags-find-symbol)
    (local-set-key "\C-xtg" 'gtags-pop-stack)
    ))

使う

まずはG*ファイルを生成しなければなりません。

% cd ~/src/gcc-4.1.1/gcc
% gtags -v
% #長い

emacsを開いてcdでG*があるディレクトリへ飛んでからM-x gtags-mode。たとえばここでC-x t t mainと打つとmainのある場所が新しいバッファに出力されます。

近いうちに本格的にソースを読んでいきます。

Category(s)
program
linux
The URL to Trackback this entry is:
http://dev.ariel-networks.com/Members/matsuyama/enjoy-source-code-reading/tbping

globalを実際につかってみた

バグ取りも噛ねて製品のソースコードの構造を理解せよとの命令が出たので、最近覚えたglobalを早速使ってみました。まずはG*ファイルを生成させるために、ソースコードディレクトリのルートで

% gtags -v

としてG*ファイルを生成させます。それで、例えばHogeクラスが定義されてるファイルってどこだろう、ということになれば

% global Hoge
path/to/Hoge

で一発で出ますし、それの中身を確認したいということになれば、Emacsからglobalを使うか、以下のようにコマンドします。

% global -x Hoge | less -T-

tでnext tag、Tでprevious tagです。:nと:pで操作するのではないので勘違いしないようにしてください。ただ、この方法だと定義周辺のコンテキストを確認できないようです。対策としては以下のようにファイル全体をlessする方法があります。

% global Hoge | xargs less

伝家の宝刀、xargsです。これはstdinを適当にsplitしてcommandに引き渡します。これによって、lessで:nで次のファイルにいったり:pで前のファイルにいったりすることができるようになるのです。ただこの方法では該当行まで飛んでくれないので、かなり不便です。代替策として以下のように根性をだしてlessする方法があります。

% global -x Hoge | awk '{ print "+"$2"G", $3 }' | xargs -n 2 less

qで次のファイル、C-cで終わりです。前のファイルには戻れませんが、そこそこ代替にはなっています。そうとう無茶していますが(笑

そもそもこの辺の処理はglobalが吸収すべきではないでしょうか。古き良きツールのgrepには-Cというマッチした行の周辺コンテキストを表示するコマンドがありますが、このような機能をglobalにもつけてほしいと思ってしまうのです。lessに丸投げにするにしても、lessのtags対応がいまいちなのでなんとも言えませんし。これはどうも自分で改造patch作ってmailinglistにpostしろという方向にベクトルが向いている雰囲気です。時間があるときになんとかしたいと思います。

Category(s)
program
linux
The URL to Trackback this entry is:
http://dev.ariel-networks.com/Members/matsuyama/coreblogentry.2006-07-20.8963268751/tbping

vim^Hは使えたほうがいいと思うのです

GNUのPAGER関係からあらゆる大規模コマンドの大半はEmacsではなくviのキーバインディングをサポートしています。まあ当然といえば当然なのですが。というわけでviのキーバインディングの超基礎をば。

移動関連
h
j
k
l
w単語単位で→
b単語単位で←
0行の先頭へ
^空白を除く行の先頭へ
$行の末尾へ
モード関連
ESCモード脱出
a追加編集モード
i挿入編集モード
検索関連
/xxxxxxを後方検索
?xxxxxxを前方検索

これだけでは全くvi, vimの恩恵にあずかれないので、本気で習得するならばVim Documents in Japaneseあたりを読んでみてください。ここにはかなりお世話になっています(まだ満足に使えませんが)。

PS: FCKEditorなどのWYSIWYGエディタを使えない僕はこのままHTMLで書けということなのでしょうか。

Category(s)
linux
The URL to Trackback this entry is:
http://dev.ariel-networks.com/Members/matsuyama/vim-h306f4f7f3048305f307b3046304430443068601d3046306e3059/tbping

Re:vim^Hは使えたほうがいいと思うのです

Posted by inoue at 2006-07-20 10:46
> PS: FCKEditorなどのWYSIWYGエディタを使えない僕はこのままHTMLで書けということなのでしょうか。

FCKEditorを使え、なんてことは言いません。
restructured textで書いてください(Webで検索してください)。テーブル、箇条書き、引用、整形済みの書き方を覚えれば、なんとかなると思います。

Emacs + Mew + Fetchmail + Procmailなメール環境

Fetchmailとはその名のとおりメールサーバーからメールをダウンロードするプログラムであり、Procmailは入力されたメールをユーザー指定のフィルタによって配分するプログラムです。これまでは個人でメールを受信するにしても面倒なローカルサーバーをたてたりしていましたが、FetchmailとProcmailを組合せることにより、ローカルサーバーをたてることなしにMaildir形式でメールを取り込むことができるようになりました。最小の設定は以下のようになります。

~/.fetchmailrc:

defaults
  protocol pop3
  keep # keep mails on the server
  no mimedecode
  mda "/usr/bin/procmail"

poll pop.example.com
  username example
  passward example

~/.procmailrc:

MAILDIR=$HOME/.maildir

これで

% fetchmail

とすれば.maildirにメールを取り込むことができます。次にMewの設定をします。

~/.emacs:

(autoload 'mew "mew" nil t)
(autoload 'mew-send "mew" nil t)
(setq mew-name "example")
(setq mew-user "example")
(setq mew-mail-domain "example.com")
(setq mew-smtp-server "smtp.example.com")
(setq mew-mailbox-type 'mbox)
(setq mew-mbox-command "incm")
(setq mew-mbox-command-arg "-u -d /home/example/.maildir")

これで、EmacsからM-x mewでMaildirにあるメールを閲覧することができます。Maildirにメールを取り込むにはその都度fetchmailする必要がありますが、一々ターミナルに移動するのが面倒でしたら

~/.emacs:

(defun fetchmail ()
  (interactive)
  (shell-command "fetchmail")
)

を定義しておけばいいでしょう。shell-commandのあとにmewを呼び出すとbetterかもしれません。

Category(s)
linux
emacs
The URL to Trackback this entry is:
http://dev.ariel-networks.com/Members/matsuyama/emacs-mew-fetchmail-procmail306a30e130fc30eb74b05883/tbping

Re:Emacs + Mew + Fetchmail + Procmailなメール環境

Posted by Bill at 2009-08-18 18:43
Hello Sir,

I have setup my system accordingly. I got a problem is that mew cannot read the mails fetched by fetchmail.
the mails are fetched and send by procmail to my maildir. I found that mew can read the mails after I changed the mail file name to pure figures, like from msg.ntLG to 15.

I have also try below:
(setq mew-mailbox-type 'maildir)
(setq mew-maildir-command "incm")
(setq mew-maildir-command-arg "-u -d /home/example/.maildir")

but it still don't work.

may I have done something wrong?

Best regards,

Bill

GNU screenを使って新着メール数を表示

http://dev.ariel-networks.com/Members/matsuyama/emacs-mew-fetchmail-procmail306a30e130fc30eb74b05883

メールを受信できるようになったのはいいのですが、新着があるかどうかもわからずにfetchmail -cしたりM-x mewするのはナンセンスというか面倒くさいのです。やはり理想はターミナルのどこかに新着メール数を表示してくれることです。幸いにも当方GNU screenのhardstatus alwayslastline(ターミナルの最終行にあらゆる情報を表示することができるステータス表示機能)を使っておりますので、ここに表示してしまうのが最も楽で見栄えもよいHackになるのです。ということで新着メール数を求める方法について検討したいと思います。まず一番はじめに思い浮かぶのが、.maildir/newのファイル数をそのまま新着メール数にしてしまうという方法。メリットはサーバー上にメールをkeepしなくてもよい。デメリットは実際に(バックグラウンドで)メールを受信しなければならない(あまりデメリットになっていない)。ほかの方法としてはサーバー上にメールをkeepしてしまってfetchmail -cの出力結果を解析して新着メール数を求める方法。メリットは実際にメールを受信するわけではないので計算時の負荷が小さい。デメリットはメールをサーバー上にkeepしなくてはならない(これは大きい)。現在のところ僕は後者の環境なのですので(近いうちに前者へ)、そちらを前提して説明します。

まずfetchmail -cで新着メール数を求める方法。これは何を使ってもいいのですが、fetchmail -cの出力結果が解析しづらい(というわけではないのですが)のと統一の問題を考慮して、Perlで書いてしまうのがいいと思います。

my ($total, $read) = `fetchmail -c` =~ /^(\d+).+?(\d+)/;
my $unread = $total - $read;
$unread = 0 if $unread < 0; # parse error ?
print $unread, "\n";

次に上のPerlスクリプトによって得られた値をターミナル、すなわちscreenのhardstatus alwayslastlineに送ります。(いろいろ方法はあるらしいですが)値を送る方法としてはscreenの-Xオプション(指定されたscreenに指定されたコマンドを送信するオプション)を使ってその都度hardstatus alwayslastlineを上書きしてしまうのが一番わかりやすいでしょう。具体的には以下のようになります。

% screen -r -X hardstatus alwayslastline Mail(0)

これでhardstatus alwayslastlineにMail(0)と表示されますので、0の部分を先ほど求めた$unreadに置きかえてやればいいわけです。

screenstatus:

#!/usr/bin/perl

my ($total, $read) = `fetchmail -c` =~ /^(\d+).+?(\d+)/;
my $unread = $total - $read;
$unread = 0 if $unread < 0;
`screen -r -X hardstatus alwayslastline Mail($unread)`;

実際に新着メール数をチェックさせてhardstatus alwayslastlineを更新させるには、このスクリプトを起動します。

% ./screenstatus

さて、これで新着メール数をターミナルに表示することはできましたが、いちいちscreenstatusを起動するのは面倒すぎます。普通の人ならcrontabに登録して自動で新着メール数が更新される姿にうっとりしたいはずです。というわけでcrontabに登録しましょう。

% crontab -e
*/10 * * * * /home/example/bin/screenstatus

これで10分ごとに新着メール数が更新されるはず!とワクワクしながら待てど一向に更新される気配がありません。

% crontab -e
*/10 * * * * screen -r -X hardstatus alwayslastline test > /tmp/stdout 2> /tmp/stderr

として/tmp/stdoutを確かめてみると

No screen session found.

となってしまっています。どうやら同一セッション内からでしか-rオプション(既存screenをresumeするオプション)を使えないようです。いろいろ対策を探しては試してみましたが一つの方法を除いて全て失敗におわりました。唯一成功した方法では-Sオプション(PIDからscreenを指定するオプション)を使用するので無理矢理感が否めませんが、ほかに方法がないのでこの方法を使うようにscreenstatusスクリプトを修正します。

screenstatus:

#!/usr/bin/perl
my ($pid) = `screen -ls` =~ /(\d+).+Attached/; # assume first number is PID

my ($total, $read) = `fetchmail -c` =~ /^(\d+).+?(\d+)/;
my $unread = $total - $read;
$unread = 0 if $unread < 0;
`screen -S $pid -X hardstatus alwayslastline Mail($unread)`;

これで無事10分ごとに新着メール数が更新されるようになりました。いやはやかっこいいですね。ぶっちゃけていうと、-Xオプションがサポートされているscreenでは新着メール数に限らずなんでも表示できてしまいます。screen最強です(screenに関するエントリも書く予定)。

なおrootで-Xオプションを使うにはコマンドが送られる側でaddacl or acladdコマンドが呼ばれている必要があります。

~.screenrc:

addacl root

あるいはC-a :でaddacl rootと逐次登録するのもありです。

Category(s)
linux
emacs
The URL to Trackback this entry is:
http://dev.ariel-networks.com/Members/matsuyama/gnu-screen30924f7f3063306665b0774030e130fc30eb657030928868793a/tbping

Re:GNU screenを使って新着メール数を表示

Posted by inoue at 2006-07-24 14:43
cronを使わずに、無限ループの中で10分間スリープするスクリプトを動かすのも手かもしれません。

Re:GNU screenを使って新着メール数を表示

Posted by kimata at 2006-07-31 21:21
初めまして.Wanderlust の wl-biff-notify-hook との組み合わせはどうでしょう?
http://acapulco.dyndns.org/hiki/hiki.cgi?%28Gentoo%29Screen

Linux的SWTプログラミング

gentoo portageのSWTはx86_64で問題がある(org.eclipse.swt.gtk.OS.memmoveがないとおこられる)ようなので http://www.eclipse.org/downloads/ -> Other downloads -> SWT Binary and Source -> Linux (x86_64/GTK-2)をダウンロードして以下のようにインストール。

% su
% unzip swt-3.2-gtk-linux-x86_64.zip -d /usr/local/

compile and run a test program.

Test.java:

import org.eclipse.swt.widgets.*;

public class Test {
    public static void main(String[] args) {
        Display display = new Display();
        Shell shell = new Shell(display);
        shell.setText("Test Shell");
        shell.setSize(200, 200);
        shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch())
                display.sleep();
        }
        display.dispose();
    }
}
% export CLASSPATH=$CLASSPATH:/usr/local/swt-M20060629-1905-gtk-linux-x86_64/swt.jar
% export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/swt-M20060629-1905-gtk-linux-x86_64/
% javac Test.java
% java Test

You may also be happy to read following useful documents (notably org.eclipse.swt.widgets in official).

Nihongo unatenakunatta. Koredakara GUI application ha iya nanda.

Category(s)
program
linux
The URL to Trackback this entry is:
http://dev.ariel-networks.com/Members/matsuyama/linux7684swt30ed30e930df30f3/tbping

Gentoo Linux 2006.0 + Xen 3.0インストールメモ - Domain 0のインストール

Gentoo Linux 2006.0 (kernel 2.6.17-r4)にXen 3.0をインストールしたときのメモを公開します。 以下かなり適当に説明するので、何をやってるのかわからない人はhttp://gentoo-wiki.com/HOWTO_Xen_and_Gentooを読んでください(ここの方法でうまくいけば、このメモ読む必要なし)。

Domain 0

準備

% nano /etc/make.conf

/etc/make.conf:

# CFLAGSに-mno-tls-direct-seg-refsを追加します。これを追加しないと著しくパフォーマンスが低下するらしいです。
# gcc4未満で-Osフラグを使用している場合は-O2に変えましょう。じゃないとbroken codeを吐いてしまうらしいです。
CFLAGS="-O2 -march=i686 -pipe -mno-tls-direct-seg-refs"
% echo "sys-libs/glibc nptlonly' >> /etc/portage/package.use
% # 世界を更新しましょう。Gentoo-Portage Wikiよりそのまま引用しました。
% # --newuseを指定していないのは単に忘れてたから?よくわからないので無視しましょう。
% emerge --emptytree --deep --ask --versose world
% # etc-updateやっておかないと大変なことになりますよ。
% etc-update
% # 必須ではありませんがnet.eth0を無効に。
% rc-update del net.eth0 default

Xenカーネルのインストール

まずはhypervisorとxen toolsをインストールします。

/etc/portage/package.keywords:

app-emulation/xen
app-emulation/xen-tools
sys-devel/dev86
sys-kernel/xen-sources

ソースコードもインストールしておきましょう。

% USE="symlink" emerge xen-sources
% # pam-loginがblockしてる場合はemerge -C pam-login
% emerge --ask --verbose app-emulation/xen app-emulation/xen-tools
% rc-update add xend default
% nano /etc/conf.d/rc

/etc/conf.d/rc:

# /etc/conf.d/rcのRC_NET_STRICT_CHECKINGをloにしないと正しくブリッジできなかったり起動中にフリーズしたりします。
RC_NET_STRICT_CHECKING="lo"

http://gentoo-wiki.com/HOWTO_Xen_and_GentooにもあるようにXenカーネルのコンパイル方法は二つあります。一つはgenkernelを使う方法で、もう一つは手動でmakeする方法です。上のページではgenkernelを使うことを事実推奨しているのですが、僕の環境ではgenkernelを使うこと自体が新たな問題を発生させているような感じがしました(/dev/ram0を認識できなかったり)。実際、http://gentoo-wiki.com/Talk:HOWTO_Xen_and_Gentooには「There seems to be a problem with using Genkernel to create an initramfs for Xen domains.」と書かれています。もちろんgenkernelの簡易さもすばらしいので、一度genkernelでコンパイルして動作できるか確認してみるのが良いでしょう。

% ls -l /usr/src/linux
... /usr/src/linux -> linux-2.6.16.26-xen
% emerge genkernel

/etc/genkernel.conf:

ARCH_OVERRIDE="xen0"

ちなみに僕の環境のgenkernel(3.4.0)とxen-sources(2.6.16.26)は相性が悪いようで、以下のような修正を加える必要があります。

/usr/share/genkernel/xen0/config.sh:

KERNEL_MAKE="make ARCH=i386"

カーネルをコンパイルします。

% genkernel --menuconfig --clean all
% # [Xen-compatible]
% # [*] 802.1d Ethernet Bridiging
% # XEN -> frontendドライバを無効

コンパイルが終了すれば/boot以下にkernel-genkernel-[spec]とinitramfs-genkernel-[spec]が生成されますので、grub.confでそれを指定してやります。

/boot/grub/grub.conf:

title=Gentoo Linux Xen 2.6.16.26
root (hd0,0)
kernel /boot/xen.gz dom0_mem=96M
module /boot/kernel-genkernel-xen0-2.6.16.26-xen root=/dev/ram0 real_root=/dev/sda1
module /boot/initramfs-genkernel-xen0-2.6.16.26-xen

これでkernel panicを起こさずに無事起動できたらもうこのメモを読む必要はありません。悲しいことに僕の環境ではkernel panicが起こってしまったので(/dev/ram0が認識できない)、もう一つの方法である手動makeでコンパイルすることになります(genkernelの試行錯誤でかなりの時間をもっていかれた)。

% cd /usr/src/linux
% make menuconfig
% # Domain 0 Kernel Config
Processor type and features  --->
  [Xen-compatible]

XEN --->
  [*] Privileged Guest (domain 0)
  < > PCI device backend driver
  <*> Block-device backend driver
  < >   Block Tap support for backend driver (DANGEROUS)
  <*> Network-device backend driver
  [ ]   Pipelined transmitter (DANGEROUS)
  <*>   Network-device loopback driver
  < > TPM-device backend driver
  < > Block-device frontend driver
  < > Network-device frontend driver
  < > Block device tap driver
  < > TPM-device frontend driver
  [*] Scrub memory before freeing it to Xen
  [ ] Disable serial port drivers
  <*> Export Xen attributes in sysfs

Networking --->
  Networking options --->
    [*] IP: tunneling
    [*] 802.1d Ethernet Bridging
% make && make modules_install
% cp vmlinuz /boot/vmlinuz-xen0-2.6.16.26-xen

その他必要なオプションを有効にしておきましょう。

カーネルをコンパイルします。

% cd /usr/src/linux
% make && make modules_install
% cp vmlinuz /boot/vmlinuz-xen0-2.6.16.26-xen

/boot/grub/grub.conf:

title=Gentoo Linux Xen 2.6.16.26
root (hd0,0)
kernel /boot/xen.gz dom0_mem=96M
module /boot/vmlinuz-xen0-2.6.16.26-xen root=/dev/sda1

これでもうまく起動できない場合は、問題にあわせてkernelオプションにdoscsiやacpi=offやnoapicなどを指定してみてください。また、kernelコンパイルオプションを見直すのも大切です。それでも解決できない場合は、あきらめるかkernelのデバッグをしましょう。

draft

Category(s)
linux
The URL to Trackback this entry is:
http://dev.ariel-networks.com/Members/matsuyama/coreblogentry.2006-08-21.5174391052/tbping

Copyright(C) 2001 - 2006 Ariel Networks, Inc. All rights reserved.