利用 Oracle Solaris 11 中的服务管理工具 (SMF) 进行高级管理

作者:Glynn Foster

使用 SMF 执行高级管理任务,包括服务清单介绍、理解 SMF 配置信息库内的分层机制,以及如何以最佳方式将配置应用到系统。

2012 年 8 月发布

服务管理工具 (SMF) 最初是在 Oracle Solaris 10 中引入的,是用来管理系统和应用程序服务的一个操作系统特性,它取代了 Oracle Solaris 和其他 UNIX 操作系统早期版本中传统的 init 脚本启动机制。SMF 可确保重要的系统和应用程序服务即使在软硬件发生故障时也能不间断运行,从而提高了系统可用性。SMF 是使用更为广泛的 Oracle Solaris 预测性自我修复功能的组件之一。

OTN 旨在帮助您充分了解 Oracle 技术,以作出明智决策。本网站提供文章、软件下载、文档等。立即加入,获取完成工作所需的技术资源。

另一篇文章“Oracle Solaris 11 中的服务管理工具 (SMF) 基础知识简介”简要概述了 SMF,并列举了有关如何使用 SMF 管理系统的基本示例,包括如何获取有关正在运行的服务的信息、如何启动和停止服务的实例,以及如何进行基本的服务配置。其中还提供了一些故障排除技巧。如果您不熟悉 SMF,建议先阅读那篇文章。

本文介绍如何使用 SMF 进行一些更高级的管理任务,包括服务清单介绍、理解 SMF 配置信息库的分层机制,以及如何以最佳方式将配置应用到系统。要了解有关 SMF 的更多信息,请参见 Oracle 技术网的 SMF 技术页面上的各种内容。

探究服务包:清单和配置文件

SMF 的核心是服务包 的概念,这是一个基于 XML 的文件,用于描述有关服务或服务实例的一切信息(包括其配置),然后会导入到 SMF 配置信息库中。服务包用于将服务提供给 Oracle Solaris,此外,管理员还可利用它们在各种系统之间提供自定义配置。

SMF 中使用两种类型的服务包:清单和配置文件。这两者都基于 /usr/share/lib/xml/dtd/service_bundle.dtd.1 中的 XML DTD,请参见 service_bundle(4) 手册页面。

清单

清单用于描述服务和服务的实例,包括所有属性组及其可能有的属性。清单存储在 /lib/svc/manifest 中,自动导入到 SMF 信息库中。SMF 自动检测清单是否已发生更改,并确保 svc:/system/early-manifest-import:default 服务将该服务上线之前,这些更改已得到反映。管理员可以随时手动重新启动 svc:/system/manifest-import:default 服务来管理已放入已知位置(详见表 1)的服务清单和配置文件的导入,无需重新启动系统。

/lib/svc/manifest 目录细分为若干不同的目录,代表您列出系统上的服务时可看到的分类。例如,svc:/system/zones:default 服务实例是提供 /lib/svc/manifest/system/zones.xml 清单的结果,而 svc:/network/ssh:default 服务实例是提供 /lib/svc/manifest/network/ssh.xml 清单的结果。这些清单存储在与其服务类别对应的目录位置,仅仅是为了方便。它们的类别在清单本身内 <service> 元素的一个属性中指定,如下所示。

虽然可以直接操作供应商清单或其他第三方清单,但最好别那样做,因为系统更新时自定义项可能会丢失。希望创建自己的 SMF 清单的管理员应将它们提供到 /lib/svc/manifest/site

我们来看看示例清单,了解关键元素。我们将检查 SSH 服务器的清单,它位于 /lib/svc/manifest/network/ssh.xml

  • 有关服务的信息(名称、说明、文档链接)

    <service
            name='network/ssh'
            type='service'
            version='1'>
    
            <create_default_instance enabled='false' />
    
            <single_instance />
    	....
            <template>
                    <common_name>
                            <loctext xml:lang='C'>
                            SSH server
                            </loctext>
                    </common_name>
                    <documentation>
                            <manpage title='sshd' section='1M' manpath='/usr/share/man' />
                    </documentation>
            </template>
    

    在本例中,我们将指定该服务名为 network/ssh,它有一个被禁用的默认实例。我们还提供可本地化的服务说明,在本例中,所存在的文档的详细信息是 sshd (1M) 手册页。

  • 服务的依赖项

            <dependency name='fs-local'
                    grouping='require_all'
                    restart_on='none'
                    type='service'>
                    <service_fmri
                            value='svc:/system/filesystem/local' />
            </dependency>
    
            <dependency name='fs-autofs'
                    grouping='optional_all'
                    restart_on='none'
                    type='service'>
                    <service_fmri value='svc:/system/filesystem/autofs' />
            </dependency>
            ....
    

    在上面的代码中,我们指定了 network/ssh 的服务依赖项。在本例中,我们有一个必需的依赖项 system/filesystem/local 和一个可选依赖项 system/filesystem/autofs。在系统启动期间,SMF 将使用此信息按正确的顺序启动服务,如果可能,可以并行启动服务来优化启动过程。SSH 服务器共有 10 个服务依赖项。有关所有可能的依赖项类型和重新启动选项,请参见 smf(5) 手册页面。

  • 通过以下方法启动、停止和刷新默认的 svc.startd 或委托的重新启动器所使用的服务:

            <exec_method
                    type='method'
                    name='start'
                    exec='/lib/svc/method/sshd start'
                    timeout_seconds='60'/>
    
            <exec_method
                    type='method'
                    name='stop'
                    exec=':kill'
                    timeout_seconds='60' />
    
            <exec_method
                    type='method'
                    name='refresh'
                    exec='/lib/svc/method/sshd restart'
                    timeout_seconds='60' />
    

    对于 SSH 服务器,我们指定四种方法:startstoprefreshunconfigure。在本例中,我们将调用另一个脚本 /lib/svc/method/sshd,它在执行 /usr/lib/ssh/sshd 之前进行一系列检查(如确保已创建主机密钥)。

  • 服务的属性组和属性:

            <property_group name='general' type='framework'>
                    <!-- to start stop sshd -->
                    <propval name='action_authorization' type='astring'
                            value='solaris.smf.manage.ssh' />
            </property_group>
    
            <property_group name='firewall_context' type='com.sun,fw_definition'>
                    <propval name='name' type='astring' value='ssh' />
                    <propval name='ipf_method' type='astring'
                        value='/lib/svc/method/sshd ipfilter' />
            </property_group>
            ....
    

    在每个属性组内,我们都定义了若干属性。对于 SSH 服务器,我们在 general 属性组中添加一个新的 action_authorization 属性,它指示谁可以启动和停止服务 (solaris.smf.manage.ssh),我们还有一个 firewall_context 属性组,它帮助生成用于 IP 数据包过滤的防火墙规则。我们总共为 SSH 服务器定义了四个属性组。

配置文件

在很多方面,配置文件与清单类似,它们使用相同的 XML DTD。但是,配置文件提供的不是与服务、其依赖项以及方法有关的信息,而是服务或服务实例的自定义信息。自定义项包括应启用还是禁用服务的实例,以及对服务配置属性的所有修改。供应商提供的配置文件位于 /etc/svc/profiles,包含本地自定义项的配置信息应存储在 /etc/svc/profiles/site 中。系统或 svc:/system/manifest-import:default 服务实例重新启动时将应用配置文件。

作为配置文件的示例,我们来看一个配置文件,可以用它创建和启动 svc:/application/pkg/server 服务(允许我们在 Apache Web 服务器上托管 IPS 包信息库)的新实例:

# cat pkg-custom.xml
<?xml version="1.0" ?>
<!DOCTYPE service_bundle
  SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'>
<service_bundle type="profile" name="application/pkg/server">
    <service version="1" type="service" name="application/pkg/server">
        <instance enabled="true" name="default">
            <property_group type="application" name="pkg">
                <propval type="astring" name="inst_root"
                    value="/export/repository"/>
                <propval type="count" name="port" value="10000"/>
                <propval type="boolean" name="readonly" value="false"/>
            </property_group>
        </instance>
    </service>
</service_bundle>

清单 1. 配置文件示例

在清单 1 中,我们可以看到名为 default 的服务实例已启用,pkg/inst_rootpkg/proxypkg/readonly 属性的值已设定。接下来,只需将该文件复制到 /etc/svc/profile/site 中并重新启动 svc:/system/manifest-import:default

# cp pkg-custom.xml /etc/svc/profile/site
# svcadm restart manifest-import
# svcs pkg/server
STATE          STIME    FMRI
online         19:13:54 svc:/application/pkg/server:default

SMF 配置信息库的分层机制

我们已经了解了服务清单和配置文件,现在我们来看看 SMF 是如何管理配置的。Oracle Solaris 11 引入了层的概念,可以通过四个不同的层更好地跟踪供应商提供的自定义项和服务及服务实例的管理自定义项,如表 1 所示。

表 1. SMF 使用的层
说明
admin 直接通过命令行或运行应用程序所做的管理性更改
site-profile 通过在 /etc/svc/profile/site 中的 SMF 配置文件所做的管理性更改
system-profile 供应商通过 /etc/svc/profile/generic.xml/etc/svc/profile/platform.xml SMF 配置文件提供的配置
manifest 供应商通过 /lib/svc/manifests 中的 SMF 清单提供的配置

SMF 通过使用这些层和简单的优先级排序方案,可确保自定义项在系统更新期间不会被覆盖。admin 层优先级最高。如果某个属性在 admin 层未找到,将依次检查 site-profile 层、system-profile 层和 manifest 层。分层机制还让管理员能够查看可能在较高层被覆盖的较低层的配置。

例如,我们来看一下 svc:/system/identity:node 服务实例,它负责 nodename 系统配置(即系统的本地名称)的设置。我们使用 svcprop 命令快速查看它的值:

# svcprop -p config/nodename svc:/system/identity:node
solaris

如上所示,这个系统的名称是 solaris。现在让我们看看该值是在 SMF 信息库中的哪个地方设置的。我们可以使用如下所示的 svccfg listcust -L 命令列出 adminsite-profile 层的所有自定义项:

# svccfg -s svc:/system/identity:node listcust -L config/nodename
config/nodename astring     site-profile          solaris

我们可以看到 solaris 值来自 site-profile 层(它是 /etc/svc/profile/site/sc_profile.xml 中初始系统配置文件的一部分)。我们使用 svcprop 命令和 -l all 选项来跟踪各层的动态:

# svcprop -p config/nodename -l all svc:/system/identity:node
config/nodename astring manifest ""
config/nodename astring site-profile solaris

跟踪这四个不同的层时,我们可以看到 config/nodename 属性(astring 类型)的定义在 manifest 层提供,而 solaris 值在 site-profile 层设置。我们进一步使用交互式 svccfg 命令设置 config/nodename 属性,如下所示:

# svccfg
svc:> select identity:node
svc:/system/identity:node> listprop config/nodename
config/nodename astring     solaris
svc:/system/identity:node> setprop config/nodename=myserver
svc:/system/identity:node> listprop config/nodename
config/nodename astring     myserver

我们再来看看信息库的不同层:

# svcprop -p config/nodename -l all svc:/system/identity:node
config/nodename astring manifest ""
config/nodename astring site-profile solaris
config/nodename astring admin myserver

我们可以看到,信息库的每个层都会保存配置。即使我们将 config/nodename 属性更改为 myserversite-profile 层仍然存储了不同的值。只要对在任何阶段创建的自定义项不确定,我们都可以使用 listcust 命令:

svc:/system/identity:node> listcust config/nodename
config/nodename astring     admin                 myserver

要删除 admin 层的自定义项,我们可以使用 delcust 命令:

svc:/system/identity:node> delcust config/nodename
 Deleting customizations for property: config/nodename
svc:/system/identity:node> listcust config/nodename

管理员不能使用 SMF 命令在 admin 层以外的其他任何层更改配置。例如,如果我们尝试使用 delprop 命令删除某个属性,该属性将被所有层“屏蔽”。其实已从视图中删除了该属性,但为“撤消删除”功能存储了底层值。

svc:/system/identity:node> listcust config/nodename
config/nodename astring     admin                 myserver
svc:/system/identity:node> delprop config/nodename
svc:/system/identity:node> listprop config/nodename
svc:/system/identity:node> listcust config/nodename
config/nodename astring     admin          MASKED myserver
svc:/system/identity:node> listcust -l site-profile config/nodename
config/nodename astring     site-profile   MASKED solaris

我们可以看到,虽然 listprop 命令返回空值,但我们仍然可以看到在信息库的 admin 层创建并通过 site-profile 层提供的自定义项。这一屏蔽功能意味着管理员可以直接更改服务、服务的实例、属性组和属性,不会影响供应商提供的底层服务配置。

