Feb 24, 2011

awk スクリプト

知り合いが awk (1) の勉強をしたいと言ってるので、 支援がてら過去に作成したスクリプトをさらしてみる。
このスクリプトは linux 上で稼働している あるプログラムが取得した共有メモリの残骸を掃除するスクリプトで、 ipcs (8) で取得した共有メモリ一覧のうち、 3 件連続しているキーが存在する場合 ipcrm (8) をコールして 共有メモリを削除する処理を行う。
短いスクリプトながら、外部コマンドの呼出し (system())、 コマンドからの値取得 (getline())、 そして関数内ローカルスコープの変数定義など awk (1)の持っている機能を結構活用しているので、 多少なりとも参考にして貰えるとうれしい。

  1#!/bin/sh
  2#
  3# Copyright (c) 2010 Mitzyuki IMAIZUMI, All rights reserved.
  4#
  5# $Id: shmrm,v 1.7 2010/05/08 09:03:15 mitz Exp $
  6#
  7# 共有メモリ削除処理
  8#
  9
 10LANG=C /usr/bin/ipcs -m | sort |
 11
 12awk '
 13    #
 14    # 初期処理
 15    #
 16    BEGIN{
 17
 18        max = 0;                        # 削除対象キーインデックス
 19        num = 0;                        # 削除対象共有メモリインデックス
 20        ipcrm = "/usr/bin/ipcrm";       # ipcrm コマンド
 21
 22    }
 23
 24    #
 25    # 16進数 -> 10進数変換
 26    #    cmd, dec はローカル変数として利用するために仮引数宣言とする
 27    #
 28    function    h2d(hex,            cmd, dec)
 29    {
 30
 31        # printf(1) を利用して 16進数を 10進数に変換
 32        cmd = sprintf("printf '%%d' %s", hex);
 33        # printf(1) の実行結果を getline で変数 dec に取得
 34        cmd | getline dec;
 35        close(cmd);
 36
 37        return dec;
 38
 39    }
 40
 41    #
 42    # 3連続するキーかのチェック
 43    #    start, i はローカル変数として利用するために仮引数宣言とする
 44    #
 45    function    cont3(num,          start, i)
 46    {
 47
 48        start = h2d(key[num]);
 49
 50        for(i=1; i<3; i++)
 51            if(h2d(key[num+i]) != start + i)
 52                return 0;
 53
 54        return 1;
 55
 56    }
 57
 58    #
 59    # コマンド実行
 60    #
 61    function    exec(key, arg)
 62    {
 63
 64        system(sprintf("%s -%s %s", ipcrm, arg, key));
 65
 66    }
 67
 68    #
 69    # 共用メモリ/セマフォの削除
 70    #
 71    function    shmrm(key, num)
 72    {
 73
 74        # 共有メモリを削除
 75        exec(key, "M");
 76
 77        # セマフォを削除
 78        if(num % 3 == 2)
 79            exec(key, "S");
 80
 81    }
 82
 83    #
 84    # メイン処理
 85    #
 86    {
 87
 88        # owner が root で権限が 666 かつ nattch が 0 の共用メモリを検索
 89        if($3 == "root" && $4 == "666" && $6 == 0)
 90            key[max++] = $1;
 91
 92    }
 93
 94    #
 95    # 終了処理(ある意味こっちがメイン)
 96    #
 97    END{
 98
 99        if("'$1'" == "-f"){
100            # 強制モード -- 3連続していないキーでも削除
101            for(n in key)
102                shmrm(key[n], 2);
103        }
104        else {
105            # 通常モード -- 3連続しているキーが削除対象なので抽出する
106            for(i=0; i<max; i++)
107                if(cont3(i))
108                    for(j=0; j<3; j++)
109                        target[num++] = key[i+j];
110
111            # 削除対象の共有メモリ/セマフォを削除
112            for(n in target)
113                shmrm(target[n], n);
114        }
115
116    }
117'
    

Edit this entry...

wikieditish message: Ready to edit this entry.
















A quick preview will be rendered here when you click "Preview" button.