While working on Nagios monitoring scripts, I encountered a frustrating limitation with SSH's -q
(quiet) flag. Despite documentation claiming it suppresses "all warning and diagnostic messages", certain errors still leak through:
$ ssh user@localhost -q -p test
Bad port 'test'
In Nagios scripting, the first line of output is crucial for status reporting. When SSH outputs errors before our custom message, it breaks the monitoring logic. We need complete silence from SSH to properly handle:
- Exit code analysis
- Custom status message formatting
- Consistent output parsing
Here are three effective methods to achieve true silence:
1. Redirect All Output Streams
ssh user@host -p 22 -q >/dev/null 2>&1 || echo "Warning|SSH error"
2. Use SSH with Config File
Create ~/.ssh/config
with:
Host *
LogLevel QUIET
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
Then call with:
ssh -F /dev/null -q user@host >/dev/null 2>&1
3. Wrapper Script Approach
For maximum control, implement a bash wrapper:
#!/bin/bash
output=$(ssh -q -o BatchMode=yes user@host 2>&1)
exit_code=$?
if [ $exit_code -ne 0 ]; then
echo "Warning|SSH connection failed (code $exit_code)"
exit 2
else
echo "OK|SSH connection successful"
exit 0
fi
Always verify with both success and failure cases:
# Test successful connection
./check_ssh.sh host.example.com
# Test invalid port
./check_ssh.sh -p invalid host.example.com
# Test timeout case
./check_ssh.sh -o ConnectTimeout=1 unreachable-host
For complex environments, you might need:
- Timeout handling with
-o ConnectTimeout=
- Custom error message differentiation
- SSH connection multiplexing
- Jump host configurations
While working on Nagios monitoring scripts, many developers encounter a frustrating limitation with SSH's -q
flag. The manual states it should suppress "all warning and diagnostic messages," but certain critical errors still leak through:
ssh user@localhost -q -p test
Bad port 'test' # This still appears despite -q
In Nagios/Icinga scripting, the first line of output is typically captured as the status message. When SSH outputs errors before your script can format proper monitoring output, it breaks the expected protocol:
#!/bin/bash
if ! ssh -q -p invalid_port user@host; then
echo "CRITICAL|SSH connection failed" # Never appears as first line
fi
1. Redirect All Output to /dev/null
The most thorough approach to silence SSH completely:
ssh -q -p "$port" user@host &>/dev/null
exit_code=$?
if [ $exit_code -ne 0 ]; then
echo "CRITICAL|SSH Error $exit_code"
exit 2
fi
2. Capture and Filter Output
When you need to preserve legitimate output while filtering errors:
output=$(ssh -q -p "$port" user@host 2>&1 | grep -v '^Bad port')
if [ $? -ne 0 ]; then
echo "CRITICAL|SSH connection failed" >&2
exit 2
fi
3. Validate Inputs Beforehand
For port validation specifically, add pre-checks:
port="test"
if ! [[ "$port" =~ ^[0-9]+$ ]]; then
echo "CRITICAL|Invalid port number" >&2
exit 2
fi
For persistent connections, configure quiet behavior in ~/.ssh/config
:
Host *
LogLevel QUIET
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
Combine with command-line options for maximum suppression:
ssh -o "LogLevel=QUIET" -o "UserKnownHostsFile=/dev/null" -q host
- Always validate inputs before execution
- Use
&>/dev/null
when output isn't needed - Implement proper exit codes (0=OK, 1=WARNING, 2=CRITICAL)
- Prefix status messages with severity level
#!/bin/bash
port=${1:-22}
host=${2:-localhost}
ssh -q -p "$port" "$host" &>/dev/null
case $? in
0) echo "OK|SSH connection successful"; exit 0;;
*) echo "CRITICAL|SSH connection failed"; exit 2;;
esac