記事検索
月別アーカイブ
アクセスカウンター

    タグ絞り込み検索

    unix

    2016年02月25日11:42killできれいに死ぬシェルスクリプト

    止めるまで動きつづける統計値を延々と出力するようなプログラムの出力を加工するスクリプトというのがあるとする。

    たとえばeth0のトラフィックをkB/sを表示するもの:

    [sar.sh]
    #!/bin/sh
    /usr/bin/sar -n DEV 1 | awk '$2=="eth0"{print $6,$5}'
    

    で、これをつかってあるプログラムを実行したときのトラフィックを記録したいとする。

    [test.sh]
    #!/bin/sh
    ./sar.sh >sar.out &
    pid_sar=$!
    
    long_program
    
    kill $pid_sar
    cat sar.out
    

    プログラムの実行が終わったらkillしているのだが、シェルが終了するだけでsarやawkは動いたままになる。

    シェルは死ぬときにフォアグラウンドのプロセスをkillしてはくれないのだ。

    コマンドラインから ./sar.sh を直接実行した場合はシェル(/bin/sh ./sar.sh)だけでなくsarもawkも終了するのは、Ctrl-Cを押したときに端末ドライバ(tty)がフォアグラウンドプロセスグループに対してSIGINTを送ってくれるためだ。UNIXは今となっては無駄に端末まわりの機能が豊富なのだ。プロセスグループをつくってくれるのはコマンドラインを解釈しているログインシェルである。

    スクリプト1の中からスクリプト2を実行した場合にスクリプト2がきれいに終了するには、そういうふうにシェルスクリプトを書けばよいとおもうところだが、pipeでつないでいるので個別のプログラムのpidがわからないという問題が。

    ということで、一番簡単なプロセスグループをつくってしまえばokという解決方法をとることにした。

    こんなかんじで自分をプロセスグループリーダにしてプロセスグループをつくる。

    [setpgid.c]
    #include <unistd.h>
    #include <stdio.h>
    #include <string.h>
    #include <errno.h>
    int
    main(int ac, char **av)
    {
            char *prog = av[0];
            if (ac < 2)
                    return 1;
            if (setpgid(0, 0) < 0) {
                    fprintf(stderr, "%s:setpgid:%s\n", prog, strerror(errno));
                    return 1;
            }
            execvp(av[1], av+1);
            fprintf(stderr, "%s:exec:%s\n", prog, strerror(errno));
            return 1;
    }
    

    つかいかたはこんかかんじ。コマンドを起動するときにsetpgidをはさむのと、killするときにプロセスグループにシグナルを送るためにpidにマイナスをつける。

    [test.sh]
    #!/bin/sh
    ./setpgid ./sar.sh >sar.out &
    pid_sar=$!
    
    long_program
    
    kill -TERM -$pid_sar
    cat sar.out
    

    でもいちいち呼出側にsetpgidを入れてまわるのは頭わるいのでshebangに入れる。

    [sar.sh]
    #!./setpgid /bin/sh
    /usr/bin/sar -n DEV 1 | awk '$2=="eth0"{print $6,$5}'
    
    [test.sh]
    #!/bin/sh
    ./sar.sh >sar.out &
    pid_sar=$!
    
    long_program
    
    kill -TERM -$pid_sar
    cat sar.out
    

    プロセスグループにシグナルを送るのは自分でやるならシグナルをつかまえて自分のプロセスグループにシグナルを送りなおせばいいはず。

    [sar.sh]
    #!./setpgid /bin/sh
    die() {
            echo "bye"
            trap - TERM INT
            kill -TERM -$$
    }
    trap die TERM INT
    /usr/bin/sar -n DEV 1 | awk '$2=="eth0"{print $6,$5}'
    

    とおもってやってみるとシェルがシグナルをうけとっても、シェルレベルのシグナルハンドラを実行してくれない。どうもシェル依存のようだ。バックグランドで実行してwaitで待てばシグナルハンドラを実行してくれるようだが、POSIX規格で決まっているわけではないので絶対安全というわけではないらしい。

    #!./setpgid /bin/sh
    die() {
            echo "bye"
            trap - TERM INT
            kill -TERM -$$
    }
    trap die TERM INT
    /usr/bin/sar -n DEV 1 | awk '$2=="eth0"{print $6,$5}' & wait
    

    とりあえずの妥協点としてはこんなところか。

    http://togetter.com/li/942376

    koie



    このエントリーをはてなブックマークに追加
    2016年01月11日01:16autoconfで構造体のサイズを調べる方法

    多言語からCのライブラリのラッパーを実装するときに、構造体の大きさを知りたいということは、ちょくちょくあるとおもう。

    configure.ac

    AC_PREREQ(2.59)
    AC_INIT([oreore], [0.1], [info@example.com])
    AC_CONFIG_HEADERS([config.h])
    AC_CHECK_SIZEOF([pthread_mutex_t], [], [#include <pthread.h>])
    AC_SUBST([HOGE], [$ac_cv_sizeof_pthread_mutex_t])
    AC_CONFIG_FILES([boke.txt])
    AC_OUTPUT
    

    config.h.in

    #undef SIZEOF_PTHREAD_MUTEX_T
    

    boke.txt.in

    sizeof pthread_mutex_t is @HOGE@.
    

    実行例

    % autoconf
    % ./configure
    checking for gcc... no
    checking for cc... cc
    checking whether the C compiler works... yes
    checking for C compiler default output file name... a.out
    checking for suffix of executables...
    checking whether we are cross compiling... no
    checking for suffix of object files... o
    checking whether we are using the GNU C compiler... yes
    checking whether cc accepts -g... yes
    checking for cc option to accept ISO C89... none needed
    checking size of pthread_mutex_t... 8
    configure: creating ./config.status
    config.status: creating boke.txt
    config.status: creating config.h
    % cat config.h
    /* config.h.  Generated from config.h.in by configure.  */
    #define SIZEOF_PTHREAD_MUTEX_T 8
    % cat boke.txt
    sizeof pthread_mutex_t is 8.
    %
    

    koie



    このエントリーをはてなブックマークに追加
    2015年09月15日14:25シェルスクリプトで一時的代入の挙動(2)

    ここからの続き

    name=value command 構文

    commandのところをいろいろ変えて、コマンド行での変数代入が永続的かどうか調べてみた。

    • nullコマンド(built-in)
    • trueコマンド(freebsd shとdashではbuilt-in、bashでは外部コマンド→うそでしたbuilt-inでした)
    • ユーザ定義関数
    • 外部コマンド
    テストスクリプト
    X1=YES :
    echo "X1=${X1-NO}"
    printenv X1
    
    X2=YES true
    echo "X2=${X2-NO}"
    printenv X2
    
    g() {
        :
    }
    X3=YES g
    echo "X3=${X3-NO}"
    printenv X3
    
    X4=YES cal >/dev/null
    echo "X4=${X4-NO}"
    printenv X4
    
    f() {
        X=FUNC
    }
    X=CMD f
    echo "X=${X-NO}"
    printenv X
    
    fbsd sh
    X1=YES
    X2=NO
    X3=NO
    X4=NO
    X=NO
    
    bash
    X1=NO
    X2=NO
    X3=NO
    X4=NO
    X=NO
    
    bash -o posix
    X1=YES
    YES
    X2=NO
    X3=YES
    YES
    X4=NO
    X=FUNC
    FUNC
    
    dash
    X1=YES
    X2=NO
    X3=YES
    X4=NO
    X=FUNC
    
    結果

    永続的か?

    Shell nullコマンド 関数 trueコマンド 外部コマンド
    fbsd sh YES NO NO NO
    bash NO NO NO NO
    bash -o posix YES+環境変数 YES+環境変数 NO NO
    dash YES YES NO NO

    コマンド行の代入と呼ばれた関数内での代入の競合は?

    Shell 結果
    fbsd sh 永続的でない
    bash 永続的でない
    bash -o posix 永続的+環境変数
    dash 永続的

    koie



    このエントリーをはてなブックマークに追加
    2015年09月14日17:22シェルスクリプトで一時的代入の挙動

    シュルスクリプトで、コマンドの前に代入を書くとコマンドを実行するときに一時的にシェル変数と環境変数を設定できて便利。

    よくある用法

    readで空白も読みたいときにIFS=""を指定する場合に

    echo "*** WITHOUT IFS="
    cal | while read X; do
        echo "$X"
    done
    
    echo "*** WITH IFS="
    cal | while IFS= read X; do
        echo "$X"
    done
    

    実行結果

    *** WITHOUT IFS=
    September 2015
    Su Mo Tu We Th Fr Sa
    1  2  3  4  5
    6  7  8  9 10 11 12
    13 14 15 16 17 18 19
    20 21 22 23 24 25 26
    27 28 29 30
    
    *** WITH IFS=
       September 2015
    Su Mo Tu We Th Fr Sa
           1  2  3  4  5
     6  7  8  9 10 11 12
    13 14 15 16 17 18 19
    20 21 22 23 24 25 26
    27 28 29 30
    

    てっきりこの代入は一時的だとおもっていたのだが、呼ばれるコマンドがシェル関数かコマンドかで挙動が違うらしい。


    http://tiswww.case.edu/php/chet/bash/POSIX

    31. Assignment statements preceding shell function calls persist in the
        shell environment after the function returns, as if a POSIX
        special builtin command had been executed.
    


    試した環境
    • FreeBSD /bin/sh
    • CentOS /bin/dash
    • bash
    • bash -o posix
    テストスクリプト
    f() {
        echo "$X"
        /usr/bin/printenv X
    }
    g() {
        X="$X.g1" f
        X="$X.g2" f
    }
    h() {
        X="$X.h1" g
        X="$X.h2" g
    }
    X=m1 h
    X="$X.m2" h
    
    sh
    m1.h1.g1
    m1.h1.g2
    m1.h2.g1
    m1.h2.g2
    .m2.h1.g1
    .m2.h1.g2
    .m2.h2.g1
    .m2.h2.g2
    
    dash
    m1.h1.g1
    m1.h1.g1.g2
    m1.h1.g1.g2.h2.g1
    m1.h1.g1.g2.h2.g1.g2
    m1.h1.g1.g2.h2.g1.g2.m2.h1.g1
    m1.h1.g1.g2.h2.g1.g2.m2.h1.g1.g2
    m1.h1.g1.g2.h2.g1.g2.m2.h1.g1.g2.h2.g1
    m1.h1.g1.g2.h2.g1.g2.m2.h1.g1.g2.h2.g1.g2
    
    bash
    m1.h1.g1
    m1.h1.g1
    m1.h1.g2
    m1.h1.g2
    m1.h2.g1
    m1.h2.g1
    m1.h2.g2
    m1.h2.g2
    .m2.h1.g1
    .m2.h1.g1
    .m2.h1.g2
    .m2.h1.g2
    .m2.h2.g1
    .m2.h2.g1
    .m2.h2.g2
    .m2.h2.g2
    
    bash -o posix
    m1.h1.g1
    m1.h1.g1
    m1.h1.g1.g2
    m1.h1.g1.g2
    m1.h1.g1.g2.h2.g1
    m1.h1.g1.g2.h2.g1
    m1.h1.g1.g2.h2.g1.g2
    m1.h1.g1.g2.h2.g1.g2
    m1.h1.g1.g2.h2.g1.g2.m2.h1.g1
    m1.h1.g1.g2.h2.g1.g2.m2.h1.g1
    m1.h1.g1.g2.h2.g1.g2.m2.h1.g1.g2
    m1.h1.g1.g2.h2.g1.g2.m2.h1.g1.g2
    m1.h1.g1.g2.h2.g1.g2.m2.h1.g1.g2.h2.g1
    m1.h1.g1.g2.h2.g1.g2.m2.h1.g1.g2.h2.g1
    m1.h1.g1.g2.h2.g1.g2.m2.h1.g1.g2.h2.g1.g2
    m1.h1.g1.g2.h2.g1.g2.m2.h1.g1.g2.h2.g1.g2
    

    まとめると

    Shell 一時的か? 環境変数か?
    fbsd sh Yes No
    dash No No
    bash Yes Yes
    bash -o posix No Yes

    続く

    koie



    このエントリーをはてなブックマークに追加
    2013年02月07日19:46sshでリモートログインしてlsするまで
                              _____________
                             |             |
         ____________        | xterm       |           
        |            |       |__________   |           
        | Xserver    |       |          |  |           
        |_________   |       | Xtoolkit |  |     ________        ________    _______  fork  _______ 
        |         |  |       |----------|  |    |        |      |        |  |       | exec |       |
        | xdriver |  |       | Xlib     |  |    | ssh    |      | sshd   |  | shell |----->| ls    |
        |_________|__|       |__________|__|    |________|      |________|  |_______|      |_______|
        |            |       |             |    |        |      |        |  |       |      |       |
        | libc       |       | libc        |    | libc   |      | libc   |  | libc  |      | libc  |
        |____________|       |_____________|    |________|      |________|  |_______|      |_______|
          |        |            |        |         |  |            |  |         |            |  |
    USER  |        |            |        |         |  |            |  |         |            |  |
    ______|________|____________|________|_________|__|____________|__|_________|____________|__|__________
          |        |            |        |         |  |            |  |         |            |  |       
    KERN  |        |   event    |        |   "ls"  |  |   "xxx"    |  |  "ls"   |____________|  |       
          |        |  --------> |        | ------> |  |  ------->  |  | ------> |   <------     |readdir
          |        +--(socket)--+        +--(pty)--+  +--(socket)--+  +--(pty)--+    "core"     |       
        [driver]      <-------             <------       <-------       <------                 |       
          |            request              "core"        "yyy"          "core"            [FileSystem] 
          |          X protocol                        SSH protocol                             |
          |                                                                                     |
    ______|_____________________________________________________________________________________|__________
         _|_____                                                                             ___|___
    HW  |       |                                                                           |       |
        | KBD   |                                                                           | disk  |
        | Mouse |                                                                           |_______|
        | Video |
        |_______|
    

    koie



    このエントリーをはてなブックマークに追加
    2013年01月11日00:46printfして画面に文字がでるまで
                _______________
               |               |   _______________
               | xterm         |  |               |
               |     __________|  | Xserver       |
               |    |          |  |               |
     _______   |    | Xtoolkit |  |      _________|
    |       |  |    |----------|  |     |         |
    | a.out |  |    | Xlib     |  |     | xdriver |
    |_______|  |____|__________|  |_____|_________|
    |       |  |               |  |               |
    | libc  |  | libc          |  | libc          |
    |_______|  |_______________|  |_______________|     USER
        |        |         |         |      |  |
    ____|________|_________|_________|______|__|_______
        |        |         |         |      |  |
     ___|________|___   ___|_________|___   |  |
    |                | |                 |  | [drv?]
    |  pty           | |  IPC(socket)    |  |  |
    |________________| |_________________|[drv]|
                                            |  |        KERN
    ________________________________________|__|_______
                                  __________|  |
                            _____|_____     ___|___
                           |           |   |       |
                           | KBD/Mouse |   | Video |
                           |___________|   |_______|    HW
    ___________________________________________________
    

    koie



    このエントリーをはてなブックマークに追加
    2011年02月19日17:23無名ファイル(3)

    カレントディレクトリを消す実験でシェルから実行するとシェルが何をしているかわからないのでopenしているかもしれない。なのでテストプログラムを組んで実験してみた。

    koie@guriandgura% df .
    Filesystem  1024-blocks   Used  Avail Capacity  Mounted on
    /dev/ad4s2a      507630 352518 114502    75%    /
    koie@guriandgura% uname -sr
    FreeBSD 9.0-CURRENT
    koie@guriandgura% cat -n foo.c
         1  #include <stdio.h>
         2  #include <sys/types.h>
         3  #include <dirent.h>
         4  #include <sys/stat.h>
         5
         6  static void
         7  ls_file(const char* path)
         8  {
         9      struct stat st;
        10      lstat(path, &st);
        11      printf("%-10s ino=%ld nlink=%ld\n", path, st.st_ino, st.st_nlink);
        12  }
        13
        14  static void
        15  ls_dir(const char* path)
        16  {
        17      DIR* dp = opendir(path);
        18      if (dp == NULL) {
        19          perror("opendir");
        20          return;
        21      }
        22      printf("ls %s {\n", path);
        23      struct dirent *dep;
        24      while ((dep = readdir(dp)) != NULL) {
        25          char fn[100];
        26          snprintf(fn, sizeof fn, "%s/%s", path, dep->d_name);
        27          ls_file(fn);
        28      }
        29      closedir(dp);
        30      printf("}\n");
        31  }
        32
        33  int
        34  main()
        35  {
        36      int rc;
        37      if (mkdir("d", 0777) < 0) {
        38          perror("mkdir");
        39          return 1;
        40      }
        41      if (chdir("d") < 0) {
        42          perror("chdir");
        43          return 1;
        44      }
        45      ls_dir(".");
        46      if (rmdir(".", 0777) < 0) {
        47          perror("rmdir");
        48          printf("keep going.\n");
        49      }
        50      if (rmdir("../d", 0777) < 0) {
        51          perror("rmdir");
        52          return 1;
        53      }
        54      ls_dir(".");
        55      ls_file(".");
        56      return 0;
        57  }
    koie@guriandgura% cc foo.c
    koie@guriandgura% ./a.out
    ls . {
    ./.        ino=33552 nlink=2
    ./..       ino=33544 nlink=3
    }
    rmdir: Invalid argument
    keep going.
    ls . {
    }
    .          ino=33552 nlink=0
    koie@guriandgura%
    
    $ uname -sr
    Linux 2.6.18-194.32.1.el5
    $ cc foo.c
    $ uname -sr
    Linux 2.6.18-194.32.1.el5
    $ ./a.out
    ls . {
    ./..       ino=64225281 nlink=4
    ./.        ino=64225284 nlink=2
    }
    rmdir: Invalid argument
    keep going.
    ls . {
    }
    .          ino=64225284 nlink=0
    $
    

    この結果からすると、ディレクトリのデータ部分(つまりディレクトリエントリ)は消えているが、ディレクトリ自身(=ディレクトリのメタデータ=inode)は消えてなくて、おそらくlookupで"."が特別扱いされいるためにディレクトリエントリを参照することなくカレントディレクトリを返しているのではないだろうか。

    #正直なところおっさんにはカーネルソースを読む気力はすでにない。



    このエントリーをはてなブックマークに追加
    2011年02月18日00:38無名ファイル(2)

    2つopenしたときにリンクカウントがどうなるか試してみた。

    FreeBSD UFS2の場合:

    koie@guriandgura% uname -sr
    FreeBSD 9.0-CURRENT
    koie@guriandgura% cat -n test.sh
         1  #!/bin/sh
         2  mkdir d || exit 1
         3  cd d || exit 1
         4
         5  touch file
         6
         7  sleep 10 >>file &
         8  sleep 1
         9  ls -li file
        10
        11  sleep 10 >>file &
        12  sleep 1
        13  ls -li file
        14
        15  wait
        16
        17  cd .. || exit 1
        18  rm -r d
    
    koie@guriandgura% sh -x test.sh
    + mkdir d
    + cd d
    + touch file
    + sleep 10
    + sleep 1
    + ls -li file
    33552 -rw-r--r--  1 koie  wheel  0  2月 18 00:26 file
    + sleep 10
    + sleep 1
    + ls -li file
    33552 -rw-r--r--  1 koie  wheel  0  2月 18 00:26 file
    + wait
    + cd ..
    + rm -r d
    koie@guriandgura%
    

    Linux ext3の場合:

    $ uname -sr
    Linux 2.6.18-164.11.1.el5
    $ sh -x test.sh
    + mkdir d
    + cd d
    + touch file
    + sleep 10
    + sleep 1
    + ls -li file
    19170211 -rw-rw-r-- 1 koie koie 0 Feb 18 00:33 file
    + sleep 10
    + sleep 1
    + ls -li file
    19170211 -rw-rw-r-- 1 koie koie 0 Feb 18 00:33 file
    + wait
    + cd ..
    + rm -r d
    $
    

    2つopenしたからといってリンクカウントが3にはならず1のまま。もしopen/closeのたびにリンクカウントを更新したとするとinodeのアップデートが頻発してパフォーマンスに問題がでるだろう。可能性としてはatime/mtimeのようにすぐに更新しないという戦略で逃げているかもしれない。

    inodeを消すかはdinodeのlinkcountとvnodeのrefcountが両方0になったときだと予想。

    $ mkdir d
    $ ls -lid d
    19170210 drwxrwxr-x 2 koie koie 4096 Feb 18 00:42 d/
    $ cd d
    $ ls -lid .
    19170210 drwxrwxr-x 2 koie koie 4096 Feb 18 00:42 ./
    $ rmdir .
    rmdir: .: Invalid argument
    $ rmdir ../d
    $ ls -lid .
    19170210 drwxrwxr-x 0 koie koie 0 Feb 18 00:42 ./
    $
    

    リンクカウント0のディクトリができて、参照できることからinodeは消されてないことがわかる。



    このエントリーをはてなブックマークに追加
    2011年02月13日01:06名無ファイル

    unixでファイルをつくってからrmするとどうなるかテスト。OSはFreeBSDでファイルシステムはUFS2。

    前準備で空っぽなファイルbokeをつくる。

    catコマンドをバックグラウンドで実行してオープンした状態を維持する。

    guriandgura# df /
    Filesystem  1K-blocks   Used  Avail Capacity  Mounted on
    /dev/ad4s2a    507630 352502 114518    75%    /
    guriandgura# mkdir /hoge
    guriandgura# cd /hoge
    guriandgura# cat >boke&
    [1] 56133
    guriandgura# ls -al
    total 4
    drwxr-xr-x   2 root  wheel   512  2月 13 00:17 .
    drwxr-xr-x  32 root  wheel  1024  2月 13 00:17 ..
    -rw-r--r--   1 root  wheel     0  2月 13 00:17 boke
    guriandgura# ls -i /hoge/boke
    49952 /hoge/boke
    

    inode番号は49952で、まだ書き込んでいないのでファイルサイズは0。

    fsdbでinodeをのぞいてみる。

    -rオプションをつけてread onlyでのぞき。

    guriandgura# fsdb -r /dev/ad4s2a
    ** /dev/ad4s2a (NO WRITE)
    Examining file system `/dev/ad4s2a'
    Last Mounted on /
    current inode: directory
    I=2 MODE=40755 SIZE=1024
    	BTIME=Apr 25 04:11:35 2007 [0 nsec]
    	MTIME=Feb 13 00:17:04 2011 [0 nsec]
    	CTIME=Feb 13 00:17:04 2011 [0 nsec]
    	ATIME=Jul 20 23:54:57 2010 [0 nsec]
    OWNER=root GRP=wheel LINKCNT=32 FLAGS=0 BLKCNT=4 GEN=694ba5aa
    fsdb (inum: 2)> inode 49952
    current inode: regular file
    I=49952 MODE=100644 SIZE=0
    	BTIME=Feb 13 00:17:03 2011 [0 nsec]
    	MTIME=Feb 13 00:17:03 2011 [0 nsec]
    	CTIME=Feb 13 00:17:03 2011 [0 nsec]
    	ATIME=Feb 13 00:17:03 2011 [0 nsec]
    OWNER=root GRP=wheel LINKCNT=1 FLAGS=0 BLKCNT=0 GEN=18996b66
    fsdb (inum: 49952)> quit
    

    LINKCNT=1となっていてディレクトリからちゃんと参照されているのがわかる。

    ファイルをrmしたらinodeはどうなるか?

    rmというのはディレクトリからの参照を消すこと。

    guriandgura# ls -li boke
    49952 -rw-r--r--  1 root  wheel  0  2月 13 00:17 boke
    guriandgura# rm boke
    guriandgura# ls -li boke
    ls: boke: そのようなファイルまたはディレクトリはありません
    guriandgura# sync
    guriandgura# fsdb  -r /dev/ad4s2a
    ** /dev/ad4s2a (NO WRITE)
    Examining file system `/dev/ad4s2a'
    Last Mounted on /
    current inode: directory
    I=2 MODE=40755 SIZE=1024
    	BTIME=Apr 25 04:11:35 2007 [0 nsec]
    	MTIME=Feb 13 00:17:04 2011 [0 nsec]
    	CTIME=Feb 13 00:17:04 2011 [0 nsec]
    	ATIME=Jul 20 23:54:57 2010 [0 nsec]
    OWNER=root GRP=wheel LINKCNT=32 FLAGS=0 BLKCNT=4 GEN=694ba5aa
    fsdb (inum: 2)> inode 49952
    current inode: regular file
    I=49952 MODE=100644 SIZE=0
    	BTIME=Feb 13 00:17:03 2011 [0 nsec]
    	MTIME=Feb 13 00:17:03 2011 [0 nsec]
    	CTIME=Feb 13 00:19:28 2011 [0 nsec]
    	ATIME=Feb 13 00:17:03 2011 [0 nsec]
    OWNER=root GRP=wheel LINKCNT=0 FLAGS=0 BLKCNT=0 GEN=18996b66
    fsdb (inum: 49952)> quit
    

    リンク数が0になったのがわかる。つまりファイルシステム上ではどのディレクトリにも名前がないということ。

    ファイルにデータをかきこんだらどうなるか?

    guriandgura# fg
    cat > boke
    hoge
    hoge
    ^Z
    中断
    guriandgura# sync
    guriandgura# fsdb -r /dev/ad4s2a
    ** /dev/ad4s2a (NO WRITE)
    Examining file system `/dev/ad4s2a'
    Last Mounted on /
    current inode: directory
    I=2 MODE=40755 SIZE=1024
    	BTIME=Apr 25 04:11:35 2007 [0 nsec]
    	MTIME=Feb 13 00:17:04 2011 [0 nsec]
    	CTIME=Feb 13 00:17:04 2011 [0 nsec]
    	ATIME=Jul 20 23:54:57 2010 [0 nsec]
    OWNER=root GRP=wheel LINKCNT=32 FLAGS=0 BLKCNT=4 GEN=694ba5aa
    fsdb (inum: 2)> inode 49952
    current inode: regular file
    I=49952 MODE=100644 SIZE=10
    	BTIME=Feb 13 00:17:03 2011 [0 nsec]
    	MTIME=Feb 13 00:20:36 2011 [0 nsec]
    	CTIME=Feb 13 00:20:36 2011 [0 nsec]
    	ATIME=Feb 13 00:17:03 2011 [0 nsec]
    OWNER=root GRP=wheel LINKCNT=0 FLAGS=0 BLKCNT=4 GEN=18996b66
    fsdb (inum: 49952)> quit
    

    SIZE=10になってファイルが大きくなっているのがわかる。またBLKCNT=4になって実際にデータブロックが割り当てられているのもわかる。

    closeしたらinodeはどうなる?

    catコマンドをkillしてcloseする。

    guriandgura# fg
    cat > boke
    ^C
    guriandgura# sync
    guriandgura# fsdb -r /dev/ad4s2a
    ** /dev/ad4s2a (NO WRITE)
    Examining file system `/dev/ad4s2a'
    Last Mounted on /
    current inode: directory
    I=2 MODE=40755 SIZE=1024
    	BTIME=Apr 25 04:11:35 2007 [0 nsec]
    	MTIME=Feb 13 00:17:04 2011 [0 nsec]
    	CTIME=Feb 13 00:17:04 2011 [0 nsec]
    	ATIME=Jul 20 23:54:57 2010 [0 nsec]
    OWNER=root GRP=wheel LINKCNT=32 FLAGS=0 BLKCNT=4 GEN=694ba5aa
    fsdb (inum: 2)> inode 49952
    current inode 49952: unallocated inode
    fsdb (inum: 49952)> quit
    guriandgura# 
    

    inodeビットマップがクリアされてしまったのだろう、unallocatedと表示されてしまいディスク上のinodeがどうクリアされたかは見えず。

    まとめ

    openしたままrmするとリンク数は0になるが、inodeが再利用されないようにinodeビットマップは使用中のままである。

    もしopenしたままrmしたあとにシステムクラッシュすると、fsckはこのinodeは使われていないとしてビットマップを修正するだろう。



    このエントリーをはてなブックマークに追加