プロジェクトおよびタスク機能 (第 5 章「プロジェクトとタスク」で説明) を使って作業負荷にラベル付けを行い、分離することにより、作業負荷ごとの資源消費を監視できます。「拡張アカウンティング」サブシステムを使用すると、プロセスとタスクの両方について詳細な資源消費統計情報を取得できます。 拡張アカウンティングサブシステムでは、行われた作業の対象プロジェクトの使用状況レコードにラベル付けします。 また、拡張アカウンティングを IPQoS (Internet Protocol Quality of Service、IP サービス品質) フローアカウンティングモジュールと組み合わせて、システム上のネットワークフロー情報を取得することもできます。 IPQoS フローアカウンティングモジュールについては、『IPQoS の管理』の「フローアカウンティングの使用と統計情報の収集 (手順)」を参照してください。
拡張アカウンティングを開始する方法については、プロセス、タスク、およびフローの拡張アカウンティングを起動する方法を参照してください。
資源管理メカニズムを適用する前に、まず、さまざまな作業負荷がシステムに対して行う資源消費要求の特徴をつかむ必要があります。Solaris オペレーティング環境の拡張アカウンティング機能を利用すると、タスクベース、プロセスベース、または IPQoS が提供するセレクタベース (ipqos(7IPP) 参照) で、システムやネットワークの資源消費を記録する柔軟性が得られます。システムの使用状況をリアルタイムで計測するオンライン監視ツールとは異なり、拡張アカウンティング機能を使用すると、使用状況の履歴を調べることができます。 その上で、将来の作業負荷の容量要件を算定できます。
拡張アカウンティングのデータを使用すれば、資源についての課金、作業負荷の監視、容量計画などの目的でソフトウェアを開発したり購入したりできます。
Solaris 環境の拡張アカウンティング機能は、アカウンティングデータを含めるために、バージョン番号が付けられた拡張可能なファイル形式を使用します。このデータ形式を使用するファイルは、添付のライブラリ libexacct(3LIB) で提供される API を使ってアクセスまたは作成できます。作成されたファイルは、拡張アカウンティング機能を使用できる任意のプラットフォーム上で分析でき、データを容量計画やチャージバックに使用できます。
拡張アカウンティングを起動すると、libexacct API で調べることができる統計情報が収集されます。libexacct は、exacct ファイルを前後どちらの方向からでも検査できます。API は、カーネルが作成するファイルだけでなく、 libexacct によって生成されたサードパーティ製のファイルもサポートします。libexact に対する Practical Extraction and Report Language (Perl) インタフェースがあり、これによってレポートおよび抽出用のカスタムスクリプトを作成できます。 libexacct に対する Perl インタフェース を参照してください。
拡張アカウンティングを有効にすると、タスクは、自分のメンバープロセスの総資源使用状況を追跡します。タスクのアカウンティングレコードは、そのタスクの完了時に書き込まれます。中間レコードを書き込むこともできます。タスクの詳細については、第 5 章「プロジェクトとタスク」を参照してください。.

