当然ながら、システムと詳細に対話できないかぎり、スクリプトはほとんど役立ちません。スクリプトがシステムと対話できるようにするための組み込み関数がいくつか存在します。
|
スクリプトがより大規模なシステムと対話するためのもっとも単純な方法は、「run」関数を使用することです。この関数は、実行するコマンドを受け取り、そのコマンドの出力を文字列として返します。次に例を示します。
dory:> configuration version script dump(run('get boot_time')) ' boot_time = 2009-10-12 07:02:17\n'
組み込みの dump 関数は、埋め込まれた復帰改行を展開することなく引数をダンプ出力します。この出力を分割するために、ECMAScript の文字列処理機能を使用できます。たとえば、空白に基づいて上の出力を分割すると、次のようになります。
dory:> configuration version script dump(run('get boot_time').split(/\s+/)) ['', 'boot_time', '=', '2009-10-12', '07:02:17', '']
run 関数は十分に強力であるため、システムに関する情報を取得するために、もっぱら出力の解析に頼りたくなることがあります。しかしこれには、将来変更されるかどうかわからない、人間が読める形式の出力をスクリプトがいつまでも解析し続けるという決定的な欠点があります。システムに関する情報をより安定して収集するには、組み込みの「get」関数を使用します。boot_time プロパティーの場合は、この関数によって文字列ではなく、ECMAScript の Date オブジェクトが返されるため、プログラムからプロパティー値を操作できます。たとえば、boot_time プロパティーを現在の時間と組み合わせて使用して、ブート時からの時間を特定することもできます。
script run('configuration version'); now = new Date(); uptime = (now.valueOf() - get('boot_time').valueOf()) / 1000; printf('up %d day%s, %d hour%s, %d minute%s, %d second%s\n', d = uptime / 86400, d < 1 || d >= 2 ? 's' : '', h = (uptime / 3600) % 24, h < 1 || h >= 2 ? 's': '', m = (uptime / 60) % 60, m < 1 || m >= 2 ? 's': '', s = uptime % 60, s < 1 || s >= 2 ? 's': '');
上のスクリプトを「uptime.aksh」として保存したとすると、それを次の方法で実行できます。
% ssh root@dory < uptime.aksh Pseudo-terminal will not be allocated because stdin is not a terminal. Password: up 2 days, 10 hours, 47 minutes, 48 seconds
仮想端末の割り当てに関するメッセージは、ssh クライアントによるものです。このメッセージが示す問題は、ssh に「-T」オプションを指定することによって対処できます。
動的な子が存在するコンテキストでは、これらの子をプログラムから繰り返し処理すると非常に有効です。これを行うには、動的な子の配列を返す list 関数を使用します。たとえば、すべてのプロジェクト内のすべてのシェアを繰り返し処理し、消費されている容量と空きスペースを出力するスクリプトを次に示します。
script run('shares'); projects = list(); for (i = 0; i < projects.length; i++) { run('select ' + projects[i]); shares = list(); for (j = 0; j < shares.length; j++) { run('select ' + shares[j]); printf("%s/%s %1.64g %1.64g\n", projects[i], shares[j], get('space_data'), get('space_available')); run('cd ..'); } run('cd ..'); }
このスクリプトが「space.aksh」という名前のファイルに保存されたと仮定して、スクリプトを実行した出力を次に示します。
% ssh root@koi < space.aksh Password: admin/accounts 18432 266617007104 admin/exports 18432 266617007104 admin/primary 18432 266617007104 admin/traffic 18432 266617007104 admin/workflow 18432 266617007104 aleventhal/hw_eng 18432 266617007104 bcantrill/analytx 1073964032 266617007104 bgregg/dashbd 18432 266617007104 bgregg/filesys01 26112 107374156288 bpijewski/access_ctrl 18432 266617007104 ...
この結果の「きれいに出力された」バージョン (ただし、プログラムの処理はより困難になる) がほしい場合は、get コマンドの出力を直接解析することもできます。
script run('shares'); projects = list(); printf('%-40s %-10s %-10s\n', 'SHARE', 'USED', 'AVAILABLE'); for (i = 0; i < projects.length; i++) { run('select ' + projects[i]); shares = list(); for (j = 0; j < shares.length; j++) { run('select ' + shares[j]); share = projects[i] + '/' + shares[j]; used = run('get space_data').split(/\s+/)[3]; avail = run('get space_available').split(/\s+/)[3]; printf('%-40s %-10s %-10s\n', share, used, avail); run('cd ..'); } run('cd ..'); }
このスクリプトが「prettyspace.aksh」という名前であると仮定して、この新しいスクリプトを実行した出力の一部を次に示します。
% ssh root@koi < prettyspace.aksh Password: SHARE USED AVAILABLE admin/accounts 18K 248G admin/exports 18K 248G admin/primary 18K 248G admin/traffic 18K 248G admin/workflow 18K 248G aleventhal/hw_eng 18K 248G bcantrill/analytx 1.00G 248G bgregg/dashbd 18K 248G bgregg/filesys01 25.5K 100G bpijewski/access_ctrl 18K 248G ...
静的な子が存在するコンテキストであっても、これらの子をプログラムから繰り返し処理すると有効です。これを行うには、静的な子の配列を返す children 関数を使用します。たとえば、すべてのサービスを繰り返し処理し、そのサービスのステータスを出力するスクリプトを次に示します。
configuration services script var svcs = children(); for (var i = 0; i < svcs.length; ++i) { run(svcs[i]); try { printf("%-10s %s\n", svcs[i], get('<status>')); } catch (err) { } run("done"); }
このスクリプトが「svcinfo.aksh」という名前のファイルに保存されたと仮定して、スクリプトを実行した出力を次に示します。
% ssh root@koi < space.aksh Password: cifs disabled dns online ftp disabled http disabled identity online idmap online ipmp online iscsi online ldap disabled ndmp online nfs online nis online ntp online scrk online sftp disabled smtp online snmp disabled ssh online tags online vscan disabled
choices 関数は、値のセットが知られていて列挙可能であるすべてのプロパティーの有効なプロパティー値の配列を返します。たとえば、次のスクリプトは、choices 関数を使用してシェアノード上のすべてのプールのリストを取得してから、すべてのプールを反復処理してプロジェクトのリストを作成し、使用可能な領域とともにシェアします。
fmt = '%-40s %-15s %-15s\n'; printf(fmt, 'SHARE', 'USED', 'AVAILABLE'); run('cd /'); run('shares'); pools = choices('pool'); for (p = 0; p < pools.length; p++) { set('pool', pools[p]); projects = list(); for (i = 0; i < projects.length; i++) { run('select ' + projects[i]); shares = list(); for (j = 0; j < shares.length; j++) { run('select ' + shares[j]); share = pools[p] + ':' + projects[i] + '/' + shares[j]; printf(fmt, share, get('space_data'), get('space_available')); run('cd ..'); } run('cd ..'); } }
これは、スクリプトを実行した出力です。
SHARE USED AVAILABLE pond:projectA/fs1 31744 566196178944 pond:projectA/fs2 31744 566196178944 pond:projectB/lun1 21474836480 587670999040 puddle:deptA/share1 238475 467539219283 puddle:deptB/share1 129564 467539219283 puddle:deptB/share2 19283747 467539219283