#!/bin/bash set -eu -o pipefail readonly script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" readonly task_worker="${script_dir}/../taskworker.js" if [[ ${EUID} -ne 0 ]]; then echo "This script should be run as root." > /dev/stderr exit 1 fi if [[ $# -eq 0 ]]; then echo "No arguments supplied" exit 1 fi if [[ "$1" == "--check" ]]; then echo "OK" exit 0 fi readonly task_id="$1" readonly logfile="$2" readonly nice="$3" readonly memory_limit_mb="$4" # SI units readonly oom_score_adjust="$5" readonly id=$(id -u $SUDO_USER) readonly service_name="box-task-${task_id}" systemctl reset-failed "${service_name}" 2>/dev/null || true options="-p TimeoutStopSec=10s -p MemoryMax=${memory_limit_mb}M -p OOMScoreAdjust=${oom_score_adjust} --wait" # systemd-run is used to create resource limited tasks. the tasks are in separate cgroup and won't get affected by box start/stop # this design is because tasks should not run when box code is stopped. if dashboard is down, nothing should run -in background. # besides, if tasks continue running, box code needs complex reconcilation code on start up. # To achieve above design, we could use BindsTo=box.service. While this stops all tasks on systemctl stop, it restarts tasks on systemctl restart. # Another approach was to use --scope but this is incompatible with --wait (and then we have to start polling status to get exit code) # it seems systemd-run does not return the exit status of the process despite --wait but atleast it waits if ! systemd-run --unit "${service_name}" --wait --uid=${id} --gid=${id} \ -p TimeoutStopSec=2s -p MemoryMax=${memory_limit_mb}M -p OOMScoreAdjust=${oom_score_adjust} --nice "${nice}" \ --setenv HOME=${HOME} --setenv USER=${SUDO_USER} --setenv DEBUG=box:* --setenv BOX_ENV=${BOX_ENV} --setenv NODE_ENV=production \ "${task_worker}" "${task_id}" "${logfile}"; then echo "Service ${service_name} failed to run" # this only happens if the path to task worker itself is wrong fi exit_code=$(systemctl show "${service_name}" -p ExecMainCode | sed 's/ExecMainCode=//g') echo "Service ${service_name} finished with exit code ${exit_code}" exit "${exit_code}"