Solaris Filesystem Layout Tour: /etc, /var, /usr, /opt, /devices, /kernel and /platform

Solaris Admin Series, part 3. Previous: Solaris on SPARC vs x86: sun4u, sun4v, i86pc and What Differs. Related: part 1, Solaris 10 and 11.4 Releases, Support Lifecycle and Which to Run. Next up: /devices, /dev, device paths and instance numbers.

Before you touch disks, zones or packages on a Solaris box, it pays to know where things live. Solaris follows the classic SVR4 layout, but it has its own quirks: configuration in /etc that is partly generated, a kernel split across /kernel, /usr/kernel and /platform, a real device tree under /devices, and several directories that are not disk at all but memory or kernel pseudo filesystems. Solaris 11 then reshuffled a few things around ZFS boot environments. This post walks the tree top to bottom and shows the commands to explore it yourself.

Applies to: both Solaris 10 and Solaris 11 (11.4), on SPARC and x86. Where the two releases differ, it is called out in the text and in the comparison table near the end.

Prerequisites

  • Shell access to a Solaris 10 or Solaris 11.4 host; everything here is read-only and works as a normal user unless noted
  • Basic familiarity with ls, df and mount
  • Part 2 of the series for what uname -m and uname -i print, since /platform is organised by those values

The official map: man filesystem

Solaris ships its own description of the directory hierarchy. It is filesystem(5) on Solaris 10 and filesystem(7) on Solaris 11.4, which renumbered the miscellaneous man page sections. Read it once; it is the authoritative list of what belongs where.

$ man -s 5 filesystem      # Solaris 10
$ man filesystem           # Solaris 11.4 (section 7)

A quick look at the top level of a Solaris 11.4 system:

$ ls -l /
total 51
lrwxrwxrwx   1 root     root           9 Sep 14 10:02 bin -> ./usr/bin
drwxr-xr-x   5 root     sys            5 Sep 14 10:10 boot
drwxr-xr-x   5 root     sys            5 Oct 28 08:12 dev
drwxr-xr-x   4 root     sys           12 Oct 28 08:12 devices
drwxr-xr-x  88 root     sys          238 Oct 28 08:13 etc
drwxr-xr-x   3 root     sys            3 Sep 14 10:05 export
dr-xr-xr-x   2 root     root           2 Sep 14 10:02 home
drwxr-xr-x  18 root     sys           18 Sep 14 10:04 kernel
drwxr-xr-x  10 root     bin          272 Sep 14 10:05 lib
drwxr-xr-x   2 root     root           3 Sep 14 10:02 mnt
dr-xr-xr-x   2 root     root           2 Sep 14 10:02 net
drwxr-xr-x   8 root     sys            8 Sep 14 10:06 opt
drwxr-xr-x   4 root     sys            4 Sep 14 10:04 platform
dr-xr-xr-x 112 root     root      480032 Oct 28 14:02 proc
drwx------   4 root     root           8 Oct 27 16:40 root
drwxr-xr-x   4 root     root           4 Sep 14 10:10 rpool
drwxr-xr-x   2 root     sys           56 Sep 14 10:04 sbin
drwxr-xr-x   5 root     root           5 Sep 14 10:02 system
drwxrwxrwt   5 root     sys          376 Oct 28 14:00 tmp
drwxr-xr-x  30 root     sys           44 Sep 14 10:05 usr
drwxr-xr-x  44 root     sys           45 Sep 14 10:06 var

Your timestamps, link counts and the exact set of directories will differ. A Solaris 10 system looks similar but has no /rpool or /root unless you created them, and usually has /lost+found if root is on UFS.

Disk, memory and kernel: find out what each directory really is

Many top-level directories are separate mounts. Before reading anything else, ask the system what is mounted where. df -h shows disk-backed and memory-backed filesystems, and mount -p (or cat /etc/mnttab) shows every mount including the pseudo filesystems.

$ df -h
Filesystem             Size   Used  Available Capacity  Mounted on
rpool/ROOT/solaris      98G   4.1G        79G     5%    /
rpool/ROOT/solaris/var  98G   812M        79G     2%    /var
/devices                 0K     0K         0K     0%    /devices
/dev                     0K     0K         0K     0%    /dev
ctfs                     0K     0K         0K     0%    /system/contract
proc                     0K     0K         0K     0%    /proc
mnttab                   0K     0K         0K     0%    /etc/mnttab
swap                   7.2G   1.6M       7.2G     1%    /system/volatile
objfs                    0K     0K         0K     0%    /system/object
sharefs                  0K     0K         0K     0%    /etc/dfs/sharetab
fd                       0K     0K         0K     0%    /dev/fd
swap                   7.2G    48K       7.2G     1%    /tmp
rpool/VARSHARE          98G   2.3M        79G     1%    /var/share
rpool/export            98G    32K        79G     1%    /export
rpool/export/home       98G    32K        79G     1%    /export/home
rpool                   98G   5.1M        79G     1%    /rpool

