Solaris Subversion installation with SMF

Solaris no longer has the facility to start network demons by configuring /etc/inetd.conf so the steps usually outlined for automatically starting svnserver don't work. Instead, it is best to integrate Subversion into the Service Manaagament Facility (SMF).

My own installation has open source packages in the directory /opt/gnu for historical reasons (/usr/local is more usual). Take care to modify the highlighted parts of scripts as needed. This page is largely inspired by the work on Frédéric Schoenahl's Homepage.

1. Create start/restart/stop scripts

The first step is to create a start and stop script. These are similar to the scripts that would normally live in /etc/init.d. In this case create /lib/svc/method/subversion with the following content:

#!/bin/sh
. /lib/svc/share/smf_include.sh

LD_LIBRARY_PATH=/usr/sfw/lib:/usr/local/lib:/opt/gnu/lib
export LD_LIBRARY_PATH

SVNSERVE=/opt/gnu/bin/svnserve
SVNREPOS=/export/home/svn/repository

case "$1" in
  start)
    $SVNSERVE --daemon --root $SVNREPOS
    ;;

  stop)
    /usr/bin/pkill svnserve
    ;;

  *)
    echo "Usage: $0 {start|stop}"
    exit 1
    ;;

esac

If your svn binaries are in different locations (such as the more normal /usr/local or your repository is elsewhere then modify the highlighted sections to suit.

Set the script to be read and executable by all:

root: chmod 755 /lib/svc/method/subversion

You can test this script by running as the user that you intend to have run subversion. In this case the user svn:

svn: /lib/svc/method/subversion start svn: pgrep -l svnserve 27296 svnserve svn: /lib/svc/method/subversion stop svn: pgrep -l svnserve svn:

2. Create SMF definition file

The SMF file specifies the name of the service, it's dependancies, and how to run the start and stop scripts. In this case create /var/svc/manifest/network/subversion.xml with the following content:

<?xml version="1.0"?>
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<!--
    subversion daemon
-->

<service_bundle type='manifest' name='SMCsubv:subversion'>
    <service
	name='network/subversion'
	type='service'
	version='1'
    >

	<dependency name='loopback'
	    grouping='require_all'
	    restart_on='error'
	    type='service'
	>
	    <service_fmri value='svc:/network/loopback:default'/>
	</dependency>

	<dependency name='physical'
	    grouping='optional_all'
	    restart_on='error'
	    type='service'
	>
	    <service_fmri value='svc:/network/physical:default'/>
	</dependency> 
			  
	<exec_method
	    type='method'
	    name='start'
	    exec='/lib/svc/method/subversion start'
	    timeout_seconds='60'
	>
	    <!-- Specify the user and group to run the script as -->
	    <method_context>
		<method_credential user='svn' group='staff' />
	    </method_context>
	</exec_method>
			  
	<exec_method  
	    type='method'
	    name='stop'
	    exec='/lib/svc/method/subversion stop'
	    timeout_seconds='60'
	/>
			  
	<property_group name='startd' type='framework'>
	    <!-- sub-process core dumps shouldn't restart session -->
	    <propval name='ignore_error' type='astring' value='core,signal' />
	</property_group>
			   
	<instance name='default' enabled='false' />

	<stability value='Unstable' />
			  
	<template>    
	    <common_name>
		<loctext xml:lang='C'>
		    Subversion server
		</loctext>
	    </common_name>
	    <documentation>
		<manpage title='svnserve' section='5' manpath='/usr/local/man' />
		<doc_link name='Tigris.org' uri='http://subversion.tigris.org' />
	    </documentation>
	</template>
    </service>
</service_bundle>

The definition above specifies that the start command be run as the svn user and group staff. Adjust these lines as needed for your configuration. Next, verify the SMF file and import it.

root: svccfg verify /var/svc/manifest/network/subversion.xml root: svccfg import /var/svc/manifest/network/subversion.xml root: svcs -a | grep subversion disabled 14:53:21 svc:/network/subversion:default

3. Start the service

Now that SMF is aware of the service it can be started in the normal way using the svcadm command.

root: svcadm enable subversion root: svcs subversion STATE STIME FMRI enabled 14:59:15 svc:/network/subversion:default

If the state shows as "enabled" then the service should be running. If you get "maintenance" at this stage then several attempts have been made to start the service, and it has repeatedly failed. Time to read the next section...

4. Debug the service

The SMF system writes its log files to /var/svc/log. It's probably best to start tailing the subversion log file too see what has gone wrong.

root: tail -f /var/svc/log/network-subversion:default.log

Once you've addressed the problem you will need to clear the maintenace condition in order for the service to start up:

root: svcadm clear subversion

The log file should show the service being started. hopefully the start script should exit with status 0, meaning all is well.

You can get a list of the services that are not running using:

root: svcs -x

Other commands

Services can be enabled and disabled. The state is retained over reboots. Adding a -t switch after enable or disable makes the change temporary, and the original setting is restored on a reboot.

root: svcadm enable subversion root: svcadm disable subversion

Services can be restarted if they are "online":

root: svcadm restart subversion