]> git.corax.cc Git - toolbox/commitdiff
include/inst: Add inst module for managing running instances of scripts
authorMatthias Kruk <m@m10k.eu>
Thu, 15 Apr 2021 13:37:00 +0000 (22:37 +0900)
committerMatthias Kruk <m@m10k.eu>
Thu, 15 Apr 2021 13:37:00 +0000 (22:37 +0900)
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 [new file with mode: 0644]

diff --git a/include/inst.sh b/include/inst.sh
new file mode 100644 (file)
index 0000000..d20a8c5
--- /dev/null
@@ -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 &>/dev/null &
+       disown
+
+       return 0
+}