拡張アカウンティングの形式は、古い SunOS システムのアカウンティングソフトウェアの形式に比べて拡張性があります (『Solaris のシステム管理 (上級編)』の「システムアカウンティング」を参照)。拡張アカウンティングでは、システムアカウンティングメトリックスのシステムへの追加や削除をシステムの解放時またはシステムの操作中に行うことができます。
拡張アカウンティングと古いシステムのアカウンティングソフトウェアの両方をシステム上で同時に起動できます。
exacct レコードを作成するルーチンは、次の 2 つの目的で使用できます。
サードパーティ製の exacct ファイルを作成できるようにする
putacct システムコールを使ってカーネルアカウンティングファイルに組み込まれるタグ付けレコードを作成できるようにする (getacct(2) 参照)
Perl インタフェースから putacct システムコールを利用することもできます。
この形式では、すべての変更を明示的なバージョン変更にしなくても、さまざまな形式のアカウンティングレコードを取得できます。アカウンティングデータを使用するアプリケーションは、認識不可能なレコードを無視するように作成する必要があります。
libexacct ライブラリは、ファイルを exacct 形式に変換し、exacct でファイルを作成します。このライブラリは、exacct 形式のファイルに対するインタフェースとしてサポートされている唯一のインタフェースです。
getacct、putacct、wracct の各システムコールは、フローには適用されません。 IPQoS フローアカウンティングの構成時には、カーネルによってフローレコードが作成され、ファイルに書き込まれます。
/etc/acctadm.conf ファイルには、現在の拡張アカウンティング構成が含まれます。このファイルは、ユーザーが直接編集するのではなく、acctadm インタフェースを介して編集します。
拡張アカウンティングデータは、デフォルトでは /var/adm/exacct ディレクトリに置かれます。acctadm(1M) コマンドを使用すると、プロセスやタスクのアカウンティングデータファイルの格納場所を変更できます。
| コマンド名 | 説明 | 
|---|---|
| acctadm(1M) | 拡張アカウンティング機能のさまざまな属性の変更、拡張アカウンティングの停止と起動を行う。また、プロセス、タスク、およびフローを追跡するためのアカウンティング属性を選択するのに使用する | 
| wracct(1M) | アクティブなプロセスおよびタスクの拡張アカウンティングアクティビティを書き込む | 
| lastcomm(1) | 直前に呼び出されたコマンドを表示する。lastcomm では、標準アカウンティングプロセスのデータまたは拡張アカウンティングプロセスのデータのどちらかを使用できる | 
タスクおよびプロジェクト関連のコマンドについては、プロジェクトとタスクの管理に使用するコマンドを参照してください。IPQoS フローアカウンティングについては、ipqosconf (1M) のマニュアルページを参照してください。
Perl インタフェースによって、exacct フレームワークで作成されたアカウンティングファイルを読み取ることのできる、Perl スクリプトを作成できます。exacct ファイルを書き出す Perl スクリプトも作成できます。
このインタフェースの機能は、基礎となる C 言語の API と同様です。可能な場合は、基礎となる C 言語の API から取得したデータを Perl データタイプとして表示します。この機能によって、データアクセスが容易になり、バッファのパック/アンパック操作が不要になります。さらに、あらゆるメモリー管理が Perl ライブラリによって実行されます。
各種のプロジェクト、タスク、exacct 関連機能はいくつかのグループに分けられます。各機能グループは、別々の Perl モジュールに配置されます。各モジュールは、サンの標準である Sun::Solaris:: Perl パッケージ接頭辞から始まります。Perl exacct ライブラリが提供するクラスはすべて、Sun::Solaris::Exacct モジュールの下にあります。
配下の libexacct(3LIB) ライブラリは、exacct 形式のファイル、カタログタグ、および exacct オブジェクトに対する操作を実行します。exacct オブジェクトは、次の 2 つのタイプに分けられます。
アイテム (単一データ値 [スカラー])
グループ (項目のリスト)
次の表に各モジュールの概要を示します。
| モジュール | 説明 | 参照先 | 
|---|---|---|
| Sun::Solaris::Project | このモジュールは、次のプロジェクト操作関数にアクセスする機能を提供する。getprojid(2)、endprojent(3PROJECT)、fgetprojent(3PROJECT)、getdefaultproj(3PROJECT)、getprojbyid(3PROJECT)、getprojbyname(3PROJECT)、getprojent(3PROJECT)、getprojidbyname(3PROJECT)、inproj(3PROJECT)、project_walk(3PROJECT)、setproject(3PROJECT)、および setprojent(3PROJECT) | Project(3PERL) | 
| Sun::Solaris::Task | このモジュールは、タスク操作関数である gettaskid(2) と settaskid(2) にアクセスする機能を提供する | Task(3PERL) | 
| Sun::Solaris::Exacct | 最上位レベルの exacct モジュール。このモジュールは、exacct 関連のシステムコールである getacct、putacct(2)、および wracct(2) にアクセスする機能を提供する。このモジュールは、libexacct(3LIB) ライブラリ関数である ea_error(3EXACCT) にアクセスする機能も提供する。exacct EO_*、EW_*、EXR_*、P_*、および TASK_* マクロのすべてに対応する定数も、このモジュールで提供される | Exacct(3PERL) | 
| Sun::Solaris::Exacct:: Catalog | このモジュールは、exacct カタログタグ内のビットフィールドにアクセスする、オブジェクト指向型メソッドを提供する。このモジュールによって、EXC_*、EXD_*、および EXD_* マクロの定数にもアクセスできる | Exacct::Catalog(3PERL) | 
| Sun::Solaris::Exacct:: File | このモジュールは、次の libexacct アカウンティングファイル関数にアクセスする、オブジェクト指向型メソッドを提供する。ea_open(3EXACCT)、ea_close(3EXACCT)、ea_get_creator(3EXACCT)、ea_get_hostname(3EXACCT)、ea_next_object(3EXACCT)、ea_previous_object(3EXACCT)、および ea_write_object(3EXACCT) | Exacct::File(3PERL) | 
| Sun::Solaris::Exacct:: Object | このモジュールは、個々の exacct アカウンティングファイルオブジェクトにアクセスする、オブジェクト指向型メソッドを提供する。exacct オブジェクトは、該当する Sun::Solaris::Exacct::Object サブクラスに与えられた、隠された参照として表される。このモジュールはさらに、アイテムかグループかのオブジェクトタイプに分けられる。 このレベルで、ea_match_object_catalog(3EXACCT) および ea_attach_to_object(3EXACCT) 関数にアクセスするメソッドがある | Exacct::Object(3PERL) | 
| Sun::Solaris::Exacct:: Object::Item | このモジュールは、独立した exacct アカウンティングファイルアイテムにアクセスする、オブジェクト指向型メソッドを提供する。このタイプのオブジェクトは、 Sun::Solaris::Exacct::Object から継承する。 | Exacct::Object::Item(3PERL) | 
| Sun::Solaris::Exacct:: Object::Group | このモジュールは、独立した exacct アカウンティングファイルグループにアクセスする、オブジェクト指向型メソッドを提供する。このタイプのオブジェクトは、 Sun::Solaris::Exacct::Object から継承する。これらのオブジェクトによって、ea_attach_to_group(3EXACCT) 関数にアクセスできる。グループ内のアイテムは Perl 配列として表される | Exacct::Object::Group(3PERL) | 
表で説明したモジュールの使用例については、libexacct に対する Perl インタフェースの使用 を参照してください。
タスク、プロセス、およびフローの拡張アカウンティング機能を起動するには、acctadm(1M) コマンドを使用します。 acctadm の最後に付けられたオプションのパラメータは、このコマンドが、拡張アカウンティング機能のプロセスアカウンティングコンポーネント、システムタスクアカウンティングコンポーネント、フローアカウンティングコンポーネントのいずれに作用するかを示します。
スーパーユーザーになります。
プロセスの拡張アカウンティングを起動します。
| # acctadm -e extended -f /var/adm/exacct/proc process | 
タスクの拡張アカウンティングを起動します。
| # acctadm -e extended,mstate -f /var/adm/exacct/task task | 
フローの拡張アカウンティングを起動します。
| # acctadm -e extended -f /var/adm/exacct/flow flow | 
/etc/init.d/acctadm スクリプトへのリンクを /etc/rc2.d に作成することにより、実行中に拡張アカウンティングを起動できます。
| # ln -s /etc/init.d/acctadm /etc/rc2.d/Snacctadm # ln -s /etc/init.d/acctadm /etc/rc2.d/Knacctadm | 
変数 n は番号で置き換えられます。
アカウンティング構成の詳細については、拡張アカウンティング構成を参照してください。
引数なしで acctadm と入力すると、拡張アカウンティング機能の現在の状態が表示されます。
| # acctadm
                 Task accounting: active
            Task accounting file: /var/adm/exacct/task
          Tracked task resources: extended
        Untracked task resources: none
              Process accounting: active
         Process accounting file: /var/adm/exacct/proc
       Tracked process resources: extended
     Untracked process resources: host,mstate
                 Flow accounting: active
            Flow accounting file: /var/adm/exacct/flow
          Tracked flow resources: extended
        Untracked flow resources: none | 
この例では、システムタスクアカウンティングが拡張モードと mstate モードで動作しています。プロセスアカウンティングとフローアカウンティングは、拡張モードで動作しています。
拡張アカウンティングの文脈では、マイクロステート (mstate) は、プロセス状態の微小な変化を反映した拡張データを意味し、このデータはプロセス使用状況ファイルで利用できます (proc(4) 参照)。このデータは、プロセスの活動に関して、基本レコードや拡張レコードよりも詳細な情報を提供します。
使用可能な資源は、システムやプラットフォームによってさまざまです。-r オプションを使用すると、システム上の使用可能なアカウンティング資源を表示できます。
| # acctadm -r process: extended pid,uid,gid,cpu,time,command,tty,projid,taskid,ancpid,wait-status,flag basic pid,uid,gid,cpu,time,command,tty,flag task: extended taskid,projid,cpu,time,host,mstate,anctaskid basic taskid,projid,cpu,timeprocess: extended pid,uid,gid,cpu,time,command,tty,projid,taskid,ancpid,wait-status,flag basic pid,uid,gid,cpu,time,command,tty,flag task: extended taskid,projid,cpu,time,host,mstate,anctaskid basic taskid,projid,cpu,time flow: extended saddr,daddr,sport,dport,proto,dsfield,nbytes,npkts,action,ctime,lseen,projid,uid basic saddr,daddr,sport,dport,proto,nbytes,npkts,action | 
プロセス、タスク、およびフローアカウンティングを停止するには、それぞれを個別にオフにします。
スーパーユーザーになります。
プロセスアカウンティングをオフにします。
| # acctadm -x process | 
タスクアカウンティングをオフにします。
| # acctadm -x task | 
フローアカウンティングをオフにします。
| # acctadm -x flow | 
タスクアカウンティング、プロセスアカウンティング、およびフローアカウンティングがオフになったことを確認します。
| 	# acctadm
            Task accounting: inactive
       Task accounting file: none
     Tracked task resources: extended
   Untracked task resources: none
         Process accounting: inactive
    Process accounting file: none
  Tracked process resources: extended
