LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1026|回复: 0

OpenSolaris新特性解析之三:SMF

[复制链接]
发表于 2008-10-28 20:46:21 | 显示全部楼层 |阅读模式
http://bbs.chinaunix.net/viewthread.php?tid=1273723

前段时间比较忙,很久没有上chinaunix, 今天准备一次性把SMF这部分写完,要不然我感觉这个系列可能会中途而废了。

SMF的全称是service management facilit, 可以翻译成为是服务管理框架,是solaris新一代的进行服务管理的东东,目前在opensolaris里面SMF和传统的INIT机制还是并存的。虽然大部分的服务已经转化成为了SMF的模式,但是INIT的机制依然得到了保留,并且还有很少部分的服务是采用INIT的形式的,SUN采用这样的策略是考虑到了部分的软件厂商,因为这些软件厂商开发的应用程序如果是有部分注册成了服务的话,那么以前肯定是注册成了INIT的那种形式,为了让这部分程序在 opensolaris和solaris10上面还可以运行,所以INIT的方式依然得到了保留,不过在将来,opensolaris上的服务都会转到 SMF上去,INIT会彻底停止使用。

先简单说下用法,
#su                   转化成超级用户
#svcs               可以看到系统里面正在运行的服务,最后一列表明了服务的名字,例如svc:/system/fmd:default
#svcs -a          列出系统里面所有的服务,包括没有启动的
#svcs -x          查看服务的错误日志
#svcadm disable service-name   停止service-name这个服务,并在下次开机时也不运行它
#svcadm enable  service-name    启动service-name这个服务,并在下次开机时也运行它
#svcadm restart  service-name  重启service-name这个服务

大家如果熟悉REDHAT的话,很快就已经发现了SMF的用法和REDHAT下面的服务管理的用法几乎完全一样,不过他们只是形似,内部机制却相差很远,REDHAT目前所使用的还是传统的INIT的机制,下面是我个人认为的它们之间的区别。

区别1:我们知道在REDHAT/etc下面有rc1.d, rc2.d ....等等这样类似的目录,其他使用INIT机制的系统也会有这样的目录,比如几乎所有的LINUX,AIX等,这些目录下面放置了相关运行级别的服务列表,比如当系统进入运行级别3的时候,/etc/rc3.d下面的那些脚本都会被执行。这些服务都是编号的,名字一般为S1service1, S2service2等,1和2这样的数字决定了服务启动的顺序,数字小的先执行,大的后执行。好,问题来了,我们知道现在硬件都是多CPU,多核的,没有依赖关系的服务应该充分利用这些硬件资源并行启动。但是在INIT的这种模型下,服务的启动只能是按照数字编号顺序启动,就算某两个服务之间并没有依赖的关系。在SMF的模型下面改进了这一点,只要两个服务之间是没有依赖关系的,SMF将尽量安排它们平行启动。

区别2:在INIT下,服务如果出错是不能自动重启的,也就是说INIT下面的服务如果要自动启动只有在开机的时候可以。这样也会带来问题的,比如我们的程序在下面注册了个服务,是专门接受数据的,这个时候半夜三更的这个服务出错了,停止服务了,而用户的数据是不能丢失的,必须要持续接收,同志们只有半夜起来去趟机房或者是进行远程连接重起这个服务了。而SMF系统会自动的重起失败的服务。

区别3:对于那些出错而不能恢复的服务,处理方式不同。对于不能恢复的服务错误,在LINUX下面一般来说是需要重起整个操作系统的,如果单独杀掉这个出错的服务,系统不知道会有什么样的后果,因为服务之间是有依赖关系的。比较安全的方式是重起整个系统。在SMF下面,SMF存储了所有服务之间的依赖关系,它知道杀掉这个出错的服务会不会有其他的关键服务受到影响,如果没有,系统就会杀掉这个出错而不能恢复的服务。对于一些运行关键任务,不能停机的主机,这个特性是比较关键的。

图1是SMF的框架,repository.db存放了所有服务的属性的值,比如电源管理服务的timeout时间之类的,当服务启动的时候需要加载这些值。svc.configd这个后台进程用于维护这个属性数据库,所有的对这个数据库的读或者写的操作都要经过这个进程,这样的设计保证了这个数据库的完整性。svc.startd这个后台进程在开机的时候使用,它将读出需要启动的每一个服务的属性的值,然后用这些值去启动这些服务。SMF tools是SMF的一些维护工具如svcadm。