$ mount -p | awk '{print $3, $4}' | sort -u -k2

That second command prints each mount point next to its filesystem type (zfs, ufs, tmpfs, proc, devfs, dev, ctfs, objfs, mntfs, fd, sharefs, lofs, autofs). On Solaris 10 with a UFS root, the first lines instead show slices such as /dev/dsk/c0t0d0s0 for / and often a separate /var slice.

PathFilesystem typeBacked byWhat it is
/, /usr, /varzfs (S11, S10 ZFS root) or ufs (S10)DiskThe installed OS
/tmptmpfsMemory and swapScratch space, emptied at every boot
/system/volatile (S11), /var/run (S10)tmpfsMemory and swapPID files, door files, runtime state
/procprocKernelOne directory per process; used by ps, pfiles, pstack
/devicesdevfsKernelThe physical device tree
/devdev (sdev)Kernel plus linksLogical device names that point into /devices
/etc/mnttabmntfsKernelThe live mount table, read-only
/system/contractctfsKernelProcess contracts that SMF uses to track services
/system/objectobjfsKernelLoaded kernel modules, used by DTrace and mdb
/dev/fdfdKernelOpen file descriptors of the current process
/etc/dfs/sharetabsharefsKernelThe current NFS/SMB share table
/net, /homeautofsAutomounterMount on demand from NIS/LDAP/local maps

/ and the bin, sbin and lib directories

On both releases /bin is a symbolic link to usr/bin, so /bin/ls and /usr/bin/ls are the same file. That has been true since Solaris 2.x, which is why /usr must be on the root filesystem or mounted very early.

$ ls -ld /bin
lrwxrwxrwx   1 root     root           9 Sep 14 10:02 /bin -> ./usr/bin
$ ls /sbin | head
  • /sbin holds a small set of programs needed before /usr is available, such as init, mount helpers and early-boot scripts. On Solaris 10 it also holds the legacy run-control scripts /sbin/rc0 to /sbin/rc6. Most admin commands live in /usr/sbin.
  • /lib holds the core shared libraries (libc.so.1, the runtime linker ld.so.1) and, since Solaris 10, the SMF method scripts in /lib/svc/method. 64-bit libraries are in /lib/64, a link to sparcv9 or amd64.
  • /usr/lib holds the remaining libraries and many daemons that are not on your PATH, for example /usr/lib/sendmail, /usr/lib/inet/inetd and /usr/lib/fm/fmd/fmd.

/usr: the read-mostly OS

/usr is the bulk of the installed operating system. It is meant to be shareable and read-mostly; nothing in it should change except when you patch or update.

DirectoryContentsNotes
/usr/binUser commandsDefault first entry on PATH on both releases
/usr/sbinAdmin commands: format, zpool, svcadm, ipadm, prtdiag
/usr/xpg4/bin, /usr/xpg6/binPOSIX/XPG-conforming versions of commands such as grep, awk, shOn Solaris 10, /usr/xpg4/bin/grep supports -E, -F and -q; the default /usr/bin/grep did not
/usr/ucbBSD compatibility commands (ps auxww, old echo)Standard on Solaris 10; on 11 it comes from the compatibility/ucb package and may not be installed
/usr/sfwSolaris 10 bundled open-source software (Apache, Samba, GCC)Gone on Solaris 11; those packages install into /usr/bin, /usr/lib or /usr/apache2
/usr/gnu/binGNU versions of tools (grep, tar, sed)Solaris 11; check where it sits on your PATH with echo $PATH
/usr/share/manMan pages
/usr/kernelKernel modules that are not needed at bootSee the kernel section below
/usr/lib/fm, /usr/lib/inetFault manager, network daemons

A common trap when moving between releases is a script that relies on GNU or XPG behaviour. Check exactly which binary you are getting:

$ which grep
/usr/bin/grep
$ ls -l /usr/bin/grep /usr/xpg4/bin/grep /usr/gnu/bin/grep 2>/dev/null

There is no /usr/local out of the box. Third-party and in-house software traditionally goes in /opt.

/etc: host-specific configuration

/etc holds configuration that is specific to this host. On Solaris 10 nearly everything was a flat file. On Solaris 11, many settings moved into the SMF repository and network configuration databases, and some files in /etc are now generated from SMF properties, so editing them directly gets overwritten.

File or directoryPurposeSolaris 10Solaris 11.4
/etc/releaseOS release bannerYesYes (use pkg info entire for the SRU)
/etc/systemKernel tunables read at bootEdit the filePrefer drop-in files in /etc/system.d/
/etc/vfstabFilesystems mounted at bootUFS, swap and NFS entriesMainly swap and NFS; ZFS mounts itself
/etc/mnttabCurrent mountsmntfs, read-onlySame
/etc/hostsHost tableLink to inet/hostsSame
/etc/nsswitch.confName service orderEdit the fileGenerated from svc:/system/name-service/switch; set with svccfg
/etc/resolv.confDNS clientEdit the fileGenerated from svc:/network/dns/client
/etc/hostname.*, /etc/defaultrouterInterface and route configYesNot used; use ipadm, dladm and route -p
/etc/default/Defaults for login, passwd, su, init (time zone on S10)YesYes; time zone is an SMF property of svc:/system/timezone
/etc/svc/SMF repository (repository.db) and volatile stateYesYes
/etc/dfs/dfstabNFS shares at bootYesReplaced by share and ZFS share.nfs properties
/etc/path_to_inst, /etc/name_to_major, /etc/driver_aliasesDevice instance numbers and driver bindingsYesYes (next post)
/etc/user_attr, /etc/security/RBAC and security policyYesYes, plus .d drop-in directories
/etc/rc*.d, /etc/init.dLegacy run-control scriptsYes, run as SMF legacy servicesStill present, few scripts

To see which Solaris 11 files are SMF-generated, check the property instead of the file:

# svccfg -s svc:/system/name-service/switch listprop config/host
config/host  astring  "files dns"
# svccfg -s svc:/network/dns/client listprop config/nameserver
config/nameserver  net_address  192.0.2.53

Values shown are examples. Change them with svccfg -s ... setprop followed by svcadm refresh; SMF gets its own block of posts later in the series.

/var: logs, spools, package data and crash dumps

/var is everything that grows. On Solaris 11 it is its own ZFS dataset inside each boot environment (rpool/ROOT/solaris/var), and a second dataset, rpool/VARSHARE mounted at /var/share, holds data that should be shared across boot environments rather than copied into each one. Several familiar paths, such as /var/mail and /var/crash, are symbolic links into /var/share.

$ ls -l /var | grep -- '->'
$ zfs list -r -o name,mountpoint rpool/VARSHARE
DirectoryWhat you find there
/var/adm/messagesMain syslog file; rotated to messages.0, .1… by logadm
/var/adm/Also wtmpx, utmpx, sulog, lastlog, sa/ for sar data
/var/svc/log/One log per SMF service instance, for example network-ssh:default.log
/var/fm/fmd/Fault manager error and fault logs, read with fmdump
/var/crash/Kernel crash dumps saved by savecore; check with dumpadm
/var/cores/Process core files when coreadm is configured to put them there
/var/sadm/Solaris 10 package and patch database: /var/sadm/pkg, /var/sadm/install/contents, /var/sadm/patch. On Solaris 11 it still holds SVR4 package data for any SVR4 packages you add
/var/pkg/Solaris 11 IPS image metadata and download cache. Do not edit or delete by hand
/var/spool/Print queues, cron crontabs (/var/spool/cron/crontabs), mail queue (clientmqueue, mqueue)
/var/tmp/Scratch space that survives reboots, unlike /tmp
/var/audit/Audit trail when auditing is enabled
/var/runRuntime state; a tmpfs on Solaris 10 and a link to /system/volatile on Solaris 11

To find what is filling /var, the usual suspects are crash dumps, old messages files, core files and, on Solaris 10, the patch backout data under /var/sadm/pkg/*/save:

# du -sk /var/* 2>/dev/null | sort -n | tail -5
4012      /var/svc
22840     /var/adm
101356    /var/sadm
350112    /var/pkg
1876544   /var/crash

/opt and /export

  • /opt is for unbundled and third-party software, each in its own subdirectory such as /opt/SUNWexplo (Oracle Explorer), /opt/developerstudio12.6 or /opt/myapp. SVR4 packages default to installing under /opt/<pkg>.
  • /export is where locally hosted data that may be shared over NFS goes. By convention user homes live in /export/home/<user> and are reached through /home/<user>, which the automounter maps using auto_home. On Solaris 11 useradd -m creates each home as its own ZFS dataset under rpool/export/home.
  • /home is therefore an autofs mount point. You cannot mkdir in it while the automounter is running; that surprise trips up almost everyone coming from Linux.
$ grep home /etc/auto_master
/home           auto_home       -nobrowse
$ cat /etc/auto_home
+auto_home
*       localhost:/export/home/&

The * wildcard entry shown is the Solaris 11 default; on Solaris 10 you often add it yourself or list users individually.

/devices and /dev

/devices is the kernel’s physical device tree, with names that follow the hardware path, for example /devices/pci@400/pci@1/scsi@0/sd@0,0:a. /dev holds the friendly logical names admins actually use, such as /dev/dsk/c0t0d0s0 and /dev/rdsk/c0t0d0s0 (block and raw), which are symbolic links into /devices. Solaris 11 also has /dev/net with vanity datalink names like net0.

$ ls -l /dev/dsk/c1t0d0s0
lrwxrwxrwx   1 root     root  51 Sep 14 10:02 /dev/dsk/c1t0d0s0 -> ../../devices/pci@0,0/pci15ad,1976@10/sd@0,0:a

The next post in the series covers this pair in depth, including instance numbers, /etc/path_to_inst and how to clean up stale links with devfsadm -C.

/kernel, /usr/kernel and /platform

The Solaris kernel is not one file. It is a small core (unix plus genunix) and hundreds of loadable modules spread over several directories. The kernel searches them in a fixed order, given by the moddir path:

/platform/`uname -i`/kernel     # this exact hardware model (implementation)
/platform/`uname -m`/kernel     # this machine class, e.g. sun4v or i86pc
/kernel                         # platform-independent modules needed at boot
/usr/kernel                     # platform-independent modules not needed at boot
$ uname -m; uname -i
sun4v
ORCL,SPARC-T8-1
$ ls /platform
ORCL,SPARC-T8-1  sun4v
$ ls /platform/sun4v/kernel
cpu  crypto  drv  misc  sparcv9  ...

Inside each kernel directory the layout is the same: drv for device drivers and their .conf files, fs for filesystem modules, misc, strmod, sys for system calls, sched for scheduling classes, and so on, with the 64-bit binaries in a sparcv9 or amd64 subdirectory. Driver configuration files (for example sd.conf) live in /kernel/drv on Solaris 10. On Solaris 11.4 you should put local changes in /etc/driver/drv/ instead, so package updates do not overwrite them.

The kernel image you booted and the loaded modules are easy to check:

$ isainfo -kv
64-bit sparcv9 kernel modules
$ modinfo | head -4
 Id Loadaddr   Size Info Rev Module Name
  0  1000000  ...   -    0  unix ()
  1  10a2b50  ...   -    0  genunix ()
  2  1214c00  ...   -    0  dtrace (Dynamic Tracing)

/platform also holds the boot archive, the RAM disk image the boot loader reads before the root filesystem is mounted (for example /platform/sun4v/boot_archive, or /platform/i86pc/amd64/boot_archive on x86 Solaris 11). It must match the files in the OS; bootadm update-archive rebuilds it and bootadm list-archive shows what goes into it.

# bootadm list-archive | head -5
etc/cluster/nodeid
etc/dacf.conf
etc/driver
etc/mach
etc/name_to_major

On x86, /boot holds the GRUB files (legacy GRUB menu.lst under the pool or /boot/grub on Solaris 10; GRUB2 configuration managed by bootadm on Solaris 11). SPARC systems boot from OBP and have little in /boot.

/proc, /system and other pseudo filesystems

  • /proc/<pid> exposes each process to tools such as pfiles, pmap, pstack, pargs and ptree. Unlike Linux, Solaris /proc contains binary structures, not text, so use the p* tools rather than cat.
  • /system/contract (ctfs) is how SMF knows every process that belongs to a service; ctstat and svcs -p read it.
  • /system/object (objfs) exposes kernel module symbol data for debuggers and DTrace.
  • /system/volatile on Solaris 11 replaces the old /var/run tmpfs, and /var/run now points to it. It is cleared at every boot.
  • /tmp is tmpfs, so files there consume RAM and swap. A runaway job that writes to /tmp can push a Solaris box into heavy paging. Cap it with a size= mount option in /etc/vfstab if needed.
$ ptree $$
612   /usr/lib/ssh/sshd
  4120  /usr/lib/ssh/sshd
    4122  -bash
      4188  ptree 4122
$ grep tmp /etc/vfstab
swap    -       /tmp    tmpfs   -       yes     size=2g

The size=2g option is an example of a cap you might add; the default line has - in that field.

Root’s home, /rpool and boot environments (Solaris 11)

  • On Solaris 10, root’s home directory is /, so dot files end up in the root of the filesystem. On Solaris 11, root is a role whose home is /root, a separate ZFS dataset.
  • /rpool is just the mount point of the top-level dataset of the root pool. It is not where the OS lives.
  • The OS itself is a boot environment (BE), a ZFS dataset under rpool/ROOT, for example rpool/ROOT/solaris or rpool/ROOT/solaris-12 after an SRU update. / and /var come from the active BE; /export, /var/share and /root‘s data are shared across BEs.
$ beadm list
BE          Flags Mountpoint Space  Policy Created
--          ----- ---------- -----  ------ -------
solaris     -     -          12.9M  static 2026-09-14 10:02
solaris-1   NR    /          6.21G  static 2026-10-20 09:41
$ zfs list -o name,mountpoint -r rpool | head

On Solaris 10 with a ZFS root (10/08 and later), the layout is similar (rpool/ROOT/s10be), but BEs are managed with Live Upgrade (lucreate, luactivate, lustatus) rather than beadm.

Solaris 10 vs Solaris 11.4 at a glance

ItemSolaris 10Solaris 11.4
Root filesystemUFS slices, or ZFS root from 10/08ZFS only, in a boot environment
/var/runtmpfsLink to /system/volatile
Shared data across BEsNot applicable on UFSrpool/VARSHARE at /var/share
Package database/var/sadm (SVR4)/var/pkg (IPS), /var/sadm for any SVR4 packages
Freeware location/usr/sfw, /opt/sfwIntegrated into /usr; GNU tools in /usr/gnu/bin
Network config files/etc/hostname.*, /etc/defaultrouteripadm/dladm databases; no flat files
Name service configFlat files in /etcSMF properties that generate files in /etc
Kernel tunables/etc/system/etc/system.d/ drop-ins preferred
Local driver config/kernel/drv/*.conf/etc/driver/drv/*.conf
Root’s home//root
Directory man pagefilesystem(5)filesystem(7)

Verification: which package owns a file?

Whenever you find an unfamiliar file, ask the packaging system who delivered it. That tells you whether it is part of the OS, safe to edit, or left over from something else.

# Solaris 10 (SVR4)
$ pkgchk -l -p /usr/bin/ls
Pathname: /usr/bin/ls
Type: regular file
Expected mode: 0555
Expected owner: root
Expected group: bin
...
Referenced by the following packages:
        SUNWcsu
Current status: installed

# Solaris 11 (IPS)
$ pkg search -l /usr/bin/ls
INDEX      ACTION VALUE      PACKAGE
path       file   usr/bin/ls pkg:/system/core-os@11.4-11.4.96.0.1.227.1

On Solaris 11 you can also check whether files have been changed from what the package delivered with pkg verify, for example pkg verify -v system/core-os. A file that no package claims was added locally or by a third-party installer.

Troubleshooting and gotchas

  • “mkdir: Failed to make directory /home/bob; Operation not applicable”. /home is an automount point. Create the directory in /export/home and let auto_home map it, or disable the automounter if you really do not want it.
  • Edits to /etc/resolv.conf or /etc/nsswitch.conf vanish on Solaris 11. They are regenerated from SMF. Set the properties with svccfg and refresh the service.
  • Files in /tmp disappeared after a reboot. That is by design; /tmp is memory-backed. Use /var/tmp for anything that must survive.
  • /var full on Solaris 10. Look at /var/crash, /var/adm and patch backout data in /var/sadm/pkg/*/save. Do not delete files under /var/sadm/install; that is the package database.
  • Deleting things under /var/pkg to save space. Do not. Use pkg purge-history and remove old boot environments with beadm destroy instead.
  • Driver change in /kernel/drv lost after an SRU on Solaris 11. Package updates replace that directory’s files. Put local overrides in /etc/driver/drv.
  • System does not boot after editing kernel files. The boot archive may be stale. Boot the failsafe or a known-good BE and run bootadm update-archive (on Solaris 11 you can also boot a previous BE from the OBP or GRUB menu).
  • Scripts behave differently between Solaris 10 and 11. Check which for every tool and compare /usr/bin, /usr/xpg4/bin and /usr/gnu/bin versions. Use full paths in scripts that must run on both.

What’s next in the Solaris Admin Series

Next comes a deeper look at /devices, /dev, device paths, instance numbers and /etc/path_to_inst. Boot archives, boot environments, SMF and both packaging systems each get their own posts later in the series. If you are just joining, start with part 1, Solaris 10 and 11.4 Releases, Support Lifecycle and Which to Run, and part 2, Solaris on SPARC vs x86: sun4u, sun4v, i86pc and What Differs.

Official references: Oracle Solaris 11.4 documentation library and Oracle Solaris 10 1/13 documentation library.

Leave a Reply

Your email address will not be published. Required fields are marked *