Untracked process resources: host,mstate
            Flow accounting: inactive
       Flow accounting file: none
     Tracked flow resources: extended
   Untracked flow resources: none | 
exacct オブジェクトの内容を再帰的に出力するには、次のコードを使用します。この機能は、ライブラリによって Sun::Solaris::Exacct::Object::dump() 関数として提供されています。ea_dump_object() という簡易関数でこの機能を利用することもできます。
| sub dump_object
     {
             my ($obj, $indent) = @_;
             my $istr = '  ' x $indent;
             #
             # Retrieve the catalog tag.  Because we are 
             # doing this in an array context, the
             # catalog tag will be returned as a (type, catalog, id) 
             # triplet, where each member of the triplet will behave as 
             # an integer or a string, depending on context.
             # If instead this next line provided a scalar context, e.g.
             #    my $cat  = $obj->catalog()->value();
             # then $cat would be set to the integer value of the 
             # catalog tag.
             #
             my @cat = $obj->catalog()->value();
             #
             # If the object is a plain item
             #
             if ($obj->type() == &EO_ITEM) {
                     #
                     # Note: The '%s' formats provide s string context, so
                     # the components of the catalog tag will be displayed
                     # as the symbolic values. If we changed the '%s'
                     # formats to '%d', the numeric value of the components
                     # would be displayed.
                     #
                     printf("%sITEM\n%s  Catalog = %s|%s|%s\n", 
                        $istr, $istr, @cat);
                     $indent++;
                     #
                     # Retrieve the value of the item.  If the item contains
                     # in turn a nested exacct object (i.e., an item or
                     # group),then the value method will return a reference
                     # to the appropriate sort of perl object
                     # (Exacct::Object::Item or Exacct::Object::Group).
                     # We could of course figure out that the item contained
                     # a nested item orgroup by examining the catalog tag in
                     # @cat and looking for a type of EXT_EXACCT_OBJECT or
                     # EXT_GROUP.
                     #
                     my $val = $obj->value();
                     if (ref($val)) {
                             # If it is a nested object, recurse to dump it.
                             dump_object($val, $indent);
                     } else {
                             # Otherwise it is just a 'plain' value, so
                             # display it.
                             printf("%s  Value = %s\n", $istr, $val);
                     }
             #
             # Otherwise we know we are dealing with a group.  Groups
             # represent contents as a perl list or array (depending on
             # context), so we can process the contents of the group
             # with a 'foreach' loop, which provides a list context.
             # In a list context the value method returns the content
             # of the group as a perl list, which is the quickest
             # mechanism, but doesn't allow the group to be modified.
             # If we wanted to modify the contents of the group we could
             # do so like this:
             #    my $grp = $obj->value();   # Returns an array reference
             #    $grp->[0] = $newitem;
             # but accessing the group elements this way is much slower.
             #
             } else {
                     printf("%sGROUP\n%s  Catalog = %s|%s|%s\n",
                         $istr, $istr, @cat);
                     $indent++;
                     # 'foreach' provides a list context.
                     foreach my $val ($obj->value()) {
                             dump_object($val, $indent);
                     }
                     printf("%sENDGROUP\n", $istr);
             }
     } | 
