ラベル Linux の投稿を表示しています。 すべての投稿を表示
ラベル Linux の投稿を表示しています。 すべての投稿を表示

2011/03/23

bashのexceとはなんぞや

発端

    #!/bin/bash
    exec 2>&1
    somecommand

というコードがあって、exec 2>&1が何をしているかはわかるけど、内部はどうなっているのか知らなかった

execってsystem callにあるよね

exec(2)は既存のプロセスのまま新しくコマンドを実行する

例えば

    $ exec ls

上記コマンドは既存のshellのプロセスのままlsを実行して終了する。実行中だったshellはexecされたら、lsになってしまうのでshellも結果として閉じる。

    $ ls

だとfork(2)して子プロセスでexec lsしているので、shellは終了しない

bashのexecはなんだよ

よくわからないからbashのsourceを読んでみる。Open Sourceに感謝する瞬間である。

Bash公式からダウンロード。tar ballを展開して、中身を改める。

ざっくり中身を見るとbuiltins/exec.defが怪しいので中をあらためる。そうするとshell_execveが見つかる。これを追いかけると以下のようになる。

builtins/exec.def
↓
shell_execve関数発見
↓
execute_cmd.cにあり
↓
int shell_execve (command, args, env)が見つかる
↓
execve (command, args, env);
↓
こいつはunistd.hで定義されているexecve(2)のようだ

眠いので限界です

次回へ続く?

2010/11/28

sedとperlで置換処理をするとファイルのownerが変更される

HTMLの置換処理をしていたときに,全ファイルのownerが変更されていたので気になって調べたのでメモ.

実行したコマンド

$ find . -type f -name "*.html" | xargs perl -i -pe 's/aaa/bbb/g'

perlをsedに置き換えても同様の現象が起きたので,内部で何が起きているのかstraceで確かめてみた

perlの場合

下記コマンドを実行して,perl-outの中身を確認

$ sudo strace -o perl-out perl -i -pe 's/aaa/bbb/' a.txt 
open("a.txt", O_RDONLY|O_LARGEFILE)     = 3
ioctl(3, SNDCTL_TMR_TIMEBASE or TCGETS, 0xbf96cae8) = -1 ENOTTY (Inappropriate ioctl for device)
_llseek(3, 0, [0], SEEK_CUR)            = 0
fstat64(3, {st_mode=S_IFREG|0644, st_size=12, ...}) = 0
fcntl64(3, F_SETFD, FD_CLOEXEC)         = 0
unlink("a.txt")                         = 0
open("a.txt", O_WRONLY|O_CREAT|O_EXCL|O_LARGEFILE, 0600) = 4
ioctl(4, SNDCTL_TMR_TIMEBASE or TCGETS, 0xbf96cae8) = -1 ENOTTY (Inappropriate ioctl for device)
_llseek(4, 0, [0], SEEK_CUR)            = 0
fstat64(4, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
fcntl64(4, F_SETFD, FD_CLOEXEC)         = 0
fstat64(4, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
fchmod(4, 0100644)                      = 0
fchown32(4, 1000, 1000)                 = 0
read(3, "ddd\nbbb\nccc\n", 4096)        = 12
read(3, "", 4096)                       = 0
write(4, "ddd\nbbb\nccc\n", 12)         = 12
close(4)                                = 0
close(3)                                = 0
exit_group(0)                           = ?
  1. a.txtをO_RDONLYでopen (fd=3)
  2. a.txtをunlink
  3. a.txtを今度はO_WRONLYでopen (fd=4)
  4. fd=3のa.txtからreadして,fd=4のa.txtに書き込み
  5. fd=4, fd=3をclose

2でunlinkして,同じ名前のファイルを再度作成しているのでownerがかわる模様

sedの場合

こんな感じのコマンドを実行して

$ sudo strace -e trace=open,close,rename,write,read -o sed-out sed -i 's/aaa/ddd/' a.txt

set-outに吐き出されたログを確認

open("a.txt", O_RDONLY|O_LARGEFILE)     = 3 
open("/proc/filesystems", O_RDONLY|O_LARGEFILE) = 4 
read(4, "nodev\tsysfs\nnodev\trootfs\nnodev\tb"..., 1024) = 337 
read(4, "", 1024)                       = 0 
close(4)                                = 0 
open("./sedwfohhg", O_RDWR|O_CREAT|O_EXCL|O_LARGEFILE, 0600) = 4 
read(3, "ddd\nbbb\nccc\n", 4096)        = 12
write(4, "ddd\n", 4)                    = 4 
write(4, "bbb\n", 4)                    = 4 
write(4, "ccc\n", 4)                    = 4 
read(3, "", 4096)                       = 0 
close(3)                                = 0 
close(4)                                = 0 
rename("./sedwfohhg", "a.txt")          = 0 
close(1)                                = 0 
close(2)                                = 0 
  1. a.txtをopen
  2. 一時ファイルとして./sedwfohhgをopen
  3. a.txtをreadして,中身を./sedwfohhgにwrite
  4. a.txtをclose
  5. ./sedwfohhgをa.txtにrename

renameしちゃっているのでownerが変わることになる

2010/10/24

libnotifyでTwitterのTimelineをデスクトップに通知

最近ときどきUbuntuの入ったノートPCを使っていて,Twitterの投稿がデスクトップに通知されるとうれしいなと思って(何番煎じかわからないが探すのがめんどくさかった)作ってみた.
  1. aptでlibnotifyをinstall
  2. OAuthを利用するためにdev.twitter.comで自分用アプリを適当に登録する
  3. AnyEvent::Twitter::Stream, Gtk2::Notifyをcpanm等でinstall
  4. stream2libnotify.plを実行!
stream2libnotify.pl

2010/03/30

MySQL Proxyをちょっと触った

MySQL Proxyを少し触ったのでメモ

MySQLサーバとクライアントに入るミドルウェア。
現在のversionは0.8.0でbeta状態。

--proxy-addressで自分の待ち受けポート等を指定できる。
FAQだとsocketで待ち受けはできないって書いてあるけど、すげー下の方にあるコメントを読むと待ち受けできるよ!って書いてあった。
実際できる。

ただし作成されるsocketの権限が1755で、オーナーが--userで指定したユーザではなく起動ユーザになっているので、
他のユーザから書き込めない可能性がある。
CentOS 5.4Finalのyumから入れたmysqld-serverだとデフォルトで作成されるsocketは1777になっていた。
同じパーミッションに変更してあげると普通にmysql-clientからも接続できた。

またmysqlはデフォルトでsocketとTCP接続の両方で待ち受けるけど、MySQL Proxyはどちらか片方でしか待ち受けできない。
localhost上にあるMySQLへの接続をProxyしようとすると、MySQL Proxyを二つ走らせる必要がありそう。

シグナルの処理がおかしい気がする SIGTERMとかSIGHUPを送っても反応がなかったりとか。

2008/05/08

[Linux]directoryのtimestampe

Linuxのdirectoryのtimestampの挙動で悩んでしまったので、忘れないようにメモ。
directoryの直下にdirectory/fileが作成された場合、又は直下にあるdirectory/fileが削除された場合に更新される。