From f0dfaf5c06d8171b7a67843aec986b0b7c14b2d0 Mon Sep 17 00:00:00 2001 From: Matthias Kruk Date: Thu, 15 Apr 2021 22:37:00 +0900 Subject: [PATCH] include/inst: Add inst module for managing running instances of scripts This commit adds the inst module which provides functions for managing instances of scripts: - The inst_start() function forks a function to the background - The inst_stop() function asks an instance to stop - The inst_list() function lists running instances - The inst_running() function tells an instance if it should stop Internally, the module makes use of semaphores to list instances and determine their state. Semaphores are kept in per-script directories within $TOOLBOX_HOME/inst. --- include/inst.sh | 145 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 include/inst.sh diff --git a/include/inst.sh b/include/inst.sh new file mode 100644 index 0000000..d20a8c5 --- /dev/null +++ b/include/inst.sh @@ -0,0 +1,145 @@ +#!/bin/bash + +__init() { + local name + + name="${0##*/}" + + if [[ -z "$name" ]]; then + echo "Could not determine script name" 1>&2 + return 1 + fi + + if ! include "opt" "sem"; then + return 1 + fi + + declare -xgr __inst_name="$name" + declare -xgr __inst_path="$TOOLBOX_HOME/inst/$__inst_name" + + if ! mkdir -p "$__inst_path"; then + return 1 + fi + + opt_add_arg "l" "list" "no" 0 "List running instances" _inst_handle_opt + opt_add_arg "s" "stop" "yes" "" "Stop a running instance" _inst_handle_opt + + return 0 +} + +_inst_handle_opt() { + local opt="$1" + local arg="$2" + + local ret + + ret=0 + + case "$opt" in + "stop") + if ! inst_stop "$arg"; then + ret=1 + fi + ;; + + "list") + if ! inst_list; then + ret=1 + fi + ;; + + *) + ret=1 + ;; + esac + + exit "$ret" +} + +inst_list() { + local sem + + while read -r sem; do + local owner + local semval + local state + local argv + + owner="${sem##*/}" + semval=$(sem_peek "$sem") + + if ! argv=$(<"$sem.argv") 2> /dev/null; then + continue + fi + + if (( semval > 0 )); then + state="STOPPING" + else + state="RUNNING" + fi + + echo "$owner $state $__inst_name $argv" + done < <(find "$__inst_path" -regex ".*/[0-9]+") + + return 0 +} + +inst_stop() { + local pid="$1" + + local sem + + sem="$__inst_path/$pid" + + if ! sem_post "$sem"; then + return 1 + fi + + return 0 +} + +inst_running() { + if ! sem_trywait "$__inst_sem"; then + return 0 + fi + + return 1 +} + +_inst_run() { + local cmd="$1" + local args=("${@:2}") + + local ret + + declare -xgr __inst_sem="$__inst_path/$BASHPID" + + if ! opt_get_argv > "$__inst_path/$BASHPID.argv"; then + log_error "Could not save args" + return 1 + fi + + if ! sem_init "$__inst_sem" 0; then + log_error "Could not initialize semaphore $__inst_sem" + return 1 + fi + + if ! "$cmd" "${args[@]}"; then + ret=1 + else + ret=0 + fi + + if ! sem_destroy "$__inst_sem"; then + log_error "Could not destroy semaphore $__inst_sem" + fi + + return "$ret" +} + +inst_start() { + _inst_run "$@" /dev/null & + disown + + return 0 +} -- 2.47.3