新しいグループレコードを作成して /tmp/exacct というファイルに書き込むには、次のスクリプトを使用します。
| #!/usr/perl5/5.6.1/bin/perl
use strict;
use warnings;
use Sun::Solaris::Exacct qw(:EXACCT_ALL);
# Prototype list of catalog tags and values.
     my @items = (
             [ &EXT_STRING | &EXC_DEFAULT | &EXD_CREATOR      => "me"       ],
             [ &EXT_UINT32 | &EXC_DEFAULT | &EXD_PROC_PID     => $$         ],
             [ &EXT_UINT32 | &EXC_DEFAULT | &EXD_PROC_UID     => $<         ],
             [ &EXT_UINT32 | &EXC_DEFAULT | &EXD_PROC_GID     => $(         ],
             [ &EXT_STRING | &EXC_DEFAULT | &EXD_PROC_COMMAND => "/bin/rec" ],
     );
     # Create a new group catalog object.
     my $cat = ea_new_catalog(&EXT_GROUP | &EXC_DEFAULT | &EXD_NONE)
     # Create a new Group object and retrieve its data array.
     my $group = ea_new_group($cat);
     my $ary = $group->value();
     # Push the new Items onto the Group array.
     foreach my $v (@items) {
             push(@$ary, ea_new_item(ea_new_catalog($v->[0]), $v->[1]));
     }
     # Open the exacct file, write the record & close.
     my $f = ea_new_file('/tmp/exacct', &O_RDWR | &O_CREAT | &O_TRUNC)
        || die("create /tmp/exacct failed: ", ea_error_str(), "\n");
     $f->write($group);
     $f = undef; | 
exacct ファイルの内容を出力するには、次の Perl スクリプトを使用します。
| #!/usr/perl5/5.6.1/bin/perl
     use strict;
     use warnings;
     use Sun::Solaris::Exacct qw(:EXACCT_ALL);
     die("Usage is dumpexacct <exacct file>\n") unless (@ARGV == 1);
     # Open the exact file and display the header information.
     my $ef = ea_new_file($ARGV[0], &O_RDONLY) || die(error_str());
     printf("Creator:  %s\n", $ef->creator());
     printf("Hostname: %s\n\n", $ef->hostname());
     # Dump the file contents
     while (my $obj = $ef->get()) {
             ea_dump_object($obj);
     }
     # Report any errors
     if (ea_error() != EXR_OK && ea_error() != EXR_EOF)  {
             printf("\nERROR: %s\n", ea_error_str());
             exit(1);
     }
     exit(0); | 
新しいグループレコードを作成してファイルに書き込む方法 で作成されたファイルに Sun::Solaris::Exacct::Object->dump() を実行した場合の出力例を示します。
| Creator:  root
Hostname: localhost
GROUP
       Catalog = EXT_GROUP|EXC_DEFAULT|EXD_NONE
       ITEM
         Catalog = EXT_STRING|EXC_DEFAULT|EXD_CREATOR
         Value = me
       ITEM
         Catalog = EXT_UINT32|EXC_DEFAULT|EXD_PROC_PID
         Value = 845523
       ITEM
         Catalog = EXT_UINT32|EXC_DEFAULT|EXD_PROC_UID
         Value = 37845
       ITEM
         Catalog = EXT_UINT32|EXC_DEFAULT|EXD_PROC_GID
         Value = 10
       ITEM
         Catalog = EXT_STRING|EXC_DEFAULT|EXD_PROC_COMMAND
         Value = /bin/rec
ENDGROUP |