如果我们愿意,也可以对整个服务做同样的操作。我们以管理员想要删除 svc:/network/telnet 服务使其不被启动为例。一种方法是从系统删除 telnet 包,另一种方法是使用 svccfg delete 命令删除服务:

# svccfg delete network/telnet
# svcs network/telnet
svcs: Pattern 'network/telnet' doesn't match any instances
STATE          STIME    FMRI
# svccfg listcust -M | grep svc:/network/telnet
svc:/network/telnet system-profile MASKED
svc:/network/telnet:default system-profile MASKED

即使该服务表面上已从系统删除,但底层配置仍然存在于 system-profile 层。在本例中,由于该服务被屏蔽,所以该服务的所有实例也被屏蔽。我们可以使用 svccfg delcust 命令删除这些更改。如果我们要从系统彻底删除服务,包括它的配置,我们可以删除软件包,也可以手动删除清单和系统或站点配置文件中的所有引用,然后重新启动 svc:/system/manifest-import 服务。

应用服务配置

虽然可以采用一对一的方式管理系统,但就跨多个不同的机器应用服务配置而言,更好的方式是使用站点配置文件。SMF 能够从系统当前配置中提取配置文件。一旦您配置了一个符合您需求的系统,便可提取配置文件,并将其应用于数据中心的其他系统。

我们来提取系统(而不是个别服务)的当前状态,如果有必要,我们也可以通过在命令行中指定服务对各服务逐个执行类似操作。如清单 2 所示,我们可以使用 svccfg extract 命令获取一个配置文件。这个配置文件将列出在 adminsite-profile 层对系统的所有更改,包括标记为受保护的所有数据。我们需要将结果输出到一个扩展名为 .xml 的文件,以便应用于其他系统。

# svccfg extract -a > my-custom-profile.xml
# cat my-profile.xml
<?xml version='1.0'?>
<!DOCTYPE service_bundle SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'>
<service_bundle type='profile' name='extract'>
  <service name='application/font/fc-cache' type='service' version='0'>
    <create_default_instance enabled='true'/>
    <single_instance/>
  </service>
  <service name='application/cups/scheduler' type='service' version='0'>
    <create_default_instance enabled='true'/>
  </service>
  <service name='application/cups/in-lpd' type='service' version='0'>
    <create_default_instance enabled='false'/>
  </service>
  <service name='application/pkg/zones-proxyd' type='service' version='0'>
    <create_default_instance enabled='false'/>
    <single_instance/>
  </service>
  ....

清单 2. 提取系统的状态

虽然上述配置文件很多内容只是启用或禁用服务,但该配置文件还包含对属性组和属性的配置更改,如下面的代码段所示:

  <service name='network/dns/client' type='service' version='0'>
    <create_default_instance enabled='true'/>
    <single_instance/>
    <property_group name='config' type='application'>
      <propval name='nameserver' type='net_address' value='192.168.0.1'/>
    </property_group>
  </service>

当我们检查该配置文件并确保一切正常后,我们便可快速修改 <service> 的 XML 标记,如下所示:

<service_bundle type='profile' name='my-custom-profile'>

如果我们想要将此配置文件应用于某个系统,只需将它复制到目标系统上的 /etc/svc/profile/site,然后重新启动 svc:/system/manifest-import 服务。安装期间,该配置文件还可以包含在 IPS 软件包中,这样就能自动在多台机器上部署。

# cp my-custom-profile.xml /etc/svc/profile/site/
# svcadm restart manifest-import

总结

SMF 为管理 Oracle Solaris 11 系统服务和应用程序的管理员提供了许多好处,包括服务自动重新启动、统一的服务配置和与故障管理框架整合。与传统的 init 系统不同,管理员使用全面的服务依赖项检查和并行服务启动功能管理服务(而不是进程),这样做的好处是系统状态更一致、可管理性更强。通过使用 SMF 配置信息库和配置层,管理员可以在其数据中心轻松跨多个系统管理自定义项的配置文件和部署站点特定的服务。

另请参见

关于作者

Glynn Foster 是 Oracle Solaris 的首席产品经理,负责技术领域,包括映像包管理系统和服务管理工具。Glynn 是 2010 年随着 Oracle 收购 Sun Microsystems 而加入 Oracle 的。

修订版 1.0,2012 年 8 月 6 日

要了解所有 Oracle 技术中与系统管理员相关的内容,请在 FacebookTwitter 上关注 OTN Systems。