by Suzanne Zorn
Published May 2012
How to migrate script-based services from older Oracle Solaris releases and other UNIX environments, such as HP-UX 11i, to the Service Management Facility in Oracle Solaris 11.
This article describes how to migrate a service controlled via legacy
/etc/rc* scripts written for older Oracle solaris releases or other UNIX environments to the Service Management Facility (SMF) in Oracle Solaris 11.
Oracle Solaris 11 continues to allow legacy
/etc/rc* scripts to start and stop its services. However, since SMF makes it so much easier to monitor and manage system services, including providing failure detection, dependency checking, and automatic restart, it's well worth your while to transition control of those services to SMF.
Traditional scripts in the
/etc/rc* directories are used to start and stop services in many UNIX environments. The system looks in these directories when transitioning to run levels, finds scripts beginning with the letters S and K, and simply runs these scripts sequentially.
Administrators can add a custom script to these directories, but there are no management tools. Administrators are responsible for ensuring sequence numbers don't conflict and that any required services are available by previously executed scripts, and they must manually monitor and restart failed services.
SMF simplifies management and provides improved methods for controlling, monitoring, and managing services. Relationships between services can be defined, and services can be started only if the services upon which they depend are online. Instead of running scripts sequentially, SMF can start services in parallel, speeding system startup times.
SMF also contains an administrative interface to easily manage and control services, with configuration changes persisting across reboots. And, SMF monitors services and can be configured to automatically restart failed services, increasing the availability and reliability of services.
An SMF service has the following components associated with it:
/var/svc/logdirectory, and they can be looked up using the
svc:/network/rpc/bind:defaultcontains three parts separated by semi-colons:
svcidentifies it as a service.
/network/rpc/bindidentifies the service.
defaultidentifies the service instance (the first instance of a service is often tagged the default instance).
This document assumes you have a service that is currently started by
In this example, we start with an example service named
myservice. This service is purely an example used to illustrate SMF functionality. Our service runs the
prstat executable and is started using the following
#!/bin/sh if [ -x /usr/bin/prstat ]; then /usr/bin/prstat -a > /dev/null & fi exit 0
/etc/rc3.d/S* scripts are run in order whenever the system reboots or transitions into multi-user mode (run level 3). When our
S99myservice shell script runs, it starts the
prstat executable. We can confirm this by rebooting the system and then checking the running processes:
# ps -A | grep prstat 1595 console 0:00 prstat
To migrate any service to SMF control, you need three things:
Since our example service is currently being started by
/etc/rc* scripts, we already have the first two pieces: the executable (
/usr/bin/prstat) and the shell script to start the executable (
/etc/rc3.d/S99myservice). The one piece we need to create is the XML file.
The SMF manifest file is an XML file that describes our service to SMF, listing information such as the executable to run and any dependencies. The manifest file used for our example service is shown in Listing 1. A description of the key elements follows.
<?xml version="1.0"?> <!DOCTYPE service_bundle SYSTEM /usr/share/lib/xml/dtd/service_bundle.dtd.1"> <service_bundle type="manifest" name="myservice"> <service name="site/myservice" type="service" version="1"> <create_default_instance enabled="false" /> <!-- Dependencies --> <dependency name="filesystem-local" grouping="require_all" restart_on="restart" type="service"> <service_fmri value="svc:/system/filesystem/local:default" /> </dependency> <!-- Execution method for start and stop --> <exec_method type="method" name="start" exec="/lib/svc/method/myservice.sh" timeout_seconds="60" > <method_context> <method_credential user="root" group="root" /> </method_context> </exec_method> <exec_method type="method" name="stop" exec=":kill -9" timeout_seconds="60" > </exec_method> <template> <common_name> <loctext xml:lang="C">My example service</loctext> </common_name> <documentation> <manpage title="No man" section="99" manpath="/dev/null" /> </documentation> </template> </service> </service_bundle>
Listing 1. Manifest File for Our Example
Our manifest file contains the following elements:
<?xml version="1.0"?> <!DOCTYPE service_bundle SYSTEM /usr/share/lib/xml/dtd/service_bundle.dtd.1">
<service_bundle type="manifest" name="myservice">
/lib/svc/manifestand include application, milestone, platform, system, device, network, and site.) The name for our example,
site/myservice, indicates it is in the site category and is named
<service name="site/myservice" type="service" version="1">
defaultthat is disabled by default:
<create_default_instance enabled="false" />
restart_on=restartspecifies that our service should be restarted if the local file system service is restarted for any reason.
Other possible values include
none (never restart our service due to dependency state change),
error (restart our service if the dependency is restarted due to hardware fault), and
refresh (restart our service if the dependency is refreshed or restarted for any reason).
grouping=require_all attribute specifies that all services upon which our service depends must be online:
<dependency name="filesystem-local" grouping="require_all" restart_on="restart" type="service"> <service_fmri value="svc:/system/filesystem/local:default" /> </dependency>
<exec_method type="method" name="start" exec="/lib/svc/method/myservice.sh" timeout_seconds="60" > <method_context> <method_credential user="root" group="root" /> </method_context> </exec_method>
For our stop method, we tell SMF to execute the
kill command to stop our service:
<exec_method type="method" name="stop" exec=":kill -9" timeout_seconds="60" > </exec_method>
Note: Because our example created a single instance by default, we did not need to include explicit instance elements. If we wanted to start multiple instances of our service, we would need to include elements such as the following:
<instance name="myservice_instance1" enabled="false" />
Our example includes only a subset of the available SMF manifest features. The Oracle white paper "How to Create an Oracle Solaris Service Management Facility Manifest" (PDF) contains a more detailed description. The complete XML syntax is documented in the file
/usr/share/lib/xml/dtd/service_bundle.dtd.1 on Oracle Solaris 11 systems.
Before adding our service to SMF, we need to have a method to start the service executable. At a minimum, our startup script will need to start the service. It can also include options to stop and restart the service.
In this example, we can use our existing
/etc/rc3.d/S99myservice script and just add an SMF-specific exit code:
#!/bin/sh . /lib/svc/share/smf_include.sh if [ -x /usr/bin/prstat ]; then /usr/bin/prstat -a > /dev/null & fi exit $SMF_EXIT_OK
In general, you can use a single script that handles everything for a service, or you can create separate scripts for starting and stopping a service. And although most services use scripts, they aren't strictly required in all cases: If you can start, stop, or refresh with a single command, you can specify that command in the manifest and eliminate the script.
The following sections step through the procedure for migrating an example service from legacy
/etc/rc* scripts to SMF management.
This procedure assumes we have a service that currently uses the legacy
/etc/rc* scripts to automatically start. Our example uses the
svcscommand to see that our service has been started by Oracle Solaris 11 and the
prstatdaemon is running:
# ls /etc/rc3.d/S99myservice /etc/rc3.d/S99myservice # svcs S99myservice STATE STIME FMRI Legacy_run 11:41:19 lrc:/etc/rc3_3/S99myservice # ps -A | grep prstat 375 ? 0:00 prstat
prstat, in this example). Then, we need to remove or rename any related scripts in the
/etc/rc*directories so that Oracle Solaris 11 doesn't continue to automatically start our service every time we reboot the system, for example:
# pkill prstat # ps -A | grep prstat # # mv /etc/rc3.d/S99myservice /etc/rc3.d/_S99myservice
# ls -l /lib/svc/method/myservice.sh -rwxr-xr-x 1 root root 133 Mar 28 10:30 /lib/svc/method/myservice.sh
Note: Make sure your script has execute permissions and the appropriate user and group ownership.
# ls /lib/svc/manifest/site myservice.xml
svccfg validatecommand to check your manifest file for syntax errors. No output indicates that no errors were found:
# svccfg validate /lib/svc/manifest/site/myservice.xml #
svcadm restartcommand to let the SMF know about your new service:
# svcadm restart manifest-import Loading smf(5) service descriptions: 1/1
Note: The procedure for adding new services to SMF has changed from Oracle Solaris 10 to Solaris 11. In Oracle Solaris 11, it is recommended that manifests be stored in the standard locations of
/lib/svc/manifest being the preferred location. If your manifest is stored in a standard location in Oracle Solaris 11, it is no longer necessary (nor is it recommended) to use the
svcadm import command. Instead, the
svcadm restart command performs synchronization of the SMF repository and will recognize any changes to manifest files stored in the standard locations.
svcscommand to check on the status of the new service we added. SMF knows about our service, but it has not yet been enabled:
# svcs myservice STATE STIME FMRI disabled 10:54:08 svc:/site/myservice:default
# svcadm enable myservice # svcs myservice STATE STIME FMRI enabled 10:55:03 svc:/site/myservice:default
prstat) was started:
# ps -A | grep prstat 2135 ? 0:00 prstat
Once our service is under SMF control, we can use the
svcs command to monitor its operation.
svcscommand with the
-loption, specifying the service by name, as shown in Listing 2:
# svcs -l myservice fmri svc:/site/myservice/default name A simple example service enabled true state online next_state none state_time March 30, 2012 01:13:54 PM PDT logfile /var/svc/log/site-myservice:default.lot restarter svc:/system/svc/restarter:default contract_id 131 manifest /lib/svc/manifest/site/myservice.xml dependency require_all/none svc:/system/system/filesystem/local:default (online)
Listing 2. Viewing All Available Information for a Service
svcscommand with the
-xoption displays extra information about the service, which can be helpful when troubleshooting problems with a service:
# svcs -x myservice svc:/site/myservice:default (A simple example service) State: online since March 30, 2012 01:13:54 PM PDT See: man -M /dev/null -s 99 No man See: /var/svc/log/site-myservice:default.log Impact: None.
svcscommand with the
# svcs -p myservice STATE STIME Online 13:13:54 svc:/site/myservice:default 13:13:54 1321 prstat
We can also use the
svccfg setnotify command to modify notification parameters for events in the SMF repository, such as when a problem is diagnosed or resolved. For example, the default behavior is to send e-mail to
root@localhost when a problem is diagnosed for any SMF service. The following command modifies SMF to send an e-mail to
# svccfg setnotify problem-diagnosed mailto:email@example.com
You can set notification globally or per specific service, and you can also set notifications for SMF state transitions, such as degraded and offline. See the
svccfg(1M) man page for more details.
SMF monitors services and automatically restarts any executables that have failed, whether they failed because of administrator or configuration error, software fault, or uncorrectable hardware error. The following example demonstrates this automatic restart.
# ps -A | grep prstat 2135 ? 0:00 prstat
# kill -9 2135
# ps -A | grep prstat 2155 ? 0:00 prstat
prstat executable was stopped with the
kill command, but it was automatically restarted by SMF. (You can tell it's a different process because the process IDs, 2135 and 2155, are different.)
SMF maintains a log file for each service instance. These log files can be useful when troubleshooting a service. Log files are stored in the
/var/svc/log directory. The log file our example service is stored at is
Entries detail what start and stop methods are called and provide information about changes in service status. For example, the following log entries were created after executing the previous command to kill our service executable. SMF noticed the failure, called our stop method, and then called our start method to automatically restart our service:
# tail -4 /var/svc/log/site-myservice:default.log [ Mar 29 11:33:23 Stopping because all processes in service exited. ] [ Mar 29 11:33:23 Executing stop method (:kill). ] [ Mar 29 11:33:23 Executing start method ("/lib/svc/method/myservice.sh"). ] [ Mar 29 11:33:23 Method "start" exited with status 0. ]
This article showed how to migrate a service that was previously started using legacy
/etc/rc* scripts to SMF control. Our simple example was complete, but it's impossible to explore all features of SMF and describe all elements of the XML manifest file within the scope of this document. The "See Also" section provides links to more information on creating an SMF manifest file and managing services with SMF. It also provides links to online man pages that document the manifest file format and SMF-related commands.
The author would like to acknowledge Brian Down (Management of Systems and Services Made Simple with the Oracle Solaris Service Management Facility, June 2010) and Rob Romack (Service Management Facility in the Solaris 10 Operating System, February 2006) for their work, which was used as background for this article.
The following resources are available for the Oracle Solaris Service Management Facility:
The following man page entries contain information on SMF and the service manifest file format:
smf(5) man page
service_bundle(4) man page
And here are some Oracle Solaris 11 resources:
Suzanne Zorn has over 20 years of experience as a writer and editor of technical documentation for the computer industry. Previously, Suzanne worked as a consultant for Sun Microsystems' Professional Services division specializing in system configuration and planning. Suzanne has a BS in computer science and engineering from Bucknell University and an MS in computer science from Renssalaer Polytechnic Institute.
Revision 1.1, 04/28/2014
See sysadmin-related content for all Oracle technologies by following OTN Systems on Twitter.