What's Actually Happening
Your automation scripts or CI/CD pipelines are failing when connecting to SSH servers that display login banners. The script expects clean SSH output but receives multi-line legal disclaimers or welcome messages that break parsing logic. Some scripts even timeout waiting for input or fail to detect successful authentication.
The Error You'll See
In your automation output:
ERROR: Unexpected output before command response
Expected: 'user@host:~$'
Got: '***************************************\n* WARNING: Authorized access only... *\n***************************************'Or using SSH in a script:
#!/bin/bash
output=$(ssh user@server 'hostname')
echo "$output"Outputs:
***************************************
* WARNING: Authorized access only *
* All activity is logged *
***************************************
server-hostnameYour script only wants the hostname but gets the banner too.
Why This Happens
SSH banners are defined in sshd_config with the Banner directive. They display before authentication completes, which means:
- 1.The banner arrives before your command output
- 2.Banners can contain any characters, including ones that break parsers
- 3.Some libraries don't distinguish banner from command output
- 4.The banner is sent to stderr, but some clients mix it with stdout
Step 1: Identify Banner Configuration
Check if the server has a banner configured:
ssh -v user@server 2>&1 | grep -i bannerYou might see:
debug1: SSH2_MSG_USERAUTH_BANNER receivedOn the server, check the configuration:
grep -i banner /etc/ssh/sshd_configLook for:
Banner /etc/issue.netStep 2: Suppress Banner in SSH Client
For your scripts, tell SSH to suppress the banner. There's no direct flag, but you can use LogLevel:
ssh -o LogLevel=ERROR user@server 'command'This suppresses informational messages including banners.
Step 3: Separate Banner from Output
Banners go to stderr, while command output goes to stdout. Capture them separately:
#!/bin/bash
output=$(ssh user@server 'hostname' 2>/dev/null)
echo "Hostname: $output"Or capture both separately:
#!/bin/bash
output=$(ssh user@server 'hostname' 2>&1)
stderr_output=$(ssh user@server 'hostname' 2>&1 1>/dev/null)
echo "Output: $output"
echo "Stderr: $stderr_output"Step 4: Use SSH Config for Automation
Create a dedicated SSH config for scripts:
# ~/.ssh/config.automation
Host *
LogLevel ERROR
BatchMode yes
StrictHostKeyChecking noThen use it:
ssh -F ~/.ssh/config.automation user@server 'command'Step 5: Handle Banner in Python Scripts
Using Paramiko:
```python import paramiko
client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.connect('server', username='user')
# Banner is available separately banner = client.get_transport().get_banner() if banner: print(f"Banner: {banner.decode()}")
# Run command stdin, stdout, stderr = client.exec_command('hostname') print(stdout.read().decode()) ```
Using subprocess:
```python import subprocess
result = subprocess.run( ['ssh', '-o', 'LogLevel=ERROR', 'user@server', 'hostname'], capture_output=True, text=True ) print(result.stdout) # Clean output, no banner ```
Step 6: Disable Banner for Specific Users (Server-Side)
If you control the server, you can disable the banner for automation users:
# /etc/ssh/sshd_config
Match User automation-user
Banner noneThen restart SSH:
sudo systemctl restart sshdStep 7: Parse Around the Banner
If you must work with the banner, skip it programmatically:
#!/bin/bash
output=$(ssh user@server 'echo "---MARKER---"; hostname')
hostname=$(echo "$output" | sed -n '/^---MARKER---$/,$ p' | tail -n +2)
echo "Hostname: $hostname"Verify the Fix
Your scripts handle banners correctly when:
- 1.SSH command output contains only the expected data
- 2.No parsing errors from unexpected characters
- 3.CI/CD pipelines complete without banner-related failures
- 4.Banners are either suppressed or properly separated from command output
Test with a script that verifies clean output:
#!/bin/bash
output=$(ssh -o LogLevel=ERROR user@server 'hostname')
if [[ "$output" =~ ^[a-zA-Z0-9.-]+$ ]]; then
echo "Clean hostname: $output"
else
echo "Unexpected characters in output"
fi