smf_method - サービス管理フレームワークのメソッド規約
サービス管理フレームワーク smf(7) 内の svc.startd(8) によって管理されるサービスクラスは、単純な fork(2)-exec(2) モデルに適合するアプリケーションで構成されます。svc.startd(8) マスターデーモンやその他のリスタータは、fork(2)-exec(2) モデルを (場合によっては追加機能を使用して) サポートします。svc.startd(8) デーモンやその他のリスタータでは、サービスインスタンスをアクティブ化、操作、または検査するメソッドがこのマニュアルページで説明されている規約に従っている必要があります。
メソッド呼び出しの形式は規約で規定されていません。メソッドの呼び出しは、デーモンまたはサービスを提供するほかの実行可能バイナリの直接呼び出しの場合もあります。実行可能スクリプトなどの間接実行可能ファイルを使用する場合は、規約では次の形式が推奨されています。
/path/to/method_executable abbr_method_name
この推奨形式の abbr_method_name は、start や stop など、サポートされているメソッドです。リスタータでサポートされているメソッドセットについては、そのリスタータの関連ページで説明されています。svc.startd(8) デーモンは、start、stop、および refresh メソッドをサポートしています。
リスタータには、このページで説明するメソッドのほかにも各種のメソッドが定義されていることがあります。そのような拡張も含めた規約はリスタータによって定義され、ここで説明する規約とは異なる場合があります。
リスタータは、メソッド呼び出しのコンテキストを決定する 4 つの環境変数をメソッドに提供します。
メソッド呼び出しの対象であるインスタンスのサービス障害管理リソース識別子 (FMRI)。
呼び出されるメソッドの完全な名前。start や stop など。
メソッドを呼び出すリスタータのサービス FMRI。
メソッドが実行されているゾーンの名前。これは zonename(1) コマンドでも取得できます。
メソッドは終了しますが、管理者が即時に介入する必要のない問題がサービスインスタンスに発生していることを検出します。この終了コードは、サービスインスタンスが正常に停止しなかったことを示すために stop メソッドで使用することもでき、その stop メソッドはあとで再試行する必要があります。
メソッドで永続的プロセスを呼び出す場合は、その前にこれらの変数を環境から削除するようにしてください。サービスの作成者が Bourne 互換のシェルスクリプトを使用して後述のインクルードファイルにサービスメソッドを合成できるように、簡易シェル関数 smf_clear_env が用意されています。
後述のとおり、メソッドコンテキストによってほかの環境変数が設定されることもあります。
メソッドは、method タイプのプロパティーグループの 3 つのプロパティーで最小限定義されます。
これらのプロパティーは次のとおりです。
メソッドの実行可能ファイルの文字列。
メソッドがタイムアウトするまでの秒数。詳細については、「タイムアウト」のセクションを参照してください。
メソッドのタイプ。現在は常に method に設定されます。
メソッドコンテキストを定義して、メソッドの実行環境をより詳細に指定することもできます。詳細については、「メソッドコンテキスト」のセクションを参照してください。
リスタータ svc.startd によってメソッドの exec 文字列に一連のトークンが定義されている場合は、それらが解析され、適切な値で展開されます。ほかのリスタータはメソッドトークンをサポートしていない場合があります。inet サービス inetd(8) の委任リスタータは、次のメソッド拡張をサポートしていません。
%
リスタータの名前。svc.startd など。
呼び出されるメソッドの完全な名前。start や stop など。
サービスの名前
インスタンスの名前
インスタンスの FMRI
プロパティーの値。prop は、プロパティーの FMRI、プロパティーグループ名とプロパティー名を / で区切ったもの、または application プロパティーグループ内のプロパティー名です。これらの値のあとに , (コンマ) または : (コロン) が続く場合があります。ある場合、その区切り文字が複数の値を区切るために使用されます。ない場合は、スペースが使用されます。次に示すシェルのメタキャラクタが文字列値の中に見つかった場合は、\ (バックスラッシュ) でクォートされます。
; & ( ) | ^ < > newline space tab \ " '
展開が正しくないとメソッドの失敗を招きます。
メソッドコマンドの代わりに、2 つの明示的なトークンを使用できます。
指定されたシグナルをプライマリインスタンス契約のすべてのプロセスに送信します。デフォルトのシグナルは SIGTERM です。常に SMF_EXIT_OK を返します。このトークンは、一般的な pkill の呼び出しの代わりに使用するようにしてください。
常に SMF_EXIT_OK を返します。このトークンは、リスタータには必要であっても、特定のサービス実装には必要のないメソッドに使用するようにしてください。
start メソッドは、サービスインスタンスが要求に応答できる状態になるか、あるいは機能するまで、終了を遅らせる必要があります。
次の終了ステータスコードが <libscf.h> とシェルサポートファイルに定義されています。
|
上で説明した終了コードに加えて、メソッドでは次の終了コードを、smf_method_exit(3SCF)、smf_include.sh、および smf_include.py Python モジュールから使用可能な、smf_method_exit() と組み合わせて使用できます。
|
正確な終了コードを使用することで、担当のリスタータでエラー応答を診断して、再起動が適切と考えられる断続的なエラーと、管理者の操作を必要とする永続的なエラーとに分類できます。
メソッドごとに個別のタイムアウトを秒単位で指定できます。メソッドのタイムアウトは timeout_seconds プロパティーで指定されます。
タイムアウトは、メソッドがハングアップしているか、または進行していないことをサービスのリスタータが判断するための最後の手段として使用されます。タイムアウトが経過すると、多くのリスタータはそのサービスを保守状態にします。svc.startd(8) を参照してください。メソッドは進行しているが、メモリー、CPU、または I/O 負荷によってシステムの応答が一時的に非常に遅くなったときの早期エラーを避けるため、タイムアウトを指定する場合は誤差の範囲を大きくすることをお勧めします。
1 - 2 秒しかかからないと予想されるメソッドの場合、適切な開始値は 60 秒です。30 秒かかることが多いメソッドの場合は 300 秒 (5 分) が適切です。日常的に長い時間のかかるメソッドの場合は、必要に応じて値を大きくしてください。
管理者の介入を促すために早期エラーが必要な場合は、短いタイムアウトを使用できます。管理者の介入がサービスをクリアーしてメソッドを再度開始させるだけの可能性が高い場合は、長いタイムアウトを考慮します。
timeout_seconds が 0 に設定されている場合、そのサービスにはタイムアウトがありません。この設定は推奨されませんが、どうしてもそれを必要とするサービスには使用できます。-1 もタイムアウトがないことを指定するために受け入れられますが、非推奨です。
前述の終了ステータス値を定義する一連の環境変数が、/lib/svc/share/smf_include.sh ファイル内の簡易シェル関数で提供されます。このファイルは Bourne シェルスクリプトであり、任意の Bourne 互換シェルのソース演算子を介したインクルードに適しています。
SMF メソッドとして機能するスクリプトおよび /etc/init.d スクリプトの合成を容易にするために、smf_present() シェル関数が用意されています。smf(7) 機能を使用できない場合、smf_present() は 0 以外の終了ステータスを返します。
そのようなスクリプトの構造の例を次に示します。
if smf_present; then
# Shell code to run application as managed service
....
smf_clear_env
else
# Shell code to run application as /etc/init.d script
....
fi
この例では、用意されている両方の簡易関数の使用方法が示されています。
/lib/svc/share/smf_include.sh で提供されている終了ステータスと同じセットは、smf_include モジュールで使用できます。
サービス管理機能は、fork(2)-exec(2) モデルサービスが実行されるコンテキストを設定するための共通のメカニズムを提供します。
必要なメソッドコンテキストはサービス開発者が指定するようにしてください。すべてのサービスインスタンスは、最低レベルの特権と、セキュリティー侵害を抑えるのに必要な最低の認可上限で実行するようにしてください。
メソッドコンテキストには次のプロパティーを含めることができます。
メソッドの環境に挿入する環境変数を、いくつかの NAME=value 文字列で指定します。
RBAC (役割に基づくアクセス制御) プロファイルの名前。メソッドの実行可能ファイルとの組み合わせで、exec_attr(5) 内のエントリを識別します。
数値またはテキスト形式のオプションのユーザー ID。
数値またはテキスト形式のオプションのグループ ID。
補助グループメンバーシップを数値またはテキスト形式の ID で指定する、省略可能な文字列。
privileges(7) で定義されている特権セットを指定する、省略可能な文字列。拡張ポリシーはここで指定できます。
privileges(7) で定義されている制限特権セットを指定する、省略可能な文字列。
メソッドを起動するホームディレクトリ。トークンとして :home を使用すると、メソッドの起動に使用された uid に該当するユーザーのホームディレクトリを指定できます。このプロパティーが設定されていない場合は、:home が使用されます。
数値またはテキスト形式のプロジェクト ID。トークンとして :default を使用すると、メソッドの起動に使用された uid に該当するユーザーの、getdefaultproj(3PROJECT) で識別されるプロジェクトを指定できます。
メソッドを起動するリソースプールの名前。トークンとして :default を使用すると、上記の project 属性で示された project(5) エントリに指定されているプールを指定できます。
labels(7) に指定されているように、プロセスの認可上限を指定するオプションの文字列。この文字列は、ADMIN_LOW、ADMIN_HIGH、または atohexlabel(8) によって生成された 16 進文字列のいずれかである可能性があります。これを指定しない場合は、policy.conf(5) に指定されている認可上限でメソッドが開始されます。デフォルト値は ADMIN_HIGH です。
このサービスをトラステッドパス上で実行するかどうかを指定するオプションの文字列。詳細は、tpd(7) のマニュアルページを参照してください。デフォルトは false です。トラステッドパス上で実行されているサービスは、MWAC ポリシーから除外されます。詳細については、mwac(7) のマニュアルページを参照してください。
An optional boolean that specifies whether this service runs with the PPRIV_DEBUG process flag. Setting this true will result in details of any file access errors or missing required privileges being printed to the system messages file. These messages will describe the missing privilege and for file access, name the file to which access was denied.
サービスまたはインスタンスの method_context プロパティーグループを指定することにより、サービスインスタンス全体のメソッドコンテキストを設定できます。メソッドプロパティーグループのメソッドコンテキストプロパティーを指定することで、メソッドがインスタンスのメソッドコンテキストをオーバーライドする場合もあります。
メソッドコンテキストの設定が正しくないと、メソッドは常に失敗しますが、環境変数が無効な場合は警告が発行されます。
上記で定義されるコンテキストに加え、fork(2)-exec(2) モデルのリスタータは、実行可能ファイルをメソッドとして呼び出すときに次の規約も使用します。
argv[] 内の引数は、exec 文字列の /bin/sh -c の結果と一致するように設定されます。
ファイル記述子 0 は /dev/null です。ファイル記述子 1 と 2 は、サービスごとのログファイルに推奨されます。
終了ステータス値の定義。
終了ステータスコードの定義。
start メソッドでは、サービスログでサービス固有の構成エラーメッセージを報告するために smf_method_exit() を使用することもできます。
if [ ! -s "$my_config_file" ]; then
smf_method_exit $SMF_EXIT_ERR_CONFIG \
missing_or_empty_config_file \
"$my_config_file is missing or empty"
fi
使用例 2 非大域ゾーンで起動されたときに大域ゾーンでのみ実行されるべきサービスを無効にします。
大域ゾーンでのみ実行されるべきサービスは、非大域ゾーンで起動されたときに、自身を無効にすることもできます。
if smf_is_nonglobalzone; then
smf_method_exit $SMF_EXIT_TEMP_DISABLE global_zone_only \
"$SMF_FMRI is not supported in a local zone" SUNW_OST_OSCMD
fi
zonename(1)、exec(2)、fork(2)、getdefaultproj(3PROJECT)、smf_method_exit(3SCF)、exec_attr(5)、project(5)、service_bundle(5)、attributes(7)、mwac(7)、labels(7)、privileges(7)、rbac(7)、smf(7)、smf_bootstrap(7)、tpd(7)、zones(7)、atohexlabel(8)、coreadm(8)、inetd(8)、svc.startd(8)、svccfg(8)
smf(7) の現在のバージョンでは、複数のリポジトリはサポートされていません。
サービスが limit_privileges とは異なる特権で root ユーザーとして起動するように構成されている場合、結果として得られるプロセスは特権に対応したものになります。これは、seteuid(<non-zero UID>) によって特権が basic 以下に下がると考えている開発者には予期しないことです。