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存储了所有服务之间的依赖关系,它知道杀掉这个出错的服务会不会有其他的关键服务受到影响,如果没有,系统就会杀掉这个出错而不能恢复的服务。对于一些运行关键任务,不能停机的主机,这个特性是比较关键的。

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类型的

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

name='application/ourapplication/A' #定义服务的名字

type='service'

version='1'>

name='multi-user-server'

grouping='optional_all'

type='service'

restart_on='none'>

#这个服务属于哪个milestone

type='method'

name='start'

exec='/lib/svc/method/ourapplication/A %m' #启动这个服务需要启动的应用程序或脚本的路径

timeout_seconds='60'>

type='method'

name='restart'

exec='/lib/svc/method/ourapplication/A %m' #restart这个服务需要restart的应用程序或脚本的路径

timeout_seconds='60'>

type='method'

name='stop'

exec='/lib/svc/method/ourapplication/A %m' #stop这个服务需要stop的应用程序脚本的路径

timeout_seconds='60' >

#定义这个服务的类型

上面以#打头的部分是我的注释,大家自己写的时候需要把这些东东去掉。 其中需要注意的是 /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的属性配置文件里面需要改动下面的东东

name='ourapplication-server'

grouping='optional_all'

type='service'

restart_on='none'>

在A里面是

name='multi-user-server'

grouping='optional_all'

type='service'

restart_on='none'>

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

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

#svccfg

svc:> select system/power #选择电源管理这个服务

svc:>listprop #让系统打印这个服务的属性的值

svc:>setprop stop/timeout_seconds=70 #修改timout这个属性的值为70

svc:>quit #直接推出

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