Skip to content

Instantly share code, notes, and snippets.

@jowharshamshiri
Last active August 25, 2023 16:27
Show Gist options
  • Save jowharshamshiri/e55c3bbce700aa312c54f5204e7e8b36 to your computer and use it in GitHub Desktop.
Save jowharshamshiri/e55c3bbce700aa312c54f5204e7e8b36 to your computer and use it in GitHub Desktop.
forky a utility for managing multiple commands in the background.
#!/bin/bash
FILE="forky.state"
SESSION_PREFIX="forky"
function print_help {
echo "forky v0.1.0"
echo "A utility for managing multiple commands in the background."
echo ""
echo "Usage:"
echo " $0 cmds=\"cmd0 [args]\",\"cmd1 [args]\" dirs=\"dir0\",\"dir1\""
echo " $0 start [id]"
echo " $0 stop [id]"
echo " $0 reset [id]"
echo " $0 list"
echo " $0 open <id>"
echo " $0 save <id> [output_file]"
echo " $0 help"
echo ""
echo "Options:"
echo " cmds: A comma-separated list of commands to run in the background."
echo " dirs: A comma-separated list of directories where each command should be run. Must have the same number of items as commands."
echo " start: Starts the previously saved commands if available."
echo " stop: Kills the tmux sessions."
echo " reset: resets the previously saved commands."
echo " list: Lists the tmux sessions."
echo " open: Attaches to the tmux session for the given command ID."
echo " save: Save the tmux session output to a given file or if not specified print to console."
echo " help: Prints this help message."
}
function load_state {
if [ ! -f "$FILE" ]; then
echo "Error: $FILE not found."
exit 1
fi
while IFS= read -r line; do
key="${line%%:*}"
value="${line#*: }"
if [[ $key == cmd* ]]; then
CMDS+=("$value")
elif [[ $key == dir* ]]; then
DIRS+=("$value")
fi
done < $FILE
}
function validate_id {
if [ -n "$ID" ] && ( [ "$ID" -lt "0" ] || [ "$ID" -ge "${#CMDS[@]}" ] ); then
echo "Error: Invalid ID. Must be in the range [0, ${#CMDS[@]})."
exit 1
fi
}
function run_commands {
if [ "${#CMDS[@]}" -ne "${#DIRS[@]}" ]; then
echo "Error: Number of commands does not match number of directories."
exit 1
fi
TEMP_FILE=$(mktemp)
for i in "${!CMDS[@]}"; do
if [ -z "$ID" ] || [ "$ID" == "$i" ]; then
CMD="${CMDS[$i]}"
DIR="${DIRS[$i]}"
SESSION_NAME="${SESSION_PREFIX}-cmd${i}"
tmux new-session -d -s "$SESSION_NAME" "cd $DIR && $CMD; bash"
if [ $? -ne 0 ]; then
echo "Error: Failed to start tmux session for command $i."
continue
fi
echo "cmd${i}: $CMD" >> $TEMP_FILE
echo "dir${i}: $DIR" >> $TEMP_FILE
fi
done
mv $TEMP_FILE $FILE
echo "Commands executed in the background. tmux sessions created."
}
function stop_sessions {
for i in "${!CMDS[@]}"; do
if [ -z "$ID" ] || [ "$ID" == "$i" ]; then
SESSION_NAME="${SESSION_PREFIX}-cmd${i}"
tmux kill-session -t "$SESSION_NAME" 2>/dev/null
fi
done
echo "tmux sessions killed."
}
function list_sessions {
echo "id session command"
for i in "${!CMDS[@]}"; do
SESSION_NAME="${SESSION_PREFIX}-cmd${i}"
CMD="${CMDS[$i]}"
printf "%-6s%-36s%s\\n" "$i" "$SESSION_NAME" "$CMD"
done
}
function open_session {
SESSION_NAME="${SESSION_PREFIX}-cmd$ID"
tmux attach-session -t "$SESSION_NAME"
}
function save_session {
SESSION_NAME="${SESSION_PREFIX}-cmd$ID"
if [ -z "$ID" ]; then
echo "Usage: $0 save <id> [output_file]"
return
fi
if [ -z "$OUTPUT_FILE" ]; then
tmux capture-pane -t "$SESSION_NAME" -p
echo "Session ${SESSION_NAME} content printed to console."
else
tmux capture-pane -t "$SESSION_NAME" -p > "$OUTPUT_FILE"
echo "Session ${SESSION_NAME} saved to $OUTPUT_FILE"
fi
}
if [ "$1" == "help" ]; then
print_help
elif [[ $1 == "cmds="* ]] && [[ $2 == "dirs="* ]]; then
IFS=',' read -ra CMDS <<< "${1#cmds=}"
IFS=',' read -ra DIRS <<< "${2#dirs=}"
run_commands
elif [ "$1" == "stop" ] || [ "$1" == "start" ] || [ "$1" == "reset" ]; then
if [ -f "$FILE" ]; then
load_state
ID="$2" # Optional command ID
validate_id
if [ "$1" == "stop" ]; then
stop_sessions
elif [ "$1" == "start" ]; then
run_commands
elif [ "$1" == "reset" ]; then
$0 stop "$ID"
$0 start "$ID"
fi
else
echo "$FILE not found."
exit 1
fi
elif [ "$1" == "list" ]; then
if [ -f "$FILE" ]; then
load_state
list_sessions
else
echo "$FILE not found."
fi
elif [ "$1" == "open" ]; then
if [ -f "$FILE" ]; then
load_state
ID="$2" # Command ID for the session to be opened
open_session
else
echo "$FILE not found."
fi
elif [ "$1" == "save" ]; then
if [ -f "$FILE" ]; then
load_state
ID="$2"
OUTPUT_FILE="$3"
save_session
else
echo "$FILE not found."
fi
else
print_help
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment