shell script to ssh remote machines and print the output of the top command
Categories:
Monitor Remote Servers: SSH and Parse 'top' Command Output

Learn how to create a shell script to securely connect to remote machines via SSH, execute the 'top' command, and capture its output for monitoring and analysis.
Monitoring the resource usage of remote servers is a fundamental task for system administrators and developers. The top
command is an invaluable tool for real-time process monitoring on Unix-like systems. This article will guide you through creating a robust shell script that automates the process of connecting to multiple remote machines via SSH, executing top
, and capturing its output for further analysis or display. We'll cover secure SSH practices, command execution, and basic output parsing.
Understanding the Core Components
Before diving into the script, let's break down the key technologies involved:
- SSH (Secure Shell): A cryptographic network protocol for operating network services securely over an unsecured network. It's essential for remote command execution.
top
command: A dynamic real-time view of a running system. It displays a summary of system information as well as a list of processes or threads currently being managed by the Linux kernel.- Shell Scripting (Bash): A powerful way to automate tasks by combining commands and control structures.
flowchart TD A[Start Script] --> B{Read Server List} B --> C{Loop through each Server} C --> D["Establish SSH Connection (ssh user@host)"] D --> E["Execute 'top -bn1' Command"] E --> F["Capture Output"] F --> G["Process/Display Output"] G --> H{Next Server?} H -- Yes --> C H -- No --> I[End Script]
Workflow for SSHing to remote servers and capturing 'top' output
Prerequisites and Secure SSH Setup
To follow this guide, you'll need:
- A local machine with Bash and SSH client installed.
- Access to one or more remote Linux/Unix servers.
- SSH keys set up for passwordless authentication between your local machine and the remote servers. This is crucial for automation.
To set up SSH keys, if you haven't already:
- Generate an SSH key pair on your local machine:
ssh-keygen -t rsa -b 4096
- Copy your public key to the remote server:
ssh-copy-id user@remote_host
This allows your script to connect without requiring manual password entry, which is vital for automation.
Building the Script: Step-by-Step
Let's construct the script. We'll start with a basic version and then enhance it.
#!/bin/bash
# List of remote servers (user@host format)
SERVERS=(
"user1@server1.example.com"
"user2@server2.example.com"
"user@192.168.1.100"
)
# Loop through each server
for SERVER in "${SERVERS[@]}"; do
echo "========================================"
echo "Fetching 'top' output from: $SERVER"
echo "========================================"
# Execute 'top -bn1' remotely and capture output
# -b: Batch mode (no interactive input)
# -n1: Only one iteration
ssh -o BatchMode=yes -o ConnectTimeout=5 "$SERVER" "top -bn1" 2>&1
# Check if the SSH command was successful
if [ $? -ne 0 ]; then
echo "Error connecting to or executing command on $SERVER"
fi
echo "\n"
done
Basic script to SSH and get 'top' output from multiple servers
Let's break down the key parts of this script:
SERVERS=()
: An array holding the connection strings for your remote machines. Replace the placeholders with your actual user and host details.for SERVER in "${SERVERS[@]}"; do ... done
: This loop iterates through each server in theSERVERS
array.ssh -o BatchMode=yes -o ConnectTimeout=5 "$SERVER" "top -bn1"
: This is the core command.-o BatchMode=yes
: Prevents SSH from asking for a password, ensuring the script runs non-interactively. If SSH keys are not set up, this will cause the connection to fail.-o ConnectTimeout=5
: Sets a timeout of 5 seconds for the connection attempt. This prevents the script from hanging indefinitely if a server is unreachable."$SERVER"
: The target remote host and user."top -bn1"
: The command to execute on the remote server.-b
: Batch mode, which meanstop
will not attempt to read input from the terminal.-n1
: Tellstop
to run for only one iteration and then exit.
2>&1
: Redirects standard error (stderr) to standard output (stdout). This ensures that any error messages from SSH or the remote command are captured and displayed.if [ $? -ne 0 ]; then ... fi
: Checks the exit status of the previous command (ssh
). If it's not zero, an error occurred.
top
command. For example, top -bn1 -w 512
will output with a wider screen, preventing truncation, and top -bn1 | head -n 10
will only show the first 10 lines (summary and a few processes).Enhancing the Script: Error Handling and Output Management
While the basic script works, we can make it more robust by adding better error handling and options for saving output.
#!/bin/bash
# Configuration
SERVERS_FILE="servers.txt" # File containing list of servers (one per line)
OUTPUT_DIR="./top_outputs" # Directory to save output files
SSH_USER="your_username" # Default SSH username if not specified in servers.txt
# Create output directory if it doesn't exist
mkdir -p "$OUTPUT_DIR"
# Check if servers file exists
if [ ! -f "$SERVERS_FILE" ]; then
echo "Error: Server list file '$SERVERS_FILE' not found."
echo "Please create it with one server (user@host or host) per line."
exit 1
fi
# Loop through each server listed in the file
while IFS= read -r SERVER_ENTRY || [[ -n "$SERVER_ENTRY" ]]; do
# Skip empty lines and comments
[[ -z "$SERVER_ENTRY" || "${SERVER_ENTRY:0:1}" == "#" ]] && continue
# Determine full server string (user@host)
if [[ "$SERVER_ENTRY" == *"@"* ]]; then
FULL_SERVER="$SERVER_ENTRY"
else
FULL_SERVER="${SSH_USER}@${SERVER_ENTRY}"
fi
SERVER_HOSTNAME=$(echo "$FULL_SERVER" | cut -d'@' -f2)
OUTPUT_FILE="${OUTPUT_DIR}/${SERVER_HOSTNAME}_top_$(date +%Y%m%d_%H%M%S).txt"
echo "========================================"
echo "Fetching 'top' output from: $FULL_SERVER"
echo "Saving to: $OUTPUT_FILE"
echo "========================================"
# Execute 'top -bn1' remotely and capture output
# Redirect stdout and stderr to the output file
ssh -o BatchMode=yes -o ConnectTimeout=10 "$FULL_SERVER" "top -bn1" > "$OUTPUT_FILE" 2>&1
# Check if the SSH command was successful
if [ $? -ne 0 ]; then
echo "Error connecting to or executing command on $FULL_SERVER. Check '$OUTPUT_FILE' for details."
else
echo "Successfully captured 'top' output."
fi
echo "\n"
done < "$SERVERS_FILE"
Enhanced script with server list file, default user, output directory, and robust error handling.
This enhanced script introduces several improvements:
SERVERS_FILE="servers.txt"
: Reads server list from a file, making it easier to manage many servers.OUTPUT_DIR="./top_outputs"
: Specifies a directory to store the output files.SSH_USER="your_username"
: Allows specifying a default SSH username if the server entry inservers.txt
only contains the hostname.mkdir -p "$OUTPUT_DIR"
: Ensures the output directory exists.- Error Checking for
servers.txt
: Verifies the existence of the server list file. while IFS= read -r SERVER_ENTRY ...
: A robust way to read lines from a file, handling spaces and special characters correctly.- Dynamic
FULL_SERVER
andOUTPUT_FILE
: Constructs the full server string and a unique output filename based on the hostname and current timestamp. - Redirection to File:
> "$OUTPUT_FILE" 2>&1
redirects all output (stdout and stderr) from the SSH command directly into a timestamped file for each server. This is crucial for logging and later analysis.
1. Save the script
Save the enhanced script as monitor_top.sh
.
2. Create servers.txt
Create a file named servers.txt
in the same directory as your script. Populate it with one server entry per line. Examples:
# This is a comment
user@server1.example.com
server2.example.com # Will use SSH_USER for this one
192.168.1.101
3. Make the script executable
Run chmod +x monitor_top.sh
to give it execute permissions.
4. Run the script
Execute the script: ./monitor_top.sh
. It will create a top_outputs
directory and save a file for each server.
5. Review output
Check the top_outputs
directory for the generated files. Each file will contain the top
output for its respective server at the time the script was run.