最近「記事
からSolaris用のパッケージを作成しています」という記事を読んで、SMF機能がHabrでまったくカバーされていないことに気付きました。
この状況を修正して、SMFとは何か、それが管理者に与える利点を見てみましょう。
はじめに
サービス管理機能(SMF)は、Solaris 10で導入されたサービス管理システムです。SMFを使用すると、プロセスをより柔軟に管理し、依存関係を割り当て、必要に応じて再起動できます。 これに加えて、SMFでは、ルート以外のユーザーにサービス管理権限を委任できます。
SMFを制御するには、次の3つのコマンドで十分です。
- svcs-サービスのステータスを確認し、
- svcadm-サービス状態管理、
- svccfg-サービス設定を構成します。
独自のサービスを追加する例を使用して、SMFを管理する方法を理解してみましょう。
最近、Solaris用のnginxが必要になりました。パッケージをコンパイルし、共通のサービスシステムに統合する必要がありました。その例を使用して、SMFを介した管理用にサービスを設計する方法を確認してください
サービスを追加する
サービスをSMFに統合するには、サービスのマニフェスト(依存関係、起動方法、およびその他のパラメーターの説明を含むXMLファイル)を記述する必要があります。 基本サービスの場合、これで十分です。より複雑なサービスの場合は、起動スクリプト(/etc/init.d/serviceに類似)も必要です。
SMFマニフェストコンテンツ
<?xml version = "1.0"?>
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<service_bundle type = 'manifest' name = 'nginx'>
<サービス
name = 'network / nginx'
タイプ= 'サービス'
バージョン= '1'>
<create_default_instance enabled = 'false' />
<single_instance />
<依存名= 'ループバック'
グループ化= 'require_all'
restart_on = 'エラー'
タイプ= 'サービス'>
<service_fmri値= 'svc:/ network / loopback:default' />
</ dependency>
<依存名= '物理的'
グループ化= 'optional_all'
restart_on = 'エラー'
タイプ= 'サービス'>
<service_fmri値= 'svc:/ network / physical:default' />
</ dependency>
<依存名= 'multiuser-server'
グループ化= 'require_all'
restart_on = 'エラー'
タイプ= 'サービス'>
<service_fmri値= 'svc:/ milestone / multi-user-server:default' />
</ dependency>
<exec_method
タイプ= 'メソッド'
名前= '開始'
exec = '/ opt / nginx / svc / nginx start'
timeout_seconds = '60 '/>
<exec_method
タイプ= 'メソッド'
名前= '停止'
exec = ':kill -QUIT'
timeout_seconds = '60 '/>
<exec_method
タイプ= 'メソッド'
name = 'refresh'
exec = '/ opt / nginx / svc / nginx refresh'
timeout_seconds = '60 '/>
<property_group name = 'nginx' type = 'application'>
<propval name = 'config' type = 'astring'
値= '/ opt / nginx / etc / nginx.conf' />
<propval name = 'pid' type = 'astring'
値= '/ opt / nginx / var / run / nginx.pid' />
</ property_group>
<property_group name = 'startd' type = 'framework'>
<!-サブプロセスのコアダンプは再起動しない
セッション->
<propval name = 'ignore_error' type = 'astring'
値= 'コア、シグナル' />
</ property_group>
<テンプレート>
<common_name>
<loctext xml:lang = 'C'>
Nginx httpサーバー
</ loctext>
</ common_name>
<ドキュメント>
<manpage title = 'nginx' section = '1M' />
<doc_link name = 'nginx.org'
uri = 'http://www.nginx.org/' />
</ドキュメント>
</ template>
</ service>
</ service_bundle>
順番に分析します。
- service_bundle-このファイルをSMFで処理する方法を示します。 タイプ「arhive」、「manifest」、「profile」の可能な値。 この場合、「マニフェスト」のみが考慮されます。 name属性は、サービスの名前を記録します。
- サービス -サービスインスタンスのセット(各サービスは構成が異なる複数のインスタンスを持つことができます)、依存関係、管理方法、および構成パラメーターを含みます。 名前、バージョン、およびタイプの属性には、それぞれ名前、バージョン、およびサービスのタイプが含まれます。 タイプは、「service」、「restarter」、「milestone」のいずれかです。
サービスの名前付け(属性名)には多くの規則があります。 それらは拘束力はありませんが、全体的な知覚を促進します。 スラッシュ(ネットワーク/ nginx)を介して名前に追加される標準カテゴリ(システム、アプリケーション、ネットワークなど)がいくつかあります。 たとえば、タイプの分離(アプリケーション/データベース/ mysql)など、いくつかのカテゴリも有効です。 - create_default_instanceおよびsingle_instanceは、サービスにはインスタンスが1つしかなく、オフ状態(enabled = 'false')で作成する必要があることを示しています。
- 依存関係 -サービスの依存関係を説明します。 すべての依存関係はタイプごとにグループ化されます(属性のグループ化)。 require_allグループのサービスは、サービスを開始するためにすべてオンラインである必要があります。 require_anyグループは説明されたサービスのいずれかを必要とし、exclude_allは指定されたすべてのサービスを除外し、optional_allは単純に(理解したように)、すべてのoptional_all依存関係の後にサービスを開始する必要があります。またはオフでした。
依存関係からのサービスの再起動のタイプは、restart_on属性によって定義され、次の値が含まれます。「エラー」-ハードウェアエラーのために依存関係が再起動した場合は再起動、「再起動」-何らかの理由(ハードウェアエラーを含む)で依存関係が再読み込みされた場合は再起動、「更新」 -依存関係が再起動または更新された場合は再起動します。 「none」の値は、依存関係の状態にかかわらず、サービスの再起動を禁止します。 - exec_method-サービスを管理するためのさまざまなメソッド。 サービスが有効(有効)、無効(無効)になり、サービスが再起動(再起動)されると、start / stopメソッドが呼び出されます。 refreshメソッドは、サービスが更新(更新)されるときに呼び出されます。
- property_group-サービスの構成パラメーターのセットを定義します。 タイプ「フレームワーク」はSMFパラメーターの構成を担当し、「アプリケーション」はサービス自体のパラメーターを担当します。 この場合、startd / ignore_errorパラメーターが渡されます。これにより、すべてのプロセスが終了して「andえ声」と「致命的な信号」を無視する場合にのみサービスを再起動する必要があることを再起動(英語版のリスターター)に説明します。 「アプリケーション」グループのパラメーターは、インスタンスの構成に使用されます。
- テンプレート -サービスに関するメタ情報を含むオプションのタグ。
ご覧のとおり、マニフェスト自体はサービスをかなり詳細に説明し、実際にはサービスの開始を担当する外部スクリプト/ opt / nginx / svc / nginxも参照しています。 今すぐ分析しましょう:
#!/ sbin / sh
#
。 /lib/svc/share/smf_include.sh
#SMF_FMRIは、ターゲットサービスの名前です。 これにより、複数のインスタンスが許可されます
#同じスクリプトを使用します。
if [-z $ SMF_FMRI]; それから
echo "SMFフレームワーク変数は初期化されていません。"
exit $ SMF_EXIT_ERR
fi
getproparg(){
val = `svcprop -p $ 1 $ SMF_FMRI`
[-n "$ val"] && echo $ val
}
NGINX_HOME = / opt / nginx
HTTPD = "$ {NGINX_HOME} / sbin / nginx"
CONF_FILE = `getproparg nginx / config`
PIDFILE = `getproparg nginx / pid`
if [-z $ CONF_FILE]; それから
echo "nginx / configプロパティが設定されていません"
exit $ SMF_EXIT_ERR_CONFIG
fi
if [-z $ PIDFILE]; それから
echo "nginx / pidプロパティが設定されていません"
exit $ SMF_EXIT_ERR_CONFIG
fi
[! -f $ {CONF_FILE}]; それから
echo "nginx / config:構成ファイルが見つかりませんでした"
exit $ SMF_EXIT_ERR_CONFIG
fi
ケース「$ 1」
開始)
$ HTTPD -t -c $ {CONF_FILE} 2>&1
[$? -ne 0]; それから
exit $ SMF_EXIT_ERR_CONFIG
fi
$ HTTPD -c $ {CONF_FILE} 2>&1
;;
更新)
if [-f "$ PIDFILE"]; それから
/ usr / bin / kill -HUP `/ usr / bin / cat $ PIDFILE`
fi
;;
停止)
if [-f "$ PIDFILE"]; それから
/ usr / bin / kill -KILL `/ usr / bin / cat $ PIDFILE`
fi
;;
*)
echo "使用法:$ 0 {start | stop | refresh}"
1番出口
;;
エサック
exit $ SMF_EXIT_OK
これは、いくつかのヘルパー関数を備えた通常のinit.dスクリプトです。 最初に、システム変数を含むファイルが含まれており、将来的に役立ちます。 それらの1つはSMF_FRMIです。これには、サービスの完全な名前が含まれています。 SMF_FRMIは、マニフェスト(getpropargヘルパー関数)から構成パラメーターを取得するために使用されます。 このアプローチの利点は、後で同じサービスの異なるインスタンスを検討するときに明らかになります。
ファイルの完全なセットができたので、システムから見えるようにします。
#svccfg -v import nginx.xml
svccfg:svc:/ network / nginx:の「初期」スナップショットを取る:デフォルト。
svccfg:svc:/ network / nginx:の「最後のインポート」スナップショットの取得:デフォルト。
svccfg:更新されたsvc:/ network / nginx:デフォルト。
svccfg:インポートに成功しました。
マニフェストに「デフォルトインスタンスの作成」と記述されているため、1つのデフォルトインスタンスを持つnetwork / nginxサービスがあります。 また、このインスタンスはオフ状態で作成する必要があります:
#svcs nginx
ステートスタイムFMRI
無効19:11:07 svc:/ network / nginx:デフォルト
管理コマンドで完全なFRMI(Eng。Fault Managed Resource Identifier)サービスを送信する必要はありません。名前(たとえば、nginx)だけで十分ですが、同じ名前の異なるカテゴリのサービスが複数ある場合は、完全な名前を指定する必要があります。 サービスに複数のインスタンスがある場合は、インスタンスも指定する必要があります(nginx:デフォルト)(FRMIが不完全な場合、svcsコマンドは比較されるすべてのサービスのステータスを表示します)。
無効状態のサービスは、OSの起動時に上昇しません。 したがって、有効にする必要があります。
#svcadm -v enable nginx
svc:/ network / nginx:デフォルトで有効。
サービスが実行されていることを確認します。
#svcs nginx
ステートスタイムFMRI
メンテナンス19:26:28 svc:/ network / nginx:デフォルト
失望は私たちを待っています-オンラインステータスの代わりにメンテナンスがあります。 メンテナンスステータスは、サービスの特定のエラーに対応しています。 SMFは、startメソッドがOK以外の値を返すか、サービスの停止に3回連続で失敗した場合、サービスをこの状態にします。 私たちのケースで何が原因になったのか見てみましょう。 これを行うには、サービスの展開状態を確認します。
#svcs -x nginx
svc:/ network / nginx:デフォルト(Nginx HTTPサーバー)
状態:2011年3月24日木曜日19:26:28以降のメンテナンス
理由:$ SMF_EXIT_ERR_CONFIGで開始メソッドが終了しました。
参照:http://sun.com/msg/SMF-8000-KS
参照:nginx(1M)
参照:/var/svc/log/network-nginx:default.log
影響:このサービスは実行されていません。
ご覧のとおり、展開されたステータスには、テンプレートマニフェストの説明も含まれています。 開始方法が失敗したことが示され、詳細を確認できるログが示されます。 ログには以下が表示されます。
[3月24日19:26:28有効。 ]
[3月24日19:26:28開始メソッドの実行( "/ opt / nginx / svc / nginx start")]
nginx / config:構成ファイルが見つかりませんでした
[3月24日19:26:28メソッド「start」がステータス96で終了しました]
起動スクリプトは、構成ファイルが見つからないと言っています。 はい、作成するのを忘れました。 ファイルを作成した後、サービスを再起動してみましょう。 メンテナンスステータスは有効/無効のサービスに影響しないことに注意してください-これは一時的な停止です。 したがって、サービスを「クリーン」するだけで、修正したことをシステムに伝えます。
#svcadm clear nginx
#svcs -x nginx
svc:/ network / nginx:デフォルト(Nginx HTTPサーバー)
状態:2011年3月24日(木)19:40:03以降のオンライン
参照:nginx(1M)
参照:/var/svc/log/network-nginx:default.log
影響:なし。
#ps -fe | grep nginx
ルート5864 1 0 19:40:04? 0:00 / opt / nginx / sbin / nginx -c /opt/nginx/etc/nginx.conf
誰も5865 5864 0 19:40:04? 0:00 / opt / nginx / sbin / nginx -c /opt/nginx/etc/nginx.conf
サービスが開始され、その機能が正常に実行されます。 この場合、次のログが記録されます。
[3月24日19:40:03クリアが要求されたためメンテナンスを終了します。 ]
[3月24日19:40:03有効。 ]
[3月24日19:40:03開始メソッドの実行(「/ opt / nginx / svc / nginxstart」)]
構成ファイルの/opt/nginx/etc/nginx.conf構文は問題ありません
設定ファイル/opt/nginx/etc/nginx.confテストが成功しました
[3月24日19:40:03メソッド「start」がステータス0で終了しました]
現在、サービスが予期せず停止した場合、SMFは(startd / ignore_errorパラメーターに従って)サービスを自動的に再起動します。 kill -9でこの状況を作成し、ログを確認します。
[3月24日19:42:25サービス中のすべてのプロセスが終了したため停止しています。 ]
[3月24日19:42:25停止メソッドの実行(:kill)]
[3月24日19:42:25開始メソッドの実行( "/ opt / nginx / svc / nginx start")]
構成ファイルの/opt/nginx/etc/nginx.conf構文は問題ありません
設定ファイル/opt/nginx/etc/nginx.confテストが成功しました
[3月24日19:42:25メソッド「start」がステータス0で終了しました]
追加機能
そのため、OSレベルでパフォーマンスが制御されるサービスがあります。 しかし、2つまたは3つの同一のサービス(たとえば、複数のpostgresqlサーバーまたは異なるタスクを備えたnginx)が必要な場合は、何のマニフェストを作成しますか? その場合の利点は何ですか?
ここでは、1つのサービスの複数のインスタンスを作成する機会を提供します。 これを行うには、マニフェストのcreate_default_instanceタグとsingle_serviceタグを削除し、明示的に独自のインスタンスを作成して、そこに一意のパラメーターを転送する必要があります。
<インスタンス名= 'default' enabled = 'false'>
<property_group name = 'nginx' type = 'application'>
<propval name = 'config' type = 'astring'
値= '/ opt / nginx / etc / nginx.conf' />
<propval name = 'pid' type = 'astring'
値= '/ opt / nginx / var / run / nginx.pid' />
</ property_group>
<property_group name = 'startd' type = 'framework'>
<!-サブプロセスのコアダンプは再起動しない
セッション->
<propval name = 'ignore_error' type = 'astring'
値= 'コア、シグナル' />
</ property_group>
</ instance>
インポートによってマニフェストをリロードする必要があります。 SMFは、何が変更されたかを判別します。
#svccfg -v import nginx.xml
svccfg:svc:/ network / nginx:の「前の」スナップショットを取得します:デフォルト。
svccfg:インスタンス「デフォルト」に従ってsvc:/ network / nginxのプロパティをアップグレードします。
svccfg:svc:/ network / nginx:プロパティグループ "nginx"を削除しています。
svccfg:svc:/ network / nginx:プロパティグループ「general」を削除しています。
svccfg:svc:/ network / nginx:プロパティグループ「startd」を削除しています。
svccfg:svc:/ network / nginx:の「最後のインポート」スナップショットの取得:デフォルト。
svccfg:更新されたsvc:/ network / nginx:デフォルト。
svccfg:インポートに成功しました。
その結果、複数のインスタンスを構成できるようになり、サービスの説明が同じになりました。 マニフェストで直接追加のインスタンスを指定できます。
<インスタンス名= 'monitoring' enabled = 'false'>
<property_group name = 'nginx' type = 'application'>
<propval name = 'config' type = 'astring'
値= '/ opt / nginx / etc / nginx-munin.conf' />
<propval name = 'pid' type = 'astring'
値= '/ opt / nginx / var / run / nginx-munin.pid' />
</ property_group>
<property_group name = 'startd' type = 'framework'>
<!-サブプロセスのコアダンプは再起動しない
セッション->
<propval name = 'ignore_error' type = 'astring'
値= 'コア、シグナル' />
</ property_group>
</ instance>
そしてインポート:
#svccfg -v import nginx.xml
svccfg:svc:/ network / nginx:の「前の」スナップショットを取得します:デフォルト。
svccfg:新しいサービスsvc:/ network / nginx:の「前の」スナップショットを取得しています。
svccfg:インスタンス「デフォルト」に従ってsvc:/ network / nginxのプロパティをアップグレードします。
svccfg:svc:/ network / nginx:監視の「初期」スナップショットを取得しています。
svccfg:svc:/ network / nginx:の「最後のインポート」スナップショットを取得しています。
svccfg:svc:/ network / nginx:の「最後のインポート」スナップショットの取得:デフォルト。
svccfg:更新されたsvc:/ network / nginx:モニタリング。
svccfg:更新されたsvc:/ network / nginx:デフォルト。
svccfg:インポートに成功しました。
これで、2つのサービスインスタンスができました(デフォルトのインスタンスは有効なままです)。
#svcs nginx
ステートスタイムFMRI
無効20:16:31 svc:/ network / nginx:監視
オンライン20:16:31 svc:/ network / nginx:デフォルト
ここで、サービスを開始するには、インスタンスを明示的に指定する必要があります。そうでない場合、システムは警告を表示します。
#svcadm enable nginx
svcadm:パターン 'nginx'は複数のインスタンスに一致します:
svc:/ network / nginx:監視
svc:/ network / nginx:デフォルト
#svcadm -v enable nginx:監視
svc:/ network / nginx:監視が有効になっています。
サービス設定を変更するsvccfgコマンドを使用して、マニフェストを編集せずにインスタンスを追加することもできます(ただし、マニフェストは複数のインスタンスに対して既に構成され、デフォルトを含む必要があります)。 大まかに言って、マニフェストをインポートした後、ソースファイルはSMFデータベースにインポートされるため、もはや役割を果たしません。 現在のサービス設定でマニフェストを取得するには、svccfg exportコマンドを使用できます。 オンザフライでインスタンスを追加すると、プロセスを自動化できます。
#svccfg -s nginx add phpfpm
#svccfg -s nginx:phpfpm addpg nginxアプリケーション
#svccfg -s nginx:phpfpm setprop nginx / config = astring:/opt/nginx/etc/fpm.conf
#svccfg -s nginx:phpfpm setprop nginx / pid = astring:/opt/nginx/run/fpm.pid
#svcadm disable nginx:phpfpm#これによりシステムプロパティが自動的に追加されます
#svcs nginx
ステートスタイムFMRI
無効20:37:30 svc:/ network / nginx:phpfpm
オンライン20:16:31 svc:/ network / nginx:デフォルト
オンライン20:21:09 svc:/ network / nginx:監視
rootユーザーからではなくサービスを開始する必要がある場合は、ここですべてが可能です。 追加するだけ
<method_context> <method_credential user = 'munin' group = 'munin' /> </ method_context>
インスタンスまたは別のメソッドの説明(別のユーザーからメソッドのみを実行する必要がある場合):
#ps -fe | grep nginx
munin 6254 1 0 21:10:52? 0:00 / opt / nginx / sbin / nginx -c /opt/nginx/etc/nginx-munin.conf
munin 6255 6254 0 21:10:52? 0:00 / opt / nginx / sbin / nginx -c /opt/nginx/etc/nginx-munin.conf
ルート5884 1 0 19:42:25? 0:00 / opt / nginx / sbin / nginx -c /opt/nginx/etc/nginx.conf
誰も6015 5884 0 21:05:04? 0:00 / opt / nginx / sbin / nginx -c /opt/nginx/etc/nginx.conf
同様の方法で、個々のプロジェクトでサービスを実行できます(プロジェクト-リソース制限)。 また、rootだけでなくサービスも管理できるようにしたい場合、SMFはSolaris RBACと統合されます!
ユーザーには、メソッド、依存関係、「アプリケーション」/「フレームワーク」グループのパラメーター、および特定のグループの権限を変更するための両方のグローバルロールを割り当てることができます。 各グループに対して、特別な属性(プロパティ値)modify_authorization、value_authorization、action_authorizationを割り当てて、操作に必要な「承認」を書き込むことができます。
- action_authorization-インスタンスの「一般」グループでのみ使用法を満たしました。 enabled属性はグループに保存され、この「承認」により、マニフェストにデータを書き込まずにサービスでアクションを実行できます。 例:更新、再起動、メンテナンスの設定/クリア
- value_authorization-グループの属性値を変更できますが、属性の追加/削除はできません。 この許可を一般グループに追加すると、ユーザーは有効な属性を変更できるようになるため、ユーザーはサービスの有効化/無効化を行うことができます。 この許可をnginxなどのグループに追加すると、ユーザーは構成ファイルへのパスを変更できます
- modify_authorization-グループ内の属性を変更、追加、削除できます。
例として、アクションの使用/サービス管理の承認の値を示します
最初に、ある種の「承認」をユーザーに追加します。簡単に説明しますが、承認を意味のある形で呼び出す必要があるという合意があります(たとえば、solaris.smf.manage.nginx / monitoring)。 (/ etc / security / auth_attrには多くの定義済みの承認もありますが、RBACは別の大きな記事の主題です):
#echo "solaris.munin ::: Munin認証::" >> / etc / security / auth_attr
#usermod -A solaris.munin munin
これまでのところ、サービスを設定しておらず、ユーザーは何もできません。
munin @ sol2 $ / usr / sbin / svcadm restart nginx:モニタリング
svcadm:svc:/ network / nginx:監視:許可が拒否されました。
munin @ sol2 $ / usr / sbin / svcadm disable nginx:モニタリング
svcadm:svc:/ network / nginx:監視:許可が拒否されました。
「承認」solaris.muninのサービスを再起動する機能を追加します。
#svccfg -s nginx:setprop general / action_authorization = astring:solaris.muninの監視
#svcadm refresh nginx:監視
(マニフェストの変更後、SMFが現在のサービスの構成を再読み取りできるように、更新サービスを実行する必要があります)
私たちはチェックします:
munin @ sol2 $ / usr / sbin / svcadm -v restart nginx:モニタリング
svc:/ network / nginx:監視用に設定されたアクション再起動。
munin @ sol2 $ / usr / sbin / svcadm -v nginxを無効にする:監視
svcadm:svc:/ network / nginx:監視:「一般」プロパティグループを変更できませんでした(許可は拒否されました)。
ユーザーがサービスを再起動できることは明らかですが、SMFデータベースのプロパティを変更することはできません。 このアプローチにより、ユーザーは構成ファイルを変更するときに「それらの」サービスを再ロードできます。 ユーザーにサービスを完全に停止する機会を与える必要がある場合、「一般」プロパティグループを変更する機会をユーザーに与えます。
#svccfg -s nginx:setprop generalの監視/ value_authorization = astring:solaris.munin
#svcadm refresh nginx:監視
私たちはチェックします:
munin @ sol2 $ / usr / sbin / svcadm -v nginxを無効にする:監視
svc:/ network / nginx:監視が無効です。
munin @ sol2 $ / usr / sbin / svcadm -v enable nginx:モニタリング
svc:/ network / nginx:監視が有効になっています。
上記の手法を使用すると、ユーザーの権利を柔軟に制限しながら、ユーザーにとって便利なシステムを作成できます。
この記事が誰かがSMFとは何かをよりよく理解するのに役立つこと、あるいはSMF、RBAC、およびSolarisのより深い理解を促すことさえ期待しています。