Automating RHEL and Ubuntu Server Inventory Collection Using Bash

Introduction

In a Linux environment, maintaining an up-to-date server inventory is an important part of system administration. Manually collecting information such as hostname, IP address, operating system, kernel version, memory, CPU, DNS configuration, and service status can be time-consuming, especially when managing multiple servers.

In my On-Premises DevOps Infrastructure Project, I created Bash scripts to automate Linux server inventory collection from a central Ansible server.

The solution supports both RHEL and Ubuntu servers and generates a CSV report that can be emailed to the administrator.


Infrastructure

The inventory collection is executed from the Ubuntu-based Ansible server ans01.

RHEL Servers

lamp01
zap01
pup01
web01
db01
jen01
son01

Ubuntu Servers

ans01
kub01
kub02
kub03
tomd01
tomp01
gra01
dock01

The central server connects to each target server using SSH and executes the appropriate collection script with sudo.


Recommended Script Names

I recommend using names that clearly distinguish data collection from inventory processing.

RHEL

rhel_inventory_collect.sh
rhel_inventory.sh
  • rhel_inventory_collect.sh — runs on each RHEL server and collects system information.

  • rhel_inventory.sh — runs from the Ansible server, processes the RHEL server list, collects the data, creates the CSV, and sends the report.

Ubuntu

ubuntu_inventory_collect.sh
ubuntu_inventory.sh
  • ubuntu_inventory_collect.sh — runs on each Ubuntu server and collects system information.

  • ubuntu_inventory.sh — runs from the Ansible server and creates the Ubuntu inventory report.

This naming convention makes the purpose of each script immediately clear.


1. RHEL Inventory Collection

The RHEL collection script gathers:

  • Hostname

  • IP address

  • DNS servers

  • RHEL version

  • Kernel version

  • Chrony status

  • Postfix status

  • Total memory

  • Swap

  • CPU count

  • System manufacturer

The script intentionally does not collect unnecessary information such as SELinux, Firewalld, NTP status, NFS/CIFS mounts, disk details, or partition details.

RHEL Collection Script

Save the script as:

rhel_inventory_collect.sh
#!/bin/bash
# Purpose: Collect basic RHEL system details
# Version: 1.0
# Author: Vallabh Darole

> /tmp/server_check_list

RHOSTNAME=$(hostname)

IPDETAILS=$(hostname -I | xargs)

DNSSERVERS=$(grep '^nameserver' /etc/resolv.conf | awk '{print $2}' | xargs)

OS=$(cat /etc/redhat-release)

KERNELV=$(uname -r)

if systemctl is-active --quiet chronyd; then
    CHRONYD="CHRONYD OK"
else
    CHRONYD="CHRONYD KO"
fi

if systemctl is-active --quiet postfix; then
    MAIL="MAIL OK"
else
    MAIL="MAIL KO"
fi

MEMORY=$(awk '/MemTotal/ {print $2}' /proc/meminfo)

SWAP=$(awk '/SwapTotal/ {print $2}' /proc/meminfo)

CPU=$(grep -c '^processor' /proc/cpuinfo)

MACHINE=$(dmidecode -s system-manufacturer 2>/dev/null | xargs)

echo "$RHOSTNAME,$IPDETAILS,$DNSSERVERS,$OS,$KERNELV,$CHRONYD,$MAIL,$MEMORY,$SWAP,$CPU,$MACHINE" \
>> /tmp/server_check_list

2. RHEL Server List

Create:

rhel_list

with:

lamp01
zap01
pup01
web01
db01
jen01
son01

3. RHEL Inventory Script

Save the main script as:

rhel_inventory.sh

The script:

  1. Reads the RHEL server list.

  2. Removes any previous temporary collection file.

  3. Copies the collection script to the remote server.

  4. Executes it using sudo.

  5. Retrieves the collected information.

  6. Appends the information to a CSV file.

  7. Removes temporary files from the remote server.

  8. Creates an email message.

  9. Sends the inventory report as an attachment.

#!/bin/bash
# Purpose: Collect RHEL server inventory
# Version: 1.0
# Author: Vallabh Darole

echo "Enter your email ID:"
read -r EMAIL

OUTPUT="/tmp/server_check_list.csv"
MESSAGE="/tmp/MESSAGE"
HOSTLIST="/home/ansible/script/rhel_list"

> "$OUTPUT"

echo "HOSTNAME,IPDETAILS,DNSSERVERS,OS,KERNELV,CHRONYD,MAIL,MEMORY(KB),SWAP(KB),CPU,MACHINE" \
>> "$OUTPUT"

while IFS= read -r i
do

    [ -z "$i" ] && continue

    echo "======================================"
    echo "Processing $i..."
    echo "======================================"

    timeout 10 ssh -n "$i" \
        'sudo rm -f /tmp/server_check_list'

    scp -q rhel_inventory_collect.sh \
        "$i:/tmp/rhel_inventory_collect.sh"

    if timeout 10 ssh -n "$i" \
        'sudo bash /tmp/rhel_inventory_collect.sh'
    then

        echo "Collection successful: $i"

        if timeout 10 ssh -n "$i" \
            'sudo cat /tmp/server_check_list' >> "$OUTPUT"
        then
            echo "Data collected: $i"
        else
            echo "ERROR: Unable to collect data from $i"
        fi

    else
        echo "ERROR: Collection failed on $i"
    fi

    timeout 10 ssh -n "$i" \
        'sudo rm -f /tmp/server_check_list /tmp/rhel_inventory_collect.sh'

done < "$HOSTLIST"

DATE=$(date)

{
    echo "Please find the RHEL server inventory created on:"
    echo "$DATE"
    echo
    echo "Servers checked:"
    cat "$HOSTLIST"
} > "$MESSAGE"

mutt -s "RHEL Server Inventory - $DATE" \
    -a "$OUTPUT" -- "$EMAIL" < "$MESSAGE"

echo "RHEL inventory process completed."

4. Ubuntu Inventory Collection

The same approach is used for Ubuntu servers.

The Ubuntu collection script gathers:

  • Hostname

  • IP address

  • DNS servers

  • Ubuntu version

  • Kernel version

  • Time synchronization status

  • Postfix status

  • Memory

  • Swap

  • CPU

  • System manufacturer

The script also checks different time synchronization services because Ubuntu systems may use chrony, chronyd, or systemd-timesyncd.

Save the script as:

ubuntu_inventory_collect.sh
#!/bin/bash
# Purpose: Collect basic Ubuntu system details
# Version: 1.0
# Author: Vallabh Darole

> /tmp/server_check_list

RHOSTNAME=$(hostname)

IPDETAILS=$(hostname -I | xargs)

DNSSERVERS=$(grep '^nameserver' /etc/resolv.conf | awk '{print $2}' | xargs)

OS=$(grep PRETTY_NAME /etc/os-release | cut -d '"' -f 2)

KERNELV=$(uname -r)

if systemctl is-active --quiet chrony; then
    CHRONYD="CHRONY OK"
elif systemctl is-active --quiet chronyd; then
    CHRONYD="CHRONYD OK"
elif systemctl is-active --quiet systemd-timesyncd; then
    CHRONYD="TIMESYNC OK"
else
    CHRONYD="TIME SYNC KO"
fi

if systemctl is-active --quiet postfix; then
    MAIL="MAIL OK"
else
    MAIL="MAIL KO"
fi

MEMORY=$(awk '/MemTotal/ {print $2}' /proc/meminfo)

SWAP=$(awk '/SwapTotal/ {print $2}' /proc/meminfo)

CPU=$(grep -c '^processor' /proc/cpuinfo)

MACHINE=$(sudo dmidecode -s system-manufacturer 2>/dev/null | xargs)

echo "$RHOSTNAME,$IPDETAILS,$DNSSERVERS,$OS,$KERNELV,$CHRONYD,$MAIL,$MEMORY,$SWAP,$CPU,$MACHINE" \
>> /tmp/server_check_list

5. Ubuntu Server List

Create:

ubuntu_list

with:

ans01
kub01
kub02
kub03
tomd01
tomp01
gra01
dock01

Here, ans01 is the Ubuntu Ansible control server itself. Including it allows the same inventory process to collect information from the Ansible server as well.


6. Ubuntu Inventory Script

Save the main script as:

ubuntu_inventory.sh
#!/bin/bash
# Purpose: Collect Ubuntu server inventory
# Version: 1.0
# Author: Vallabh Darole

echo "Enter your email ID:"
read -r EMAIL

OUTPUT="/tmp/ubuntu_server_check_list.csv"
MESSAGE="/tmp/ubuntu_MESSAGE"
HOSTLIST="/home/ansible/script/ubuntu_list"

> "$OUTPUT"

echo "HOSTNAME,IPDETAILS,DNSSERVERS,OS,KERNELV,TIME-SYNC,MAIL,MEMORY(KB),SWAP(KB),CPU,MACHINE" \
>> "$OUTPUT"

while IFS= read -r i
do

    [ -z "$i" ] && continue

    echo "======================================"
    echo "Processing $i..."
    echo "======================================"

    timeout 10 ssh -n "$i" \
        'sudo rm -f /tmp/server_check_list'

    scp -q ubuntu_inventory_collect.sh \
        "$i:/tmp/ubuntu_inventory_collect.sh"

    if timeout 10 ssh -n "$i" \
        'sudo bash /tmp/ubuntu_inventory_collect.sh'
    then

        echo "Collection successful: $i"

        if timeout 10 ssh -n "$i" \
            'sudo cat /tmp/server_check_list' >> "$OUTPUT"
        then
            echo "Data collected: $i"
        else
            echo "ERROR: Unable to collect data from $i"
        fi

    else
        echo "ERROR: Collection failed on $i"
    fi

    timeout 10 ssh -n "$i" \
        'sudo rm -f /tmp/server_check_list /tmp/ubuntu_inventory_collect.sh'

done < "$HOSTLIST"

DATE=$(date)

{
    echo "Please find the Ubuntu server inventory created on:"
    echo "$DATE"
    echo
    echo "Servers checked:"
    cat "$HOSTLIST"
} > "$MESSAGE"

mutt -s "Ubuntu Server Inventory - $DATE" \
    -a "$OUTPUT" -- "$EMAIL" < "$MESSAGE"

echo "Ubuntu inventory process completed."

7. Why ssh -n Is Important

One issue encountered during testing was that only the first server was processed.

The server list contained:

lamp01
zap01
pup01
web01
db01
jen01
son01

but the generated CSV contained only lamp01.

The reason is that ssh can consume input from the same standard input used by the while read loop.

Using:

ssh -n

prevents SSH from reading from the loop's input.

Therefore the script uses:

ssh -n "$i"

for all SSH operations.

This is an important detail when writing Bash automation that processes a list of servers.


8. Temporary File Cleanup

The collection script creates:

/tmp/server_check_list

on the target server.

After retrieving the data, the inventory script removes:

sudo rm -f /tmp/server_check_list

and:

sudo rm -f /tmp/rhel_inventory_collect.sh

or:

sudo rm -f /tmp/ubuntu_inventory_collect.sh

This prevents old inventory information from being appended to a new report.

The collection script also starts with:

> /tmp/server_check_list

This is important because the previous version of the script appended new information to an existing file, resulting in duplicate rows with old and new formats.


9. Directory Structure

The final automation directory on ans01 looks like:

/home/ansible/script/
│
├── rhel_list
├── rhel_inventory.sh
├── rhel_inventory_collect.sh
│
├── ubuntu_list
├── ubuntu_inventory.sh
└── ubuntu_inventory_collect.sh

Generated reports:

/tmp/server_check_list.csv
/tmp/ubuntu_server_check_list.csv

10. Execution

Make the scripts executable:

chmod +x rhel_inventory.sh
chmod +x rhel_inventory_collect.sh
chmod +x ubuntu_inventory.sh
chmod +x ubuntu_inventory_collect.sh

Run the RHEL inventory:

./rhel_inventory.sh

Run the Ubuntu inventory:

./ubuntu_inventory.sh

The generated CSV reports can then be emailed to the operations or infrastructure team.


Benefits

This automation provides several benefits:

  • Reduces manual server inventory collection.

  • Provides consistent information across servers.

  • Supports multiple Linux distributions.

  • Generates a CSV report suitable for Excel.

  • Can be scheduled through cron.

  • Uses the existing Ansible control server.

  • Cleans up temporary files automatically.

  • Handles multiple servers through simple host-list files.

  • Can easily be extended with additional checks.


Future Improvements

The scripts can be further enhanced by:

  1. Adding Ansible instead of direct SSH execution.

  2. Generating Excel .xlsx files instead of CSV.

  3. Adding server reachability checks.

  4. Recording failed servers separately.

  5. Adding execution timestamps.

  6. Adding application/service inventory.

  7. Adding CPU utilization and filesystem utilization.

  8. Storing historical inventory reports.

  9. Scheduling the reports using cron.

  10. Integrating the inventory process with Jenkins.


Conclusion

This Bash-based inventory solution provides a simple and practical way to automate Linux server information collection from a central Ubuntu Ansible server.

Using separate collection and inventory scripts keeps the design modular:

Central Ansible Server
        |
        +---- RHEL Inventory
        |       |
        |       +-- rhel_inventory.sh
        |       +-- rhel_inventory_collect.sh
        |
        +---- Ubuntu Inventory
                |
                +-- ubuntu_inventory.sh
                +-- ubuntu_inventory_collect.sh

This approach can be used as a foundation for a larger Linux infrastructure inventory and health-check automation framework.

No comments:

Post a Comment