|home| |posts| |projects| |cv| |bookmarks| |github|

Manage Background Services With Bash

Let's say you have a program that is intended to run forever in the background, for example a HTTP server, and that program is a standalone statically linked binary(like Go's binaries) which just needs to be executed and that's it, nothing else.

How would you manage that?

Using docker?

No, for this usecase docker is overkill. Docker is huge and like decribed above you just want to manage a statically linked binary with no other dependencies.

Using systemd(or other init system)?

This is better but still overkill. Like docker, systemd is not small. It has too many moving parts that you have to know about and we just want to manage a simple binary.

Using bash's disown

disown is a bash(and zsh) builtin command. It removes jobs from the shell job table.

Normally when you execute a long running job in a shell and close the shell while that job is running, the job will be killed along with its parent shell.

If you disown that job before closing the shell, the job will keep running in the background even after the shell is closed.

For example, let's say you open a terminal and run netcat to listen on port 3344:

nc -l 3344

From other terminal you can see the listening socket:

ss -pat|grep 3344
LISTEN       0        1                0.0.0.0:3344             0.0.0.0:*        users:(("nc",pid=26132,fd=3))

And now you close the terminal and check again to see the socket:

ss -pat|grep 3344

No output should appear.

But if you run the command like this:

nc -l 3344 & disown

And redo the previous steps, the job should remain in the background even after you close the terminal.

Notes

By disowning a job you will lose access to its stdout and stderr.

You can avoid this by redirecting them to a file:

nc -l 3344 2>&1 | tee /tmp/log & disown

For each service you can deploy the binary and a script that runs the binary.

For example, if the binary is named mybinary, you deploy the binary and a script like this one somewhere in your PATH:

#!/bin/bash

mybinary 2>&1 | tee /tmp/mybinary.log & disown

Log rotation should be managed manually.

This is done manually via ps, pgrep, pkill, kill, killall, top, htop commands for stopping the service and via the run script for restarting the service.

E.g.:

Check if service is running:

pgrep mybinary

Kill it if is running:

pkill mybinary

OR

kill pid_returned_by_pgrep

x