下面我将说明如果加入一个SMF服务,把以前的INIT的服务转换成SMF服务的方式也是一样的。

比如我们以前的服务是个应用程序,分为A和B两个部分,其中B依赖于A。我们需要先创建这两个服务的属性配置文件。在SMF下面所有的属性配置文件都是放在/var/svc/manifest下面的,大家可以看到下面有几个分类目录:application  device  milestone  network  platform  site  system。我们的服务是应用程序,所以我们先到application目录下面创建个目录ourapplication,在这个目录下我们再创建服务A的属性配置文件,内容如下,格式是xml类型的

<?xml version="1.0"?>
<!DOCTYPE service_bundle
  SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">  #必须要包含的文件,就好像C语言里面的头文件,里面有预定义

<service_bundle type='manifest' name='ourapplication:A'>
  <service
    name='application/ourapplication/A'                 #定义服务的名字
    type='service'
    version='1'>
    <create_default_instance enabled='false' />     
    <single_instance />

    <dependency
      name='multi-user-server'               
      grouping='optional_all'
      type='service'
      restart_on='none'>                                                                    
        <service_fmri value='svc:/milestone/multi-user-server' />  #这个服务属于哪个milestone
    </dependency>
    <exec_method
      type='method'
      name='start'
      exec='/lib/svc/method/ourapplication/A %m'          #启动这个服务需要启动的应用程序或脚本的路径
      timeout_seconds='60'>
      <method_context>
        <method_credential user='user' />
      </method_context>
    </exec_method>

    <exec_method
      type='method'
      name='restart'
      exec='/lib/svc/method/ourapplication/A %m'         #restart这个服务需要restart的应用程序或脚本的路径
      timeout_seconds='60'>
      <method_context>
        <method_credential user='user' />
      </method_context>
    </exec_method>

    <exec_method
      type='method'
      name='stop'
      exec='/lib/svc/method/ourapplication/A %m'          #stop这个服务需要stop的应用程序脚本的路径
      timeout_seconds='60' >
      <method_context>
        <method_credential user='user' />
      </method_context>
    </exec_method>

    <property_group name='startd' type='framework'>            
      <propval name='duration' type='astring' value='contract' />        #定义这个服务的类型
    </property_group>

   </service>
</service_bundle>


上面以#打头的部分是我的注释,大家自己写的时候需要把这些东东去掉。其中需要注意的是  /lib/svc/method/ourapplication/A 这个路径,我们看到start,stop, restart都是使用的这个脚本,熟悉INIT的朋友应该明白了,这个脚本就是在INIT里面的那个对应的脚本,我们这里只是把相应的参数如 start,restart,stop等传给它。

第二步,我们需要创建/lib/svc/method/ourapplication/A 这个脚本,它的写法和init中rcx.d下面脚本的写法一样,如果是把INIT下面的服务移植到SMF下面,我们的工作就是直接的拷贝。

第三步,我们需要把这个服务的属性文件导入到属性数据库中
# svccfg
svc:> validate /var/svc/manifest/application/ourapplication/a.xml
svc:> import /var/svc/manifest/application/ourapplication/a.xml
svc:> quit

第四步,激活
# svcadm enable svc:/application/ourapplication/a

这样就OK了,将B加入到SMF中的办法是一样的,唯一的区别是因为B依赖于A,所以在B的属性配置文件里面需要改动下面的东东
    <dependency
      name='ourapplication-server'
      grouping='optional_all'
      type='service'
      restart_on='none'>
        <service_fmri value='svc:/application/ourapplication/a' />
    </dependency>
在A里面是
   <dependency
      name='multi-user-server'               
      grouping='optional_all'
      type='service'
      restart_on='none'>                                                                    
        <service_fmri value='svc:/milestone/multi-user-server' />  
    </dependency>

大家对比一下就明白了。其他的步骤是完全一样的。

写道这里SMF这部分就基本上介绍完了。其他的更加具体的用法可以见附件servicemgmthowto。最后写一个列子是如果动态改变SMF服务中的属性的

#svccfg
svc:> select system/power #选择电源管理这个服务
svc:>listprop                      #让系统打印这个服务的属性的值
svc:>setprop stop/timeout_seconds=70   #修改timout这个属性的值为70
svc:>quit                                                  #直接推出

大家可以再用这个工具看看那个属性,可以看到已经改变了,并且这个服务会用这个新的值运行

[ 本帖最后由 niupigege 于 2008-9-22 17:12 编辑 ]

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表