Serviceman generates and enables startup files on Linux, Mac, and Windows.
https://git.rootprojects.org/root/serviceman| Installer Source| Releases (json) (tab)
Serviceman generates and enables startup files on Linux, Mac, and Windows.
https://git.rootprojects.org/root/serviceman| Installer Source| Releases (json) (tab)
To update or switch versions, run webi serviceman@stable
(or @v0.8
, beta
,
etc).
A lightweight, cross-platform wrapper to more easily
use your native init system to control system service daemons
and user launch agents. \Works for web servers, backup scripts, network and system tools, etc, in all languages.
Works for any program, written in any language.
These are the files / directories that are created and/or modified with this install:
~/.config/envman/PATH.env
~/.local/bin/serviceman
This will also generate init system unit files according to your OS:
(use the --dryrun
option to learn what serviceman
does without making any
changes)
launchctl
(macOS)~/Library/LaunchAgents/<AGENT>.plist
/Library/LaunchDaemons/<DAEMON>.plist
systemctl
(Linux)/etc/systemd/system/<DAEMON>.service
~/.config/systemd/user/<AGENT>.service
openrc
(Alpine, Docker)/etc/init.d/<DAEMON>
HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run <AGENT>
sudo env PATH="$PATH" \
serviceman add --system --path="$PATH" -- \
bash ./backup.sh /mnt/data
Development Server
pushd ./my-node-app/
sudo env PATH="$PATH" \
serviceman add --system --path="$PATH" \
--cap-net-bind -- \
npx nodemon ./server.js
Production Server
pushd ./my-node-app/
sudo env PATH="$PATH" \
serviceman add --system --path="$PATH" \
--cap-net-bind -- \
npm start
pushd ./my-go-package/
sudo env PATH="$PATH" \
serviceman add --system --path="$PATH" \
-- \
go run -mod=vendor cmd/my-service/*.go --port 3000
pushd ./my-go-package/
go build -mod=vendor cmd/my-service
sudo env PATH="$PATH" \
serviceman add --system --path="$PATH" \
--cap-net-bind -- \
./my-service --port 80
serviceman list --system
serviceman list --user
serviceman-managed services:
example-service
You can either add
the service again (which will update any changed options),
or you can stop
and then start
any service by its name:
sudo env PATH="$PATH" serviceman stop example-service
sudo env PATH="$PATH" serviceman start example-service
The main help, showing all subcommands:
serviceman --help
Sub-command specific help:
serviceman add --help
--dryrun
to see the generated launcher config:sudo env PATH="$PATH" \
serviceman add --system --path="$PATH" \
--dryrun -- \
bash ./backup.sh /mnt/data
systemd
is the init system on cloud-init enabled server distros, and most
desktop distros.
[Unit]
Description=example-service
After=network-online.target
Wants=network-online.target systemd-networkd-wait-online.service
[Service]
Restart=always
StartLimitInterval=10
StartLimitBurst=3
User=root
Group=root
WorkingDirectory=/srv/example-service
ExecStart=/srv/example-service/bin/example-command start
ExecReload=/bin/kill -USR1 $MAINPID
# Allow the program to bind on privileged ports, such as 80 and 443
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE
NoNewPrivileges=true
[Install]
WantedBy=multi-user.target
init.d
service script looks likeopenrc
is the init
system on Alpine and other Docker and
container-friendly Linuxes.
/etc/init.d/exampled
:
#!/sbin/openrc-run
supervisor=supervise-daemon
name="Example System Daemon"
description="A Service for Logging 'Hello, World', a lot!"
description_checkconfig="Check configuration"
description_reload="Reload configuration without downtime"
# example:
# exampled run --port 1337 --envfile /path/to/env
# exampled check-config --port 1337 --envfile /path/to/env
# exampled reload --port 1337 --envfile /path/to/env
# for setting Config
: ${exampled_opts:="--envfile /root/.config/exampled/env"}
command=/root/bin/exampled
command_args="run --port 1337 $exampled_opts"
command_user=root:root
extra_commands="checkconfig"
extra_started_commands="reload"
output_log=/var/log/exampled.log
error_log=/var/log/exampled.err
depend() {
need net localmount
after firewall
}
checkconfig() {
ebegin "Checking configuration for $name"
su ${command_user%:*} -s /bin/sh -c "$command check-config $exampled_opts"
eend $?
}
reload() {
ebegin "Reloading $name"
su ${command_user%:*} -s /bin/sh -c "$command reload $exampled_opts"
eend $?
}
stop_pre() {
if [ "$RC_CMD" = restart ]; then
checkconfig || return $?
fi
}
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated for serviceman. Edit as you wish, but leave this line. -->
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>example-service</string>
<key>ProgramArguments</key>
<array>
<string>/Users/me/example-service/bin/example-command</string>
<string>start</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>WorkingDirectory</key>
<string>/Users/me/example-service</string>
<key>StandardErrorPath</key>
<string>/Users/me/.local/share/example-service/var/log/example-service.log</string>
<key>StandardOutPath</key>
<string>/Users/me/.local/share/example-service/var/log/example-service.log</string>
</dict>
</plist>