Last active
August 25, 2023 16:27
-
-
Save jowharshamshiri/e55c3bbce700aa312c54f5204e7e8b36 to your computer and use it in GitHub Desktop.
forky a utility for managing multiple commands in the background.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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