The -t
flag in SSH forces pseudo-terminal allocation, which enables terminal features when running interactive commands remotely. This is particularly useful for:
# Editing files remotely
ssh -t user@server vim /path/to/file
# Running interactive tools
ssh -t user@server top
ssh -t user@server htop
While ssh -t
solves many interactive use cases, there are specific scenarios where it can cause issues:
1. Automated Script Execution
When running scripts remotely, TTY allocation can interfere with output processing:
# Bad practice for automation
ssh -t user@server "/path/to/script.sh"
# Better approach
ssh user@server "/path/to/script.sh"
2. Command Chaining and Piping
TTY allocation adds control characters that can break pipe operations:
# Problematic with -t
ssh -t user@server "ls -l /tmp" | grep ".log"
# Correct approach
ssh user@server "ls -l /tmp" | grep ".log"
3. Background Processes
Processes started with TTY allocation may terminate when SSH disconnects:
# Process may die on disconnect
ssh -t user@server "nohup long_running_process &"
# More reliable without -t
ssh user@server "nohup long_running_process > /dev/null 2>&1 &"
The pseudo-terminal allocation performs several behind-the-scenes operations that can cause unexpected behavior:
- Line buffering instead of block buffering
- Special character interpretation (like Ctrl+C handling)
- Terminal control sequence injection
- Different handling of stdin/stdout/stderr
Follow these guidelines for optimal SSH usage:
# Use -t for:
1. Interactive applications (vim, less, top)
2. Commands requiring terminal features
3. When you need proper signal handling
# Avoid -t for:
1. Script automation
2. Output processing pipelines
3. Background processes
4. Non-interactive bulk operations
Some commands behave differently with/without TTY. You can force non-TTY behavior even when connected interactively:
# Force non-TTY mode for specific command
ssh user@server "script -q -c 'your_command' /dev/null"
The ssh -t
flag forces pseudo-terminal allocation, which enables:
# Working interactive commands
ssh -t user@server vim /path/to/file
# Proper terminal emulation
ssh -t user@server top
Automation and Scripting:
#!/bin/bash
# Bad practice:
result=$(ssh -t user@server "command")
# Better:
result=$(ssh user@server "command")
Command Chaining and Pipes:
# Problematic:
ssh -t user@server "command1 | command2" > output.log
# Preferred:
ssh user@server "command1 | command2" > output.log
Line Buffering Problems:
# With -t: Immediate output
ssh -t user@server "while true; do echo 'test'; sleep 1; done"
# Without -t: Buffered output
ssh user@server "while true; do echo 'test'; sleep 1; done"
Exit Code Corruption:
# With -t (may report incorrect exit status)
ssh -t user@server "false; echo $?"
# Without -t (accurate exit code)
ssh user@server "false; echo $?"
- Use
-t
only when you need terminal features (vim, top, etc.) - Avoid
-t
in scripts and automated processes - Combine carefully with
-T
when needed:ssh -t host1 ssh -T host2
- For complex commands, test both with and without
-t
to observe behavior differences
# Problematic chain:
ssh -t host1 ssh -t host2
# Better approach:
ssh -t host1 ssh -T host2