aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md16
-rwxr-xr-xpool.sh167
2 files changed, 183 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..3f921c2
--- /dev/null
+++ b/README.md
@@ -0,0 +1,16 @@
+# pool.sh a simple processes pool management
+
+**What is pool.sh ?** pool.sh allows you to create simple pools of processes. This is usefull to run several process in parallel such as simulations. It is design to be used in bash scripts.
+
+**How it works ?**
+- Create a pool with `./pool.sh create <poolname> <capacity>`
+- Launch a process in a pool with `./pool.sh run <poolname> <command>` which return the process id `<procid>` If the pool `<poolname>` is full (number of processes equals to `<capacity>`) pool.sh will wait until room has been made in the pool to run `<command>`.
+- Get the output of a process with `./pool.sh cat <poolname> <procid>`
+- Wait until all the processes are completed with `./pool.sh wait <poolname>`
+- Remove a pool with `./pool.sh remove <poolname>` if there is still processes running this call will fail.
+- Force the removal of a pool with `./pool.sh remove-force <poolname>` all running processes will be killed and the pool will be deleted
+- Additional properties can be attach to processes with `./pool.sh setp <poolname> <procid> <propname> <propvalue>` Defaults properties are `<cmd>`,`<procpid>`,`<startat>`.
+- Properties can be retrieve with `./pool.sh getp <poolname> <procid> <propname>`
+- Finally, all the processes output file can be retrieve with `./pool.sh ls <poolname>`
+
+**Finale quote:** No checks are performed on the pool.sh arguments. Be sure to use the right ones.
diff --git a/pool.sh b/pool.sh
new file mode 100755
index 0000000..dbaec3c
--- /dev/null
+++ b/pool.sh
@@ -0,0 +1,167 @@
+#!/usr/bin/env bash
+set -e
+
+# Fetch arguments
+CMD=$1
+POOL_ID=$2
+shift 2
+PROC_CMD=$@
+
+# Config: feel free to change at your own risks
+tmpdir=/tmp
+pool_format="pool_${POOL_ID}"
+pool="${tmpdir}/${pool_format}/"
+pool_status="${pool}/status"
+REFRESH_EVERY=1
+
+abort() {
+ echo $@
+ exit 1
+}
+
+write_status() {
+ echo "maxproc=${maxproc}" > "$pool_status"
+ echo "nproc=${nproc}" >> "$pool_status"
+ echo "procs=\"${procs}\"" >> "$pool_status"
+ echo "lastprocid=$lastprocid" >> "$pool_status"
+}
+
+write_process() {
+ file="${pool}/proc_${procid}"
+ echo cmd=\"${PROC_CMD}\" > "$file"
+ echo "procpid=${procpid}" >> "$file"
+ echo "procid=${procid}" >> "$file"
+ echo "startat=${startat}" >> "$file"
+}
+
+setp() {
+ file="${pool}/proc_${procid}"
+ echo $1=$2 >> "$file"
+}
+
+getp() {
+ file="${pool}/proc_${procid}"
+ source "$file"
+ echo "${!1}"
+}
+
+
+create() {
+ [ -d "$pool" ] && abort "Pool \"$pool\" already exists"
+ mkdir -p "$pool"
+ # Write pool status
+ maxproc=$1
+ nproc=0
+ procs=""
+ lastprocid=0
+ write_status
+}
+
+remove() {
+ refresh
+ [ $nproc -gt 0 ] && abort "Processes are still running in the pool!"
+ rm -rf "$pool"
+}
+
+refresh() {
+ source "$pool_status"
+ procs_new=""
+ for proc in $procs
+ do
+ if kill -0 $proc &>/dev/null
+ then
+ [ -z "$procs_new" ] && procs_new="$proc" || procs_new="$procs_new $proc"
+ fi
+ done
+ procs=$procs_new
+ nproc=$(echo "$procs"|wc -w)
+ write_status
+}
+
+run() {
+ refresh
+ while [ $nproc -ge $maxproc ]
+ do
+ sleep $REFRESH_EVERY
+ refresh
+ done
+ nproc=$(( nproc + 1 ))
+ procid=$(( lastprocid + 1 ))
+ lastprocid=$procid
+ startat=$(date +"%s")
+ $PROC_CMD > "$pool/out_$procid" &
+ procpid=$!
+ [ -z "$procs" ] && procs="$procpid" || procs="$procs $procpid"
+ write_status
+ write_process
+ echo $procid
+}
+
+cat_output() {
+ file="${pool}/out_${procid}"
+ cat "$file"
+}
+
+wait_pool() {
+ refresh
+ while [ $nproc -gt 0 ]
+ do
+ sleep $REFRESH_EVERY
+ refresh
+ done
+}
+
+list_output() {
+ refresh
+ find "${pool}" -name "out_*"
+}
+
+remove_force() {
+ refresh
+ for proc in $procs
+ do
+ kill -9 $proc
+ done
+ rm -rf "$pool"
+}
+
+# Ensure pool exists
+[ ! "$CMD" == "create" ] && [ ! -d "$pool" ] && abort "Pool $POOL_ID not found"
+
+# Launch command
+case "$CMD" in
+ "create")
+ create $1
+ ;;
+ "remove")
+ remove
+ ;;
+ "run")
+ run
+ ;;
+ "cat")
+ procid=$1
+ refresh
+ [ $procid -gt $lastprocid ] && abort "Processus $procid not found"
+ cat_output
+ ;;
+ "ls")
+ list_output
+ ;;
+ "wait")
+ wait_pool
+ ;;
+ "remove-force")
+ remove_force
+ ;;
+ "setp")
+ procid=$1
+ setp $2 $3
+ ;;
+ "getp")
+ procid=$1
+ getp $2
+ ;;
+ *)
+ abort "Command $CMD unknown"
+esac