When executing remote commands through SSH, developers often need persistent sessions that survive disconnections. The naive approach fails because screen
requires a proper terminal allocation:
ssh user@remote "screen -dmS logs tail -f /var/log/messages" # Won't work directly
GNU Screen demands a terminal for session management. SSH command mode (-c
) doesn't allocate a PTY by default, causing the "Must be connected to a terminal" error. The solution involves forcing pseudo-terminal allocation.
Force pseudo-terminal allocation using SSH's -t
flag combined with screen's detach options:
ssh -t user@remote "screen -S session_name -dm bash -c 'your_command; exec bash'"
Practical example for monitoring logs:
ssh -t admin@server01 "screen -S log_monitor -dm bash -c 'tail -f /var/log/nginx/access.log; exec bash'"
For complex scenarios requiring multiple commands:
ssh -t deploy@prod "screen -S deployment -dm bash -c '
git pull origin master &&
npm install &&
systemctl restart myapp;
exec bash'"
Later reconnection to verify and attach:
ssh -t user@remote "screen -r session_name"
List active sessions:
ssh user@remote "screen -ls"
Bash function for your .bashrc
:
function ssh-screen() {
if [ $# -lt 3 ]; then
echo "Usage: ssh-screen user host session command"
return 1
fi
ssh -t $1@$2 "screen -S $3 -dm bash -c '$4; exec bash'"
}
When administering remote servers, a common pain point emerges: how to execute long-running commands that persist after SSH disconnection. The naive approach fails:
ssh user@host screen "your_command"
This triggers the frustrating "Must be connected to a terminal" error because screen requires a proper TTY allocation.
Modern SSH clients provide the -t
flag to force pseudo-terminal allocation:
ssh -t user@host screen -dmS session_name "your_command"
The flags breakdown:
-t
: Forces pseudo-terminal allocation
-dmS
: Starts screen in detached mode with session naming
For mission-critical deployments, consider this robust pattern:
ssh -t user@host <<'EOF'
screen -S maintenance -dm bash -c '
while true; do
your_script.sh >> /var/log/script_output.log 2>&1
sleep 60
done
'
EOF
To verify and manage your detached sessions:
# List all screen sessions
ssh user@host screen -list
# Attach to specific session
ssh -t user@host screen -r session_name
# Kill unwanted sessions
ssh user@host screen -X -S session_name quit
If you encounter "Cannot open your terminal" errors, force UTF-8 mode:
ssh -t user@host LC_ALL=en_US.UTF-8 screen -md command
For systems with strict environments, wrap in a shell:
ssh -t user@host "bash -lc 'screen -dmS session command'"