A significant amount of my work revolves around issues that happen under specific constraints like CPU architecture, amount of RAM, versions of some dependencies, and the list goes on. I was debugging an issue, and I realized I never wrote about this.
At work I have a service named Beaker (based on this project), and as I usually only request one machine at a time, I edit my SSH config file and I put the host name there. So I only need to do ssh beaker
to start working.
A while ago I wrote a dirty bash script that I never touched again because it works wonders. I have it in my path; I call it beaker-sync
, and I use it almost daily.
#!/usr/bin/env bash
DST=`realpath --relative-to="$HOME" .`
HOST=${HOST:-beaker}
rsync -avz --delete --rsync-path="mkdir -p $DST; rsync" . $HOST:$DST;
while inotifywait -r -e modify,create,delete,move ./; do
clear
rsync -avz --delete --rsync-path="mkdir -p $DST; rsync" . $HOST:$DST;
echo -e "\033[0;31mReady\033[0m"
done
I even documented it! I was inspired that day.
Recently I wrote an Ansible script to retrieve a lot of information from a system (to be sure that later I can say, “Oh this issue happened in this scenario but not in this other one”). It’s far from perfect, but I guess now beaker-sync
has a sibiling, beaker-sysinfo
.
---
- name: Gather system information from beaker
hosts: beaker
gather_facts: yes
tasks:
- name: Ensure essential packages are installed on remote host
ansible.builtin.package:
name:
- lshw
- dmidecode
- rsync
- git
- tmux
- golang
- gcc
- gdb
state: present
become: yes
- name: Ensure output directory exists locally (~/Documents/Beaker Reports)
delegate_to: localhost
ansible.builtin.file:
path: "~/Documents/Beaker Reports"
state: directory
mode: '0755'
- name: Get hostname of 'beaker'
ansible.builtin.command: hostname
register: sysinfo_remote_hostname
- name: Get CPU information
ansible.builtin.command: lscpu
register: sysinfo_cpu
- name: Get memory information (human-readable)
ansible.builtin.command: free -h
register: sysinfo_memory_free
- name: Get detailed memory information (from /proc/meminfo)
ansible.builtin.command: cat /proc/meminfo
register: sysinfo_memory_proc
- name: Get physical RAM module details
ansible.builtin.command: dmidecode -t memory
register: sysinfo_memory_dmidecode
become: yes
- name: Get disk space usage
ansible.builtin.command: df -hT
register: sysinfo_disk_df
- name: Get block device information
ansible.builtin.command: lsblk -o NAME,SIZE,TYPE,MOUNTPOINT,FSTYPE,MODEL
register: sysinfo_disk_lsblk
- name: Get OS release information
ansible.builtin.command: cat /etc/os-release
register: sysinfo_os_release
- name: Get kernel and system architecture
ansible.builtin.command: uname -a
register: sysinfo_uname
- name: Get network interface information
ansible.builtin.command: ip a
register: sysinfo_network_ip
- name: Get uptime and load average
ansible.builtin.command: uptime
register: sysinfo_uptime
- name: Get detailed hardware list
ansible.builtin.command: lshw -short
register: sysinfo_lshw_short
become: yes
- name: Get list of all installed packages
ansible.builtin.package_facts:
manager: auto
become: yes
- name: Compile and save system information to a file
delegate_to: localhost
ansible.builtin.copy:
content: |
### System Information Report for {{ sysinfo_remote_hostname.stdout | default('N/A') }} ###
Date: {{ ansible_date_time.iso8601_basic }}
--- Linux Distribution Version ---
OS Family: {{ ansible_facts['os_family'] | default('N/A') }}
Distribution: {{ ansible_facts['distribution'] | default('N/A') }}
Version: {{ ansible_facts['distribution_version'] | default('N/A') }}
Major Version: {{ ansible_facts['distribution_major_version'] | default('N/A') }}
{% if ansible_facts['redhat_release'] is defined %}
RedHat Release: {{ ansible_facts['redhat_release'] }}
{% endif %}
--- CPU Info (lscpu) ---
{{ sysinfo_cpu.stdout | default('N/A') }}
--- Memory Info (free -h) ---
{{ sysinfo_memory_free.stdout | default('N/A') }}
--- Memory Info (/proc/meminfo) ---
{{ sysinfo_memory_proc.stdout | default('N/A') }}
--- Physical RAM Modules (dmidecode -t memory) ---
{{ sysinfo_memory_dmidecode.stdout | default('N/A') }}
--- Disk Space Usage (df -hT) ---
{{ sysinfo_disk_df.stdout | default('N/A') }}
--- Block Devices (lsblk) ---
{{ sysinfo_disk_lsblk.stdout | default('N/A') }}
--- OS Release Information (/etc/os-release) ---
{{ sysinfo_os_release.stdout | default('N/A') }}
--- Kernel and System Architecture (uname -a) ---
{{ sysinfo_uname.stdout | default('N/A') }}
--- Network Interface Information (ip a) ---
{{ sysinfo_network_ip.stdout | default('N/A') }}
--- Uptime and Load Average ---
{{ sysinfo_uptime.stdout | default('N/A') }}
--- Short Hardware List (lshw -short) ---
{{ sysinfo_lshw_short.stdout | default('N/A') }}
--- Installed Packages (DNF/Yum) ---
{% if ansible_facts.packages is defined and ansible_facts.packages | length > 0 %}
{% for pkg_name, versions in ansible_facts.packages.items() %}
- {{ pkg_name }}: {{ versions[0].version }}-{{ versions[0].release }}.{{ versions[0].arch }}
{% endfor %}
{% else %}
(No package facts gathered or no packages installed)
{% endif %}
dest: "~/Documents/Beaker Reports/{{ sysinfo_remote_hostname.stdout }}_{{ ansible_date_time.iso8601_basic }}_sysinfo.txt"
run_once: true
- name: Print report path
delegate_to: localhost
ansible.builtin.debug:
msg: "System information for {{ sysinfo_remote_hostname.stdout }} saved to ~/Documents/Beaker Reports/{{ sysinfo_remote_hostname.stdout }}_{{ ansible_date_time.iso8601_basic }}_sysinfo.txt"
Feel free to use them, the beaker
word is everywhere, but it has nothing special; it will work with any machine.