Go to file
suyono b2668287ae Merge pull request 'README.md + Example + Docker build args + wmpidproxy fix' (#1) from readme into main
Reviewed-on: #1
2023-12-26 20:57:04 +00:00
.devcontainer feat(exec): cgo call to getpwnam and getgrnam 2023-12-17 05:23:26 +00:00
.idea fix: setting last run when true 2023-12-08 15:15:35 +11:00
cmd fix(pidproxy): replace Timer with Ticker 2023-12-26 09:53:37 +11:00
config wip: config unit test 2023-12-25 13:13:03 +11:00
docker doc: getting-started 2023-12-27 07:51:31 +11:00
example/ssh-docker fix(pidproxy): handle new line 2023-12-26 09:20:42 +11:00
files/testconfig wip: start simple 2023-12-08 15:15:35 +11:00
init chore: fix .gitignore 2023-12-14 00:11:39 +00:00
logger wip: pipe stdout & stderr 2023-12-09 02:44:06 +00:00
.gitignore feat(exec): initial 2023-12-17 03:36:47 +00:00
.tool-versions fix: setting last run when true 2023-12-08 15:15:35 +11:00
LICENSE Initial commit 2023-08-28 08:04:50 +00:00
Makefile chore: exclude test binary on default build 2023-12-18 12:28:14 +00:00
README.md doc: getting-started 2023-12-27 07:51:31 +11:00
go.mod wip: config unit test 2023-12-25 13:13:03 +11:00
go.sum wip: config unit test 2023-12-25 13:13:03 +11:00
logger.go fix: mismatch WaitGroup 2023-12-09 04:29:38 +00:00
types.go feat(pidproxy): read startsecs from env 2023-12-10 22:23:43 +11:00



Wingmate is a process manager for services. It works like init. It starts and restarts services. It also has cron feature. It is designed to run in a container/docker. The Wingmate binary do not need any external dependency. Just copy the binary, and exec from the entry point script.

Getting Started


There are three binaries in this project: wingmate, wmpidproxy, and wmexec.

wingmate is the core binary. It reads config, starts, restarts services. It also runs cron. Read the configuration section for files needed to run wingmate.

wmpidproxy is a helper binary for monitoring legacy style service (fork, exit initial proces, and continue in background). Read here for further details about wmpidproxy.

wmexec is a helper binary for running process in different user or group. It also useful for setting the process as process group leader. Read here for further details about wmexec.

Building a container image based on wingmate image in Docker Hub

Wingmate has no dependency other than alpine base image, so you just need to copy the binaries directly. If you have built your application into an alpine based image, all you need to do is copy whichever binary you need, crontab file (if you use cron) and add some shell script to glue them together. Here is a Dockerfile example.

# Dockerfile
FROM suyono/wingmate:alpine as source

FROM alpine:latest
ADD --chmod=755 wingmate/ /etc/wingmate/
ADD --chmod=755 entry.sh /usr/local/bin/entry.sh
COPY --from=source /usr/local/bin/wingmate /usr/local/bin/wingmate
COPY --from=source /usr/local/bin/wmpidproxy /usr/local/bin/wmpidproxy
COPY --from=source /usr/local/bin/wmexec /usr/local/bin/wmexec
ENTRYPOINT [ "/usr/local/bin/entry.sh" ]
CMD [ "/usr/local/bin/wingmate" ]

You can find some examples for shell script in alpine docker and bookworm docker.


When wingmate binary starts, it will look for some files. By default, it will try to read the content of /etc/wingmate directory. You can change the directory where it reads by setting WINGMATE_CONFIG_PATH environment variable. The structure inside the config path should look like this.

 └── wingmate
     ├── crontab
     ├── crontab.d
     │   ├── cron1.sh
     │   ├── cron2.sh
     │   └── cron3.sh
     └── service
         ├── one.sh
         └── spawner.sh

First, wingmate will try to read the content of service directory. The content of this directory should be executables (either shell scripts or binaries). The wingmate will run every executable in service directory without going into any subdirectory.

Next, wingmate will read the crontab file. wingmate expects the crontab file using common UNIX crontab file format. Something like this

 ┌───────────── minute (059)
 │ ┌───────────── hour (023)
 │ │ ┌───────────── day of the month (131)
 │ │ │ ┌───────────── month (112)
 │ │ │ │ ┌───────────── day of the week (06) (Sunday to Saturday)
 │ │ │ │ │ 
 │ │ │ │ │
 │ │ │ │ │
 * * * * * <commad or shell script or binary>

The command part only support simple command and arguments. Shell expression is not supported yet. It is recommended to write a shell script and put the path to shell script in the command part.


Wingmate PID Proxy binary

wingmate works by monitoring its direct children process. When it sees one of its children exited, it will start the child process again.

Sometimes you find some services work by running in the background. It means it forks a new process, disconnect the new child from terminal, exit the parent process, and continue running in the child process. This kind of service usually write its background process PID in a pid file.

To monitor the background services, wingmate utilizes wmpidproxy. wmpidproxy runs in foreground in-place of the background service. It also periodically check whether the background service is still running, in current implementation it checks every second.

wmpidproxy --pid-file <path to pid file> -- <background service binary/start script>


Running sshd background with wingmate and wmpidproxy: here


It is recommended to configure services to run in foreground if they support it. When services running in foreground, they are running as direct children process of wingmate. wingmate monitors children process effectively. Whenever a child process exited/terminated, wingmate will start it again quickly. Running in foreground also removes the overhead of running wmpidproxy together with the service.

Wingmate Exec binary

wingmate runs all the services as its children using the same uid, gid, and in the same process group. You can use wmexec to run service in different uid, gid, or make the service process as its own process group leader.


wmexec [--user <uid>[:<gid>]] [--setsid] -- <target executable>
Option Parameter Description
--user uid[:gid] Set the real user ID and the real group id. Uid and Gid can be either in numeric form or in name form
--setsid Set the process become the leader of its own process group, effectively detaching from parent's terminal


You can find example for wmexec in here and here