Skip to content

Instantly share code, notes, and snippets.

@hyp3ri0n-ng
Last active May 18, 2024 20:45
Show Gist options
  • Save hyp3ri0n-ng/32a130fd72f4599dafc9f3576fdf7e30 to your computer and use it in GitHub Desktop.
Save hyp3ri0n-ng/32a130fd72f4599dafc9f3576fdf7e30 to your computer and use it in GitHub Desktop.
Not a fan of expect. Run stuff in screen, pass arguments to prompts you will encounter, they'll inject into screen when they come up.
#!/bin/bash
#Purpose: I don't like having to write expect scripts and stuff. I'd rather it be easier, so made this little thingy,
#it runs everything in a screen session and allows you to specify your responses to prompts. It can handle any number of
#prompts. If you don't want to define what to do, it defaults to "y" and an Enter keypress.
#Usage: ./scrun "apt install whatever; apt upgrade; etc etc" "prompt1 response" "prompt2 response" "prompt 3 response".....
#OR ./scrun "apt install whatever" without any prompt response defined manually it will just put 'y' and press enter
#example: ./scrun "apt install emacs-nox; apt remove vim" "y" "Y"
#The above example would install a REAL text editor (emacs) and when prompted by apt "are you sure blah blah?" it'll put
#a y in there and press enter. The second command is then run, uninstalling the beast/demon that is vim. For that one we
#enter a capital Y and then Enter just to make sure that it dies. Any number of prompts are supported, if you don't specify the answer to
#a prompt it will press "y" and then Enter.
# Check if a command is provided
if [ -z "$1" ]; then
echo "Usage: $0 <command>"
exit 1
fi
# Extract the command and optional responses
COMMAND="$1"
shift
RESPONSES=("$@")
# Use default responses if none are provided
if [ ${#RESPONSES[@]} -eq 0 ]; then
RESPONSES=("y" "")
fi
# Define the file to store the session name
SESSION_FILE="/tmp/screen_session_name"
# Check if the session file exists and read the session name
if [ -f "$SESSION_FILE" ]; then
SESSION_NAME=$(cat $SESSION_FILE)
else
SESSION_NAME=""
fi
# Check if the session is still active
if [ -n "$SESSION_NAME" ] && screen -list | grep -q "$SESSION_NAME"; then
echo "Using existing screen session: $SESSION_NAME"
else
# Generate a new unique screen session name and save it
SESSION_NAME="session_$RANDOM"
echo "$SESSION_NAME" > $SESSION_FILE
echo "Creating new screen session: $SESSION_NAME"
screen -dmS $SESSION_NAME bash -c "exec bash"
sleep 1 # Give some time for the session to initialize
fi
# Send the command to the screen session
screen -S $SESSION_NAME -p 0 -X stuff "$COMMAND > /tmp/${SESSION_NAME}_output 2>&1; echo \$? > /tmp/${SESSION_NAME}_exit_code; exec bash\r"
# Function to send responses to prompts
send_responses() {
local session_name=$1
while true; do
for response in "${RESPONSES[@]}"; do
screen -S $session_name -p 0 -X stuff "$response\r"
sleep 1
done
done
}
# Start the response sender in the background
send_responses $SESSION_NAME &
# Monitor the output file for completion
while [ ! -f /tmp/${SESSION_NAME}_exit_code ]; do
sleep 1
done
# Kill the background response sender
pkill -f "send_responses $SESSION_NAME"
# Display the output
if [ -f /tmp/${SESSION_NAME}_output ]; then
cat /tmp/${SESSION_NAME}_output
fi
# Get the exit code
if [ -f /tmp/${SESSION_NAME}_exit_code ]; then
EXIT_CODE=$(cat /tmp/${SESSION_NAME}_exit_code)
else
EXIT_CODE=1
fi
# Clean up temporary files
rm -f /tmp/${SESSION_NAME}_output
rm -f /tmp/${SESSION_NAME}_exit_code
# Notify the user how to connect to the screen session
echo "The screen session is left open. To reconnect, use: screen -r $SESSION_NAME"
# Exit with the same code as the command
exit $EXIT_CODE
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment