cpsv(8)

cpsv(8) β€” straight out of the GNU/Linux System Administrator's manual, and bestie, this one is a whole personality πŸ’–

✨ NAME ✨

cpsv β€” a utility to install and manage runit services. that's it, that's the girl πŸŽ€


✨ SYNOPSIS ✨

cpsv  [-f] a <service-directory> [ <service-directory2> ...]
cpsv  p <service-directory> [ <service-name> ]
cpsv  d <service-directory> [ <service-name> ]
cpsv  [-f] s
cpsv  l
cpsv  i

✨ DESCRIPTION ✨

okay so first things first, the whole game here is two directories. CPSV_SOURCE is where the runscripts come from, CPSV_DEST is where they go. and you've got three moves:

  • cpsv a or cpsv s β†’ install runscripts from CPSV_SOURCE to CPSV_DEST πŸ’…
  • cpsv d β†’ peek at runscripts that are already installed in CPSV_DEST (inspection era) πŸ”
  • cpsv p β†’ spin up a named instance from a template, rename a service, or maintain a partially modified version of a service. templates live in CPSV_SOURCE, instances get created in CPSV_DEST πŸ¦‹

now, on a Debian system, by default CPSV_SOURCE is /usr/share/runit/sv.current and CPSV_DEST is /etc/sv. no cap. Debian packages install runscripts in /usr/share/runit/sv, and a runitme copy of each relevant service is maintained at /usr/share/runit/sv.current.

and here's the split that makes it all make sense: when a package installs a runscript in /usr/share/runit/sv/, then /etc/sv/ is used to store instances or locally modified copy of that service. package territory vs. your territory, bestie 🫢


πŸ’– COMMANDS πŸ’–

🌸 a

Copy <service> from CPSV_SOURCE into CPSV_DEST, then create symlinks as when the p command is used. you can pass more than one <service> name with this command, and each <service> directory must exists in CPSV_SOURCE.

if <service> already exists in CPSV_DEST, cpsv prints a warning, the cp invocation is skipped, and the return code is increased by one. the -f option can be used to change this behaviour. ⚠️

🌈 p

Create <CPSV_DEST/service-name> if it does not exists, then populate it with directories and symlinks pointing at <CPSV_SOURCE/service-directory>. <service-directory> must already exist in CPSV_SOURCE. if <service-name> is omitted, <service-directory> is used instead. and when <cpsv p> is invoked without root privileges, the <@user> suffix in <service-name>, if any, gets stripped. bye suffix πŸ’€

so <run,check,finish,xchopts,control,.meta,env> and <log/run> are created in <CPSV_DEST/service-name> as symlinks to their conterpart in <CPSV_SOURCE/service-directory>. then:

  • if a <CPSV_DEST/service-name/.meta/finish> file exists, and a <CPSV_DEST/service-name/finish> file or symlink is not found, cpsv creates a symlink to /lib/runit/finish-exec
  • if a <CPSV_DEST/service-name/supervise> symlink or directory is not found, cpsv creates one

if <CPSV_SOURCE/service-directory/log> is found, the <CPSV_DEST/service-name/log> directory is created. and when a <CPSV_DEST/service-name>/log directory exists:

  • if <service-name>/log/supervise link or directory is not found, cpsv creates one
  • if <CPSV_SOURCE/service-directory/log/run is found, cpsv creates a <CPSV_DEST/service-name>/log/run symlink to it
  • otherwise the symlink points to /etc/sv/svlogd/run
Files or directories already found in <CPSV_DEST/service-name> are skipped, and targets of existing symlinks are not updated. respectfully, hands off πŸ–οΈ

πŸ‘‘ d

Print the diff between the <service-directory> in CPSV_SOURCE and the <service-name> in CPSV_DEST, then return diff's exit status. <service-directory> must exists in CPSV_SOURCE. if <service-name> is omitted, <service-directory> is used instead. Supervise, conf and wtime are excluded from the diff. (iconic of them to sit this one out ✨)

🧚 s

Sync CPSV_DEST with CPSV_SOURCE. for each <service> directory in CPSV_SOURCE, cpsv will search the system for a systemd or sysv service file with the same name:

  • when it finds one β†’ it copies the <service> directory as when the a command is given, and goes to the next directory
  • else β†’ cpsv looks for the path written in a <service>/.meta/bin file, and if such path exists in the system, then it copies the <service> directory as when the a command is given
  • otherwise β†’ it goes to the next directory

it's giving automated detective work πŸ”πŸ’…

πŸ’œ l

List installed services in CPSV_DEST. the name of each <service> that would be copied with the s command is printed, preceded with a character surrounded by square brakets:

  • [a]: <service>; β†’ exists in CPSV_SOURCE but not in CPSV_DEST
  • [i]: <service>; β†’ exists both in CPSV_SOURCE and CPSV_DEST, and the copy in CPSV_DEST is identical to the one created with the a command
  • [l]: <service>; β†’ exists both in CPSV_SOURCE and CPSV_DEST, and the copy in CPSV_DEST is different from the one created with the a command

πŸŽ€ i

Install directories and symlinks needed by runit. heads up: targets of existing symlinks are never updated this way. 🚨

when run without root privileges, the following directories amd symlinks are installed inside </home/$user/:>

.runit/sv
.runit/log
.runit/supervise
.runit/runsvdir/default
.runit/runsvdir/headless
.service->.runit/runsvdir/current
.runit/runsvdir/current->.runit/runsvdir/default

if the </home/$user/> directory is not found in the system, cpsv returns 0 immediately. no home, no problem, we out πŸšͺπŸ’¨

when run with root privileges, the following directories amd symlinks are installed:

/etc/sv
/etc/runit/runsvdir/default
/usr/share/runit/sv
/usr/share/runit/sv.now
/etc/runit/runsvdir/current->/etc/runit/runsvdir/default
/etc/service->/etc/runit/runsvdir/current
/usr/share/runit/sv.current->/usr/share/runit/sv.now
/usr/share/runit/sv.src->/usr/share/runit/sv

✨ OPTIONS ✨

  • -f β€” Overwrite <service> files in CPSV_DEST with <service> files in CPSV_SOURCE. no backup is provided, so like… be so serious before you type this one 😭. When a <service>/log directory exists, the <service>/log/run file or symlink is replaced with the default one that is created with the p command. supervise directories or symlinks are never overwritten or replaced this way. πŸ›‘

🌈 ENVIRONMENT 🌈

CPSV_DEST

The environment variable $CPSV_DEST overrides the default directory where services are copied. If omitted or empty, the default is set to /etc/sv when cpsv is run with root privileges, and ~/.runit/sv when cpsv is run without root privileges.

CPSV_SOURCE

The environment variable $CPSV_SOURCE overrides the default directory from where services are copied. If omitted or empty, the default is set to /usr/share/runit/sv.current. By changing the target of the /usr/share/runit/sv.current symlink it is possible to permanently override CPSV_SOURCE to use a local colletion of runscripts. symlink hack, main character energy πŸ”—πŸ‘‘


πŸ¦‹ FILES πŸ¦‹

  • /etc/sv
  • /usr/share/runit/sv.current
  • ~/.runit/sv

🌸 AUTHOR 🌸

Lorenzo Puliti <plorenzo@disroot.org> β€” thank you for your service (literally) πŸ«‘πŸ’–


πŸ’… SEE ALSO πŸ’…


and that's the whole page, bestie πŸŽ€ this was cpsv(8) from the GNU/Linux System Administrator's manual, dated Feb 8, 2026 β€” go forth, manage your runit services, and remember: no backup is provided, so read the -f section twice. mwah πŸ’‹βœ¨

πŸ“¦ where this page comes from