When automating system administration tasks with GNU Screen, we often need to:
- Create detached screen sessions
- Execute commands within them
- Maintain session persistence
The standard approach of using screen -d -m -S session_name
works for creation, but command execution becomes tricky when we need to:
# This works only after initial attachment screen -S my_session -X stuff "cd /path/to/scripts$(printf \\r)" screen -S my_session -X stuff "./start_service.sh$(printf \\r)"
Here's a bulletproof method to execute commands in a freshly created screen:
# Create session with initial command screen -dmS maintenance_session /bin/bash -c 'cd /opt/app/; ./maintenance_script.sh; exec bash'
This approach:
- Starts bash as the shell
- Changes directory and runs the script
- Keeps the session alive with 'exec bash'
For scripts that might terminate but need the session to persist:
#!/bin/bash # Create persistent wrapper cat << 'EOF' > /tmp/screen_wrapper.sh #!/bin/bash /path/to/actual_script.sh # Keep shell open after completion exec bash EOF chmod +x /tmp/screen_wrapper.sh screen -dmS persistent_session /tmp/screen_wrapper.sh
For complex initialization sequences:
screen -dmS complex_init bash -c '\ cd /var/log/app/; \ ./rotate_logs.sh; \ ./start_service.sh --debug; \ exec bash'
Add robust checking to your automation:
if ! screen -list | grep -q "maintenance_session"; then screen -dmS maintenance_session bash -c '\ trap "echo Cleaning up..." EXIT; \ ./critical_process.sh; \ exec bash' sleep 1 # Allow time for initialization screen -S maintenance_session -X logfile /var/log/screen_${timestamp}.log screen -S maintenance_session -X log fi
Here's a complete automation script example:
#!/bin/bash SESSION="auto_maintenance" LOG_DIR="/var/log/screen_logs" mkdir -p "$LOG_DIR" # Kill existing session if needed screen -XS "$SESSION" quit # Create new session with persistence screen -dmS "$SESSION" bash -c '\ cd /opt/automation/; \ source ./env_setup.sh; \ while true; do \ ./main_loop.sh; \ sleep 60; \ done; \ exec bash' # Verify creation if screen -list | grep -q "$SESSION"; then # Configure logging timestamp=$(date +%Y%m%d_%H%M%S) screen -S "$SESSION" -X logfile "$LOG_DIR/${SESSION}_${timestamp}.log" screen -S "$SESSION" -X log echo "Session $SESSION created and configured" else echo "Failed to create session $SESSION" >&2 exit 1 fi
When automating server maintenance tasks, many sysadmins need to execute commands in persistent GNU Screen sessions without manual attachment. The standard approach using screen -d -m -S session_name
creates the session, but subsequent command execution often fails until the session has been manually attached at least once.
Here's the most robust method I've found for creating a screen session and immediately executing commands:
# Create screen with initial command
screen -dmS maintenance_session /bin/bash -c 'cd /opt/scripts && ./monitor.sh; exec bash'
This approach:
- Creates detached session (-dm)
- Names the session (-S)
- Runs commands through bash -c
- Keeps session alive with exec bash
For complex command sequences, create a wrapper script:
#!/bin/bash
# maintenance_wrapper.sh
cd /opt/scripts
source ./config.env
./start_monitoring.sh --log-level=debug
exec bash
Then launch with:
screen -dmS monitoring_session ./maintenance_wrapper.sh
The key to keeping the session alive after command completion is the exec bash
trick. This replaces the current shell with a new interactive bash instance after your commands finish.
For existing sessions where you can't modify the initial command:
screen -S existing_session -X stuff $'cd /opt/scripts\n./run.sh\n'
screen -S existing_session -X stuff $'exec bash\n'
Note the use of $''
syntax for proper newline handling.
Here's a complete automation script I use for log rotation:
#!/bin/bash
SESSION="log_rotation_$(date +%s)"
# Create and configure session
screen -dmS $SESSION /bin/bash -c '
cd /var/log
./compress_old_logs.sh
./update_log_index.sh
exec bash
'
# Verify creation
if screen -ls | grep -q $SESSION; then
echo "Rotation session started successfully"
else
echo "Failed to start rotation session" >&2
exit 1
fi