Add shoreman.sh and a Procfile for easily running a local setup
This commit is contained in:
parent
8e600ba3b6
commit
6cc263aae4
2
Procfile
Normal file
2
Procfile
Normal file
@ -0,0 +1,2 @@
|
||||
server: RUST_LOG=debug ./target/debug/synchronik-server -c examples/server.yml
|
||||
agent: RUST_LOG=debug ./target/debug/synchronik-agent
|
133
scripts/shoreman.sh
Executable file
133
scripts/shoreman.sh
Executable file
@ -0,0 +1,133 @@
|
||||
#!/usr/bin/env bash
|
||||
# [shoreman](https://github.com/chrismytton/shoreman) is an
|
||||
# implementation of the **Procfile** format. Inspired by the original
|
||||
# [foreman](http://ddollar.github.com/foreman/) tool for ruby.
|
||||
|
||||
# Make sure that any errors cause the script to exit immediately.
|
||||
set -eo pipefail
|
||||
[[ "$TRACE" ]] && set -x
|
||||
|
||||
# ## Usage
|
||||
|
||||
# Usage message that is displayed when `--help` is given as an argument.
|
||||
usage() {
|
||||
echo "Usage: shoreman [procfile|Procfile] [envfile|.env]"
|
||||
echo "Run Procfiles using shell."
|
||||
echo
|
||||
echo "The shoreman script reads commands from [procfile] and starts up the"
|
||||
echo "processes that it describes."
|
||||
}
|
||||
|
||||
# ## Logging
|
||||
|
||||
# For logging we want to prefix each entry with the current time, as well
|
||||
# as the process name. This takes two arguments, the name of the process
|
||||
# with its index, and then reads data from stdin, formats it, and sends it
|
||||
# to stdout.
|
||||
log() {
|
||||
local index="$2"
|
||||
local format="%s %s\t| %s"
|
||||
|
||||
# We add colors when output is a terminal. `SHOREMAN_COLORS` can override it.
|
||||
if [ -t 1 -o "$SHOREMAN_COLORS" == "always" ] \
|
||||
&& [ "$SHOREMAN_COLORS" != "never" ]; then
|
||||
# Bash colors start from 31 up to 37. We calculate what color the process
|
||||
# gets based on its index.
|
||||
local color="$((31 + (index % 7)))"
|
||||
format="\033[0;${color}m%s %s\t|\033[0m %s"
|
||||
fi
|
||||
|
||||
while IFS= read -r data
|
||||
do
|
||||
printf "$format\n" "$(date +"%H:%M:%S")" "$1" "$data"
|
||||
done
|
||||
}
|
||||
|
||||
# ## Running commands
|
||||
|
||||
# When a process is started, we want to keep track of its pid so we can
|
||||
# `kill` it when the parent process receives a signal, and so we can `wait`
|
||||
# for it to finish before exiting the parent process.
|
||||
store_pid() {
|
||||
pids="$pids $1"
|
||||
}
|
||||
|
||||
# This starts a command asynchronously and stores its pid in a list for use
|
||||
# later on in the script.
|
||||
start_command() {
|
||||
bash -c "$1" 2>&1 | log "$2" "$3" &
|
||||
pid="$(jobs -p %%)"
|
||||
store_pid "$pid"
|
||||
}
|
||||
|
||||
# ## Reading the .env file
|
||||
|
||||
# The .env file needs to be a list of assignments like in a shell script.
|
||||
# Shell-style comments are permitted.
|
||||
load_env_file() {
|
||||
local env_file=${1:-'.env'}
|
||||
|
||||
# Set a default port before loading the .env file
|
||||
export PORT=${PORT:-5000}
|
||||
|
||||
if [[ -f "$env_file" ]]; then
|
||||
export $(grep "^[^#]*=.*" "$env_file" | xargs)
|
||||
fi
|
||||
}
|
||||
|
||||
# ## Reading the Procfile
|
||||
|
||||
# The Procfile needs to be parsed to extract the process names and commands.
|
||||
# The file is given on stdin, see the `<` at the end of this while loop.
|
||||
run_procfile() {
|
||||
local procfile=${1:-'Procfile'}
|
||||
# We give each process an index to track its color. We start with 1,
|
||||
# because it corresponds to green which is easier on the eye than red (0).
|
||||
local index=1
|
||||
while read line || [[ -n "$line" ]]; do
|
||||
if [[ -z "$line" ]] || [[ "$line" == \#* ]]; then continue; fi
|
||||
local name="${line%%:*}"
|
||||
local command="${line#*:[[:space:]]}"
|
||||
start_command "$command" "${name}" "$index"
|
||||
echo "'${command}' started with pid $pid" | log "${name}" "$index"
|
||||
index=$((index + 1))
|
||||
done < "$procfile"
|
||||
}
|
||||
|
||||
# ## Cleanup
|
||||
|
||||
# When a `SIGINT`, `SIGTERM` or `EXIT` is received, this action is run, killing the
|
||||
# child processes. The sleep stops STDOUT from pouring over the prompt, it
|
||||
# should probably go at some point.
|
||||
onexit() {
|
||||
echo "SIGINT received"
|
||||
echo "sending SIGTERM to all processes"
|
||||
kill $pids
|
||||
sleep 1
|
||||
}
|
||||
|
||||
main() {
|
||||
local procfile="$1"
|
||||
local env_file="$2"
|
||||
|
||||
# If the `--help` option is given, show the usage message and exit.
|
||||
expr -- "$*" : ".*--help" >/dev/null && {
|
||||
usage
|
||||
exit 0
|
||||
}
|
||||
|
||||
load_env_file "$env_file"
|
||||
run_procfile "$procfile"
|
||||
|
||||
trap onexit INT TERM
|
||||
|
||||
exitcode=0
|
||||
for pid in $pids; do
|
||||
# Wait for the children to finish executing before exiting.
|
||||
# If said children exitcode is not successful, collect it.
|
||||
wait "${pid}" || exitcode=$?
|
||||
done
|
||||
exit $exitcode
|
||||
}
|
||||
|
||||
main "$@"
|
Loading…
Reference in New Issue
Block a user