SMF on illumos

From girlwiki
Revision as of 15:22, 19 February 2023 by Flurry (talk | contribs) (mention how you import this)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Maybe I just suck at finding docs, but SMF feels like a bit of a mess. It seems like Solaris users get some nice tools for creating manifests, but I'm guessing that's post-illumos fork. Refer to this PDF for more in-depth info.

This assumes you're using svc.startd(8) as your "restarter", which mainly affects the exec_method elements (AIUI). If you (like me) don't know what that means, this is likely the case.

<?xml version="1.0"?>
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<!-- name seems to be arbitrary. best to set it to the service name -->
<service_bundle type="manifest" name="service_name">
  <!--
    name is how you'll refer to the service in svcs/svcadm. I typically
    use "application/<service_name>", no idea if that's idiomatic or not.

    version must be an integer.
    -->
  <service name="scarlet/my_service" type="service" version="1">
    <!-- this sample service should only ever have one instance -->
    <single_instance />
    <!--
      if you want multiple instances, don't use that tag. instead, use:
      <create_default_instance enabled="(true|false)" />
      depending on whether you want application/my_service:default to exist.
      -->

    <!--
      say this service relies on networking and fs to function. if the
      relevant SMF services get refreshed (reconfigured) or restarted,
      we need to restart too. so we'll use restart_on='refresh' ('restart' is
      implied) and since we need all the services, grouping='require_all'.
      -->
    <!-- TODO: the DTD seems to imply multiple service_fmri tags work, but
         nobody seems to do this. is this ok? works fine for me so far -->
    <dependency name="net_fs" grouping="require_all" restart_on="refresh" type="service">
      <service_fmri value="svc:/milestone/network:default" />
      <service_fmri value="svc:/system/filesystem/local" />
    </dependency>

    <!-- You can also depend on stuff like files existing! -->
    <dependency name="config_file" grouping="require_all" restart_on="refresh" type="path">
      <service_fmri value="file://localhost/etc/serviced.conf" />
    </dependency>

    <!-- name should be 'start', 'refresh' (reconfigure), or 'stop'. -->
    <exec_method type="method"
        name="start"
        exec="/opt/local/bin/serviced --with-args "stuff""
        timeout_seconds="60">
      <method_context>
        <!-- you can add other groups with supp_groups (comma/space delim) -->
        <method_credential user='svcuser' group='svcgrp' />
        <method_environment>
          <envvar name="HOME" value="/var/lib/service" />
        </method_environment>
      </method_context>

      <!--
        not sure where it's documented, but ':kill' works to just kill
        the service PID.
        -->
      <exec_method type="method"
          name="stop"
          exec=":kill"
          timeout_methods="60" />

      <!-- svc.startd specific options -->
      <property_group name="startd" type="framework">
        <!-- 
          startd durations:
          - 'child': long-running foreground process
          - 'contract': "daemonizing" process (uses fork)
          - 'transient': similar to systemd's 'oneshot'
          -->
        <propval name="duration" type="astring" value="child" />
        <!-- don't restart on some errors -->
        <propval name="ignore_error" type="astring" value="core,signal" />
        <!-- 
          if you need a separate session for the service:
            <propval name="need_session" type="boolean" value="true" />
          
          there's also utmpx_prefix, but unless your service is *very*
          unix-y, you probably don't need this.
          -->
      </property_group>

      <template>
        <!-- locale-specific names for your service -->
        <common_name>
          <loctext xml:lang="C">Sample Service Daemon</loctext>
        </common_name>
        <!-- optional: link some docs -->
        <documentation>
          <manpage title="serviced" section="8" manpath="/opt/local/share/man" />
          <doc_link name="docs-home" uri="https://example.com/docs/" />
        </documentation>
      </template>
  </service>
</service_bundle>

Okay, but how do I use this?

That's the easy part! As root:

# svccfg import your-manifest.xml

You can now use it like every other service on your system. Use svcs my_service to see its status, svcadm (enable|disable|refresh|restart) my_service to do all of those relevant things, etc etc.