Suppressing All SSH Output: Techniques for Truly Silent SSH Operations in Nagios Scripting


1 views

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