From a7273dc6d885d1cd083ac2ef56206fccf5d26495 Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:31:40 +0530 Subject: [PATCH 01/39] refactor(structure): reorganize root scripts into scripts/ directory --- cleanup-cache.sh | 20 ----- network-info.sh | 27 ------- scripts/maintenance/cleanup-cache.sh | 52 +++++++++++++ scripts/network/network-info.sh | 70 +++++++++++++++++ scripts/packages/update-system.sh | 55 ++++++++++++++ .../storage/disk-usage.sh | 0 scripts/system/system-info.sh | 75 +++++++++++++++++++ system-info.sh | 35 --------- update-system.sh | 25 ------- 9 files changed, 252 insertions(+), 107 deletions(-) delete mode 100644 cleanup-cache.sh delete mode 100644 network-info.sh create mode 100755 scripts/maintenance/cleanup-cache.sh create mode 100755 scripts/network/network-info.sh create mode 100755 scripts/packages/update-system.sh rename disk-usage.sh => scripts/storage/disk-usage.sh (100%) mode change 100644 => 100755 create mode 100755 scripts/system/system-info.sh delete mode 100644 system-info.sh delete mode 100644 update-system.sh diff --git a/cleanup-cache.sh b/cleanup-cache.sh deleted file mode 100644 index 3e110ec..0000000 --- a/cleanup-cache.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -echo "Cleaning temporary files..." - -if [[ -d /tmp ]]; then - find /tmp -mindepth 1 -maxdepth 1 -user "$USER" -exec rm -rf -- {} + -fi - -if command -v pacman >/dev/null 2>&1; then - echo - echo "Pacman cache:" - du -sh /var/cache/pacman/pkg 2>/dev/null || true - echo - echo "Use 'sudo paccache -r' to safely remove old package versions." -fi - -echo -echo "Cleanup completed." diff --git a/network-info.sh b/network-info.sh deleted file mode 100644 index 335d105..0000000 --- a/network-info.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -echo "================================" -echo " NETWORK INFORMATION" -echo "================================" - -echo -echo "Hostname:" -hostname - -echo -echo "Interfaces:" -ip -brief address - -echo -echo "Default route:" -ip route | grep default || echo "No default route found." - -echo -echo "DNS:" -if command -v resolvectl >/dev/null 2>&1; then - resolvectl status | grep -E 'DNS Servers|Current DNS Server' || true -elif [[ -f /etc/resolv.conf ]]; then - grep '^nameserver' /etc/resolv.conf || true -fi diff --git a/scripts/maintenance/cleanup-cache.sh b/scripts/maintenance/cleanup-cache.sh new file mode 100755 index 0000000..67a3419 --- /dev/null +++ b/scripts/maintenance/cleanup-cache.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash + +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: $(basename "$0") [OPTIONS] + +Clean temporary files and display cache information. + +Options: + -h Show this help message +EOF +} + +if [[ "${1-}" == "-h" ]]; then + show_help + exit 0 +fi + +echo "Cleaning temporary files..." + +if [[ -d /tmp ]]; then + find /tmp -mindepth 1 -maxdepth 1 -user "$USER" -exec rm -rf -- {} + +fi + +if command -v pacman >dev/null 2>&1; then + echo + echo "Pacman cache:" + du -sh /var/cache/pacman/pkg 2>/dev/null || true + echo + echo "Use 'sudo paccache -r' to safely remove old package versions." +fi + +echo +echo "Cleanup completed." +echo "Cleaning temporary files..." + +if [[ -d /tmp ]]; then + find /tmp -mindepth 1 -maxdepth 1 -user "$USER" -exec rm -rf -- {} + +fi + +if command -v pacman >/dev/null 2>&1; then + echo + echo "Pacman cache:" + du -sh /var/cache/pacman/pkg 2>/dev/null || true + echo + echo "Use 'sudo paccache -r' to safely remove old package versions." +fi + +echo +echo "Cleanup completed." diff --git a/scripts/network/network-info.sh b/scripts/network/network-info.sh new file mode 100755 index 0000000..85a691a --- /dev/null +++ b/scripts/network/network-info.sh @@ -0,0 +1,70 @@ +#!/usr/bin/env bash + +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: network-info.sh [options] + +Options: + -h, --help Show this help message and exit + +Description: + Displays information about network hostname, network interfaces, IP addresses, + default routing, and active DNS servers. +EOF + exit 0 +} + +while (( "$#" )); do + case "$1" in + -h|--help) show_help;; + *) echo "Unknown option: $1" >&2; exit 1;; + esac + shift +done + +get_hostname() { + if command -v hostname >/dev/null 2>&1; then + hostname + else + uname -n + fi +} + +echo "================================" +echo " NETWORK INFORMATION " +echo "================================" +echo "" +echo "Hostname:" +get_hostname + +echo "" +echo "Interfaces:" +if command -v ip >/dev/null 2>&1; then + ip -brief address || ip addr +elif command -v ifconfig >/dev/null 2>&1; then + ifconfig +else + echo "Neither 'ip' nor 'ifconfig' command found." +fi + +echo "" +echo "Default route:" +if command -v ip >/dev/null 2>&1; then + ip route | grep default || echo "No default route found." +elif command -v route >/dev/null 2>&1; then + route -n | grep -E '^0.0.0.0' || echo "No default route found." +else + echo "Routing tools not available." +fi + +echo "" +echo "DNS:" +if command -v resolvectl >/dev/null 2>&1; then + resolvectl status 2>/dev/null | grep -E 'DNS Servers|Current DNS Server' || true +elif [[ -f /etc/resolv.conf ]]; then + grep '^nameserver' /etc/resolv.conf || true +else + echo "DNS configuration not found." +fi diff --git a/scripts/packages/update-system.sh b/scripts/packages/update-system.sh new file mode 100755 index 0000000..21eaefd --- /dev/null +++ b/scripts/packages/update-system.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: $(basename "$0") [OPTIONS] + +Options: + -h Show this help message and exit + -n Dry‑run mode: display the commands that would be run without executing them + +Updates the system using the detected package manager (pacman, apt, dnf, zypper). +EOF + exit 0 +} + +# Default values +DRY_RUN=false + +# Parse options +while getopts "hn" opt; do + case "$opt" in + h) show_help ;; + n) DRY_RUN=true ;; + *) show_help ;; + esac +done + +run_cmd() { + if $DRY_RUN; then + echo "[DRY RUN] $*" + else + sudo "$@" + fi +} + +# Detect package manager and perform update +if command -v pacman >/dev/null 2>&1; then + echo "Detected Arch Linux (pacman)" + run_cmd pacman -Syu +elif command -v apt >/dev/null 2>&1; then + echo "Detected Debian/Ubuntu (apt)" + run_cmd apt update + run_cmd apt upgrade -y +elif command -v dnf >/dev/null 2>&1; then + echo "Detected Fedora/RHEL (dnf)" + run_cmd dnf upgrade -y +elif command -v zypper >/dev/null 2>&1; then + echo "Detected openSUSE (zypper)" + run_cmd zypper refresh + run_cmd zypper update +else + echo "Unsupported package manager." + exit 1 +fi diff --git a/disk-usage.sh b/scripts/storage/disk-usage.sh old mode 100644 new mode 100755 similarity index 100% rename from disk-usage.sh rename to scripts/storage/disk-usage.sh diff --git a/scripts/system/system-info.sh b/scripts/system/system-info.sh new file mode 100755 index 0000000..a8d63d8 --- /dev/null +++ b/scripts/system/system-info.sh @@ -0,0 +1,75 @@ +#!/usr/bin/env bash + +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: system-info.sh [options] + +Options: + -h, --help Show this help message and exit + +Description: + Displays basic system information including OS distribution, hostname, + kernel version, architecture, uptime, CPU, memory, and root disk usage. +EOF + exit 0 +} + +while (( "$#" )); do + case "$1" in + -h|--help) show_help;; + *) echo "Unknown option: $1" >&2; exit 1;; + esac + shift +done + +get_hostname() { + if command -v hostname >/dev/null 2>&1; then + hostname + else + uname -n + fi +} + +echo "================================" +echo " SYSTEM INFORMATION " +echo "================================" +echo "" +echo "Hostname : $(get_hostname)" +echo "Kernel : $(uname -r)" +echo "Arch : $(uname -m)" +echo "Uptime : $(uptime -p 2>/dev/null || uptime)" + +if command -v lsb_release >/dev/null 2>&1; then + echo "OS : $(lsb_release -ds)" +elif [[ -f /etc/os-release ]]; then + # shellcheck source=/dev/null + . /etc/os-release + echo "OS : ${PRETTY_NAME:-Linux}" +else + echo "OS : $(uname -s)" +fi + +echo "Shell : ${SHELL##*/}" +echo "User : ${USER:-$(whoami)}" + +echo "" +echo "CPU:" +if command -v lscpu >/dev/null 2>&1; then + lscpu | grep -E 'Model name|CPU\(s\):' | head -n 2 +else + grep -m 1 "model name" /proc/cpuinfo 2>/dev/null || echo "Unknown CPU" +fi + +echo "" +echo "Memory:" +if command -v free >/dev/null 2>&1; then + free -h +else + cat /proc/meminfo | head -n 3 +fi + +echo "" +echo "Root Disk:" +df -h / | tail -n 1 diff --git a/system-info.sh b/system-info.sh deleted file mode 100644 index 079cfd5..0000000 --- a/system-info.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -echo "================================" -echo " SYSTEM INFORMATION" -echo "================================" - -echo -echo "Hostname : $(hostname)" -echo "Kernel : $(uname -r)" -echo "Arch : $(uname -m)" -echo "Uptime : $(uptime -p)" - -if command -v lsb_release >/dev/null 2>&1; then - echo "OS : $(lsb_release -ds)" -elif [[ -f /etc/os-release ]]; then - . /etc/os-release - echo "OS : $PRETTY_NAME" -fi - -echo "Shell : ${SHELL##*/}" -echo "User : $USER" - -echo -echo "CPU:" -lscpu | grep -E 'Model name|CPU\(s\)' | head -n 2 - -echo -echo "Memory:" -free -h - -echo -echo "Disk:" -df -h / | tail -n 1 diff --git a/update-system.sh b/update-system.sh deleted file mode 100644 index 1061bd6..0000000 --- a/update-system.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -if command -v pacman >/dev/null 2>&1; then - echo "Detected Arch Linux" - sudo pacman -Syu - -elif command -v apt >/dev/null 2>&1; then - echo "Detected Debian/Ubuntu" - sudo apt update - sudo apt upgrade - -elif command -v dnf >/dev/null 2>&1; then - echo "Detected Fedora/RHEL" - sudo dnf upgrade - -elif command -v zypper >/dev/null 2>&1; then - echo "Detected openSUSE" - sudo zypper update - -else - echo "Unsupported package manager." - exit 1 -fi From 0220d2fc8aba1e38b7bf16bc9c7fba935e95777c Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:31:47 +0530 Subject: [PATCH 02/39] feat(system): add system-health check utility --- scripts/system/system-health.sh | 46 +++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100755 scripts/system/system-health.sh diff --git a/scripts/system/system-health.sh b/scripts/system/system-health.sh new file mode 100755 index 0000000..58fe039 --- /dev/null +++ b/scripts/system/system-health.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash + +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: $(basename "$0") [OPTIONS] + +Display a quick overview of system health indicators. + +Options: + -h Show this help message +EOF +} + +if [[ "${1-}" == "-h" ]]; then + show_help + exit 0 +fi + +echo "=== System Health Overview ===" + +# Load average +if command -v uptime >/dev/null 2>&1; then + echo "Load average: $(uptime | awk -F'load average:' '{print $2}' | sed 's/^ //')" +fi + +# Memory usage +if command -v free >/dev/null 2>&1; then + echo "Memory usage:" && free -h +fi + +# Disk usage (root) +if command -v df >/dev/null 2>&1; then + echo "Disk usage (root):" && df -h / +fi + +# Top CPU consuming processes (non-root) +if command -v ps >/dev/null 2>&1; then + echo "Top CPU processes:" && ps -eo pid,comm,%cpu --sort=-%cpu | head -n 6 +fi + +# Top memory consuming processes +if command -v ps >/dev/null 2>&1; then + echo "Top memory processes:" && ps -eo pid,comm,%mem --sort=-%mem | head -n 6 +fi From 661bd76d05d7e98d4f6885632c41564463484d51 Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:31:47 +0530 Subject: [PATCH 03/39] feat(system): add kernel-info module and inspection --- scripts/system/kernel-info.sh | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100755 scripts/system/kernel-info.sh diff --git a/scripts/system/kernel-info.sh b/scripts/system/kernel-info.sh new file mode 100755 index 0000000..5436ea9 --- /dev/null +++ b/scripts/system/kernel-info.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: $(basename "$0") [options] + +Options: + -h, --help Show this help message and exit + +Displays kernel information including version, loaded modules, and configuration (if available). +EOF + exit 0 +} + +# Parse arguments +while (( "$#" )); do + case "$1" in + -h|--help) show_help;; + *) echo "Unknown option: $1"; show_help;; + esac + shift +done + +echo "Kernel version:" && uname -r + +echo -e "\nLoaded modules:" && lsmod + +if [[ -r /proc/config.gz ]]; then + echo -e "\nKernel config (compressed):" + zcat /proc/config.gz | head -n 20 +else + echo -e "\nKernel config not available (no /proc/config.gz)." +fi From 34483e3cf97de0ac8f99fff8412484ee6fbb4fdb Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:31:47 +0530 Subject: [PATCH 04/39] feat(system): add boot-info startup analysis --- scripts/system/boot-info.sh | 40 +++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100755 scripts/system/boot-info.sh diff --git a/scripts/system/boot-info.sh b/scripts/system/boot-info.sh new file mode 100755 index 0000000..7551cee --- /dev/null +++ b/scripts/system/boot-info.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: $(basename "$0") [options] + +Options: + -h, --help Show this help message and exit + +Displays recent boot performance information using systemd-analyze and recent boot logs. +EOF + exit 0 +} + +# Parse arguments +while (( "$#" )); do + case "$1" in + -h|--help) show_help;; + *) echo "Unknown option: $1"; show_help;; + esac + shift +done + +if command -v systemd-analyze >/dev/null 2>&1; then + echo "Boot time breakdown:" && systemd-analyze blame + echo -e "\nCritical chain:" && systemd-analyze critical-chain +else + echo "systemd-analyze not available on this system." +fi + +if command -v journalctl >/dev/null 2>&1; then + echo -e "\nRecent boot log (last 20 lines):" + journalctl -b -n 20 +elif [[ -f /var/log/boot.log ]]; then + echo -e "\nRecent boot log (last 20 lines) from /var/log/boot.log:" + tail -n 20 /var/log/boot.log +else + echo "No boot log accessible." +fi From 1e3f774c22be3eb8091e8246414ff5056b81766c Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:31:47 +0530 Subject: [PATCH 05/39] feat(system): add failed-services monitor --- scripts/system/failed-services.sh | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100755 scripts/system/failed-services.sh diff --git a/scripts/system/failed-services.sh b/scripts/system/failed-services.sh new file mode 100755 index 0000000..c8b57a8 --- /dev/null +++ b/scripts/system/failed-services.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: $(basename "$0") [options] + +Options: + -h, --help Show this help message and exit + +Lists systemd services that are in a failed state. +EOF + exit 0 +} + +# Parse arguments +while (( "$#" )); do + case "$1" in + -h|--help) show_help;; + *) echo "Unknown option: $1"; show_help;; + esac + shift +done + +if command -v systemctl >/dev/null 2>&1; then + echo "Failed services:" && systemctl --failed --no-legend || true +else + echo "systemctl not available on this system." +fi From b0d8f441a4ab5a7cfc82f4a95f0eccca4d496cff Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:31:52 +0530 Subject: [PATCH 06/39] feat(storage): add find-large-files utility --- scripts/storage/find-large-files.sh | 35 +++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100755 scripts/storage/find-large-files.sh diff --git a/scripts/storage/find-large-files.sh b/scripts/storage/find-large-files.sh new file mode 100755 index 0000000..aa6f238 --- /dev/null +++ b/scripts/storage/find-large-files.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash + +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: $(basename "$0") [OPTIONS] + +Find files larger than a given size. + +Options: + -s SIZE Size threshold (e.g., 100M, 1G). Default: 100M + -d DIR Directory to search. Default: current directory + -h Show this help message +EOF +} + +SIZE="100M" +DIR="." +while getopts "s:d:h" opt; do + case $opt in + s) SIZE="$OPTARG" ;; + d) DIR="$OPTARG" ;; + h) show_help; exit 0 ;; + *) show_help; exit 1 ;; + esac +done + +if ! command -v find >/dev/null 2>&1; then + echo "Error: 'find' command not found." >&2 + exit 1 +fi + +echo "Searching for files larger than $SIZE in $DIR ..." +find "$DIR" -type f -size +"$SIZE" -exec du -h {} + 2>/dev/null | sort -hr From b15da2fb9a2f8d177b614dd68fe87a047c73c6a1 Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:31:52 +0530 Subject: [PATCH 07/39] feat(storage): add directory-size space calculator --- scripts/storage/directory-size.sh | 32 +++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100755 scripts/storage/directory-size.sh diff --git a/scripts/storage/directory-size.sh b/scripts/storage/directory-size.sh new file mode 100755 index 0000000..489d61b --- /dev/null +++ b/scripts/storage/directory-size.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash + +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: $(basename "$0") [OPTIONS] [DIRECTORY] + +Display the total size of a directory (including subdirectories). +If DIRECTORY is omitted, the current directory is used. + +Options: + -h Show this help message +EOF +} + +if [[ "${1-}" == "-h" ]]; then + show_help + exit 0 +fi + +DIR="${1:-.}" + +if [[ ! -d "$DIR" ]]; then + echo "Error: '$DIR' is not a directory" >&2 + exit 1 +fi + +# Use du to calculate size, suppress errors for inaccessible files. +size=$(du -sh "${DIR}" 2>/dev/null | cut -f1) + +echo "Directory size of '$DIR': $size" From f36fe39318ebb2f9d910c940c69536ed73fe3e7a Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:31:52 +0530 Subject: [PATCH 08/39] feat(storage): add inode-usage monitor and alerts --- scripts/storage/inode-usage.sh | 42 ++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100755 scripts/storage/inode-usage.sh diff --git a/scripts/storage/inode-usage.sh b/scripts/storage/inode-usage.sh new file mode 100755 index 0000000..60d2ba0 --- /dev/null +++ b/scripts/storage/inode-usage.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: $(basename "$0") [options] + +Options: + -h, --help Show this help message and exit + +Displays inode usage for all mounted filesystems and warns if any exceed 90% usage. +EOF + exit 0 +} + +# Parse arguments +while (( "$#" )); do + case "$1" in + -h|--help) show_help;; + *) echo "Unknown option: $1"; show_help;; + esac + shift +done + +if ! command -v df >/dev/null 2>&1; then + echo "df command not found. Cannot display inode usage." + exit 1 +fi + +# Show inode usage +printf "\nInode usage (percentage used):\n" +df -iP | tail -n +2 | awk '{printf "%s %s %s %s %s %s\n", $1, $2, $3, $4, $5, $6}' + +# Warn if any filesystem exceeds 90% inode usage +threshold=90 +while read -r line; do + usage=$(echo "$line" | awk '{print $5}' | tr -d "%") + mount=$(echo "$line" | awk '{print $6}') + if [[ $usage -ge $threshold ]]; then + echo "Warning: $mount inode usage is ${usage}% (above ${threshold}%)" + fi +done < <(df -iP | tail -n +2) From dc67db59abec57838230120922c6c2f7131ee815 Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:31:52 +0530 Subject: [PATCH 09/39] feat(storage): add mount-info filesystem inspector --- scripts/storage/mount-info.sh | 48 +++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100755 scripts/storage/mount-info.sh diff --git a/scripts/storage/mount-info.sh b/scripts/storage/mount-info.sh new file mode 100755 index 0000000..0bdcfd1 --- /dev/null +++ b/scripts/storage/mount-info.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: $(basename "$0") [options] + +Options: + -h, --help Show this help message and exit + -t Show only mounts of the specified filesystem type (e.g., ext4, nfs) + +Displays current mount points and their options. If a type is provided, filters the output. +EOF + exit 0 +} + +# Default values +filter_type="" + +# Parse arguments +while (( "$#" )); do + case "$1" in + -h|--help) show_help;; + -t) + filter_type="$2" + shift 2 + ;; + *) + echo "Unknown option: $1" + show_help + ;; + esac +done + +if ! command -v findmnt >/dev/null 2>&1; then + echo "findmnt command not found. Falling back to /proc/mounts." + if [[ -n "$filter_type" ]]; then + awk -v type="$filter_type" '$3 == type {print $1, $2, $3, $4}' /proc/mounts + else + cat /proc/mounts + fi +else + if [[ -n "$filter_type" ]]; then + findmnt -t "$filter_type" -o SOURCE,TARGET,FSTYPE,OPTIONS + else + findmnt -o SOURCE,TARGET,FSTYPE,OPTIONS + fi +fi From 18cee102692ce0e5d9e0cf629bdbefa078254b78 Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:31:52 +0530 Subject: [PATCH 10/39] feat(storage): add filesystem-info block inspector --- scripts/storage/filesystem-info.sh | 52 ++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100755 scripts/storage/filesystem-info.sh diff --git a/scripts/storage/filesystem-info.sh b/scripts/storage/filesystem-info.sh new file mode 100755 index 0000000..21b80ee --- /dev/null +++ b/scripts/storage/filesystem-info.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: $(basename "$0") [options] + +Options: + -h, --help Show this help message and exit + +Displays filesystem usage information, including size, type, and mount options. +EOF + exit 0 +} + +# Parse arguments +while (( "$#" )); do + case "$1" in + -h|--help) show_help;; + *) echo "Unknown option: $1"; show_help;; + esac + shift +done + +echo "Filesystem size and type (human readable):" +if command -v df >/dev/null 2>&1; then + df -Th +else + echo "df command not found." +fi + +echo -e "\nMount points and options:" +if command -v mount >/dev/null 2>&1; then + mount | column -t +else + echo "mount command not found." +fi + +# Show extended info for ext* filesystems if tune2fs is available +if command -v tune2fs >/dev/null 2>&1; then + echo -e "\nExtended ext* filesystem info:" + while IFS= read -r line; do + dev=$(echo "$line" | awk '{print $1}') + fstype=$(echo "$line" | awk '{print $3}') + if [[ "$fstype" == ext* ]]; then + echo "--- $dev ($fstype) ---" + tune2fs -l "$dev" | grep -E 'Filesystem state|Block count|Free blocks|Inode count|Free inodes' + fi + done < <(df -T | tail -n +2) +else + echo -e "\nFor detailed ext* info, install e2fsprogs (tune2fs)." +fi From 4573a79f72e6b58ddedceb8529165afb8e641027 Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:31:52 +0530 Subject: [PATCH 11/39] feat(storage): add disk-health SMART diagnostics --- scripts/storage/disk-health.sh | 47 ++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100755 scripts/storage/disk-health.sh diff --git a/scripts/storage/disk-health.sh b/scripts/storage/disk-health.sh new file mode 100755 index 0000000..ca51c7e --- /dev/null +++ b/scripts/storage/disk-health.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: $(basename "$0") [options] + +Options: + -h, --help Show this help message and exit + +Scans all attached block devices for SMART health status using smartctl. +If smartctl is not installed, the script will inform the user. +EOF + exit 0 +} + +# Parse arguments +while (( "$#" )); do + case "$1" in + -h|--help) show_help;; + *) echo "Unknown option: $1"; show_help;; + esac + shift +done + +if ! command -v smartctl >/dev/null 2>&1; then + echo "smartctl not found. Please install smartmontools to use this script." + exit 1 +fi + +# Identify block devices (exclude partitions) +devices=$(lsblk -dn -o NAME,TYPE | awk '$2=="disk" {print "/dev/"$1}') +if [[ -z "$devices" ]]; then + echo "No block devices found." + exit 0 +fi + +for dev in $devices; do + echo "=== $dev ===" + # Run health check; ignore non-SMART capable devices + if smartctl -i "$dev" | grep -q "SMART support is: Available"; then + smartctl -H "$dev" || true + else + echo "SMART not supported on $dev" + fi + echo +done From 3444bbc8f80b2f5d1437d6cef0acd48d4e887487 Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:32:00 +0530 Subject: [PATCH 12/39] feat(network): add ping-test and latency checker --- scripts/network/ping-test.sh | 48 ++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100755 scripts/network/ping-test.sh diff --git a/scripts/network/ping-test.sh b/scripts/network/ping-test.sh new file mode 100755 index 0000000..5e7485a --- /dev/null +++ b/scripts/network/ping-test.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: $(basename "$0") [options] [host] + +Options: + -h, --help Show this help message and exit + -c Number of ping packets to send (default: 4) + +Performs a simple ICMP ping test to the specified host (default 8.8.8.8). +The script reports success/failure and average round‑trip time. +EOF + exit 0 +} + +# Default values +count=4 +host="8.8.8.8" + +# Parse arguments +while (( "$#" )); do + case "$1" in + -h|--help) show_help;; + -c) + count="$2" + shift 2 + ;; + *) + host="$1" + shift + ;; + esac +done + +if ! command -v ping >/dev/null 2>&1; then + echo "ping command not found. Install iputils-ping or equivalent." + exit 1 +fi + +echo "Pinging $host with $count packet(s)..." +if ping -c "$count" "$host"; then + echo "Ping succeeded." +else + echo "Ping failed." + exit 1 +fi From 2a25a022fee9f689752d591fc11af8ea496e7dbb Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:32:00 +0530 Subject: [PATCH 13/39] feat(network): add dns-test lookup tool --- scripts/network/dns-test.sh | 50 +++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100755 scripts/network/dns-test.sh diff --git a/scripts/network/dns-test.sh b/scripts/network/dns-test.sh new file mode 100755 index 0000000..ce0088b --- /dev/null +++ b/scripts/network/dns-test.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: $(basename "$0") [options] + +Options: + -h, --help Show this help message and exit + -c Number of DNS queries to perform (default: 1) + +Performs a DNS lookup for the given hostname using dig if available, +otherwise falls back to nslookup. Reports the resolved IP addresses. +EOF + exit 0 +} + +# Default values +count=1 + +# Parse arguments +while (( "$#" )); do + case "$1" in + -h|--help) show_help;; + -c) + count="$2" + shift 2 + ;; + *) + hostname="$1" + shift + ;; + esac +done + +if [[ -z "${hostname:-}" ]]; then + echo "Error: hostname is required." + show_help +fi + +if command -v dig >/dev/null 2>&1; then + echo "Using dig for DNS lookup..." + dig +short "${hostname}" | head -n "$count" +elif command -v nslookup >/dev/null 2>&1; then + echo "Using nslookup for DNS lookup..." + nslookup "$hostname" | awk '/^Address: / {print $2}' | head -n "$count" +else + echo "Neither dig nor nslookup is installed. Cannot perform DNS lookup." + exit 1 +fi From 1f02e86aba64a698d628899f7ba31ad8a6ff3540 Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:32:00 +0530 Subject: [PATCH 14/39] feat(network): add port-check TCP connection test --- scripts/network/port-check.sh | 42 +++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100755 scripts/network/port-check.sh diff --git a/scripts/network/port-check.sh b/scripts/network/port-check.sh new file mode 100755 index 0000000..6d1d9a5 --- /dev/null +++ b/scripts/network/port-check.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash + +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: $(basename "$0") [OPTIONS] HOST PORT + +Check if a TCP port is open on a host. + +Options: + -h Show this help message +EOF +} + +if [[ "${1-}" == "-h" ]]; then + show_help + exit 0 +fi + +if [[ $# -ne 2 ]]; then + echo "Error: HOST and PORT required" >&2 + show_help + exit 1 +fi + +HOST="$1" +PORT="$2" + +if ! command -v nc >/dev/null 2>&1; then + echo "Error: 'nc' (netcat) not found. Install it to use this script." >&2 + exit 1 +fi + +# Try to connect with a timeout of 2 seconds. +if nc -z -w2 "$HOST" "$PORT" >/dev/null 2>&1; then + echo "Port $PORT on $HOST is OPEN" + exit 0 +else + echo "Port $PORT on $HOST is CLOSED or filtered" + exit 1 +fi From b9b6a3f28d48a42d95f0829cbd54e9eef0e05658 Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:32:00 +0530 Subject: [PATCH 15/39] feat(network): add route-info kernel routing table viewer --- scripts/network/route-info.sh | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100755 scripts/network/route-info.sh diff --git a/scripts/network/route-info.sh b/scripts/network/route-info.sh new file mode 100755 index 0000000..86fb7d0 --- /dev/null +++ b/scripts/network/route-info.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: $(basename "$0") [options] + +Options: + -h, --help Show this help message and exit + +Displays the current routing table using ip route (or netstat -r as fallback). +EOF + exit 0 +} + +# Parse arguments +while (( "$#" )); do + case "$1" in + -h|--help) show_help;; + *) echo "Unknown option: $1"; show_help;; + esac + shift +done + +if command -v ip >/dev/null 2>&1; then + ip route show +elif command -v netstat >/dev/null 2>&1; then + netstat -r +else + echo "Neither ip nor netstat commands are available to display routing information." + exit 1 +fi From 12c801306b77cec622b4c65678baf8cabf496ec8 Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:32:00 +0530 Subject: [PATCH 16/39] feat(network): add internet-test WAN connectivity tool --- scripts/network/internet-test.sh | 59 ++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100755 scripts/network/internet-test.sh diff --git a/scripts/network/internet-test.sh b/scripts/network/internet-test.sh new file mode 100755 index 0000000..a816e43 --- /dev/null +++ b/scripts/network/internet-test.sh @@ -0,0 +1,59 @@ +#!/usr/bin/env bash +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: $(basename "$0") [options] [URL] + +Options: + -h, --help Show this help message and exit + -t Timeout for the connection test (default: 5) + +Performs a basic Internet connectivity test by attempting to fetch the +provided URL (default: https://www.google.com) using curl or wget. It +reports success or failure and the HTTP status code if reachable. +EOF + exit 0 +} + +# Default values +url="https://www.google.com" +timeout=5 + +# Parse arguments +while (( "$#" )); do + case "$1" in + -h|--help) show_help;; + -t) + timeout="$2" + shift 2 + ;; + *) + url="$1" + shift + ;; + esac +done + +if command -v curl >/dev/null 2>&1; then + echo "Testing connectivity to $url using curl..." + if curl -s -o /dev/null -w "%{http_code}" --max-time "$timeout" "$url" | grep -q "^[23][0-9][0-9]$"; then + echo "Internet connectivity OK (HTTP success)." + exit 0 + else + echo "Failed to reach $url (curl reported non‑2xx/3xx)." + exit 1 + fi +elif command -v wget >/dev/null 2>&1; then + echo "Testing connectivity to $url using wget..." + if wget -q --timeout=$timeout --spider "$url"; then + echo "Internet connectivity OK (wget succeeded)." + exit 0 + else + echo "Failed to reach $url (wget failed)." + exit 1 + fi +else + echo "Neither curl nor wget is installed. Cannot perform Internet test." + exit 1 +fi From febba46334e356e5c902a0bd5a7e475bdc046e52 Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:32:00 +0530 Subject: [PATCH 17/39] feat(network): add listening-ports socket audit --- scripts/network/listening-ports.sh | 50 ++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100755 scripts/network/listening-ports.sh diff --git a/scripts/network/listening-ports.sh b/scripts/network/listening-ports.sh new file mode 100755 index 0000000..1c6c357 --- /dev/null +++ b/scripts/network/listening-ports.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: $(basename "$0") [options] [port] + +Options: + -h, --help Show this help message and exit + -p Specify a port number to filter results (optional) + +Lists TCP and UDP ports that are currently listening on the system. +If a port is provided, only that port's listening entries are shown. +EOF + exit 0 +} + +# Default values +filter_port="" + +# Parse arguments +while (( "$#" )); do + case "$1" in + -h|--help) show_help;; + -p) + filter_port="$2" + shift 2 + ;; + *) + echo "Unknown option: $1" + show_help + ;; + esac +done + +# Choose command: ss preferred, fallback to netstat +if command -v ss >/dev/null 2>&1; then + cmd="ss -tuln" +elif command -v netstat >/dev/null 2>&1; then + cmd="netstat -tuln" +else + echo "Neither ss nor netstat is available to list listening ports." + exit 1 +fi + +if [[ -n "$filter_port" ]]; then + $cmd | awk "{print} /:$filter_port\b/" +else + $cmd +fi From d33b6c6f1b026fa63944f64b7a3015236e2aaafb Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:32:00 +0530 Subject: [PATCH 18/39] feat(network): add network-diagnostics end-to-end suite --- scripts/network/network-diagnostics.sh | 102 +++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100755 scripts/network/network-diagnostics.sh diff --git a/scripts/network/network-diagnostics.sh b/scripts/network/network-diagnostics.sh new file mode 100755 index 0000000..e1dad2c --- /dev/null +++ b/scripts/network/network-diagnostics.sh @@ -0,0 +1,102 @@ +#!/usr/bin/env bash +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: $(basename "$0") [options] + +Options: + -h, --help Show this help message and exit + +Runs a quick network diagnostics suite: + * Checks internet connectivity (curl or wget) + * Performs a DNS lookup for a default host (google.com) + * Pings a default IP (8.8.8.8) + * Checks common ports (80, 443) on the default gateway +The script reports success/failure for each step but never modifies the system. +EOF + exit 0 +} + +# Default values +host="google.com" +ping_ip="8.8.8.8" +ports="80 443" + +# Parse arguments +while (( "$#" )); do + case "$1" in + -h|--help) show_help;; + *) echo "Unknown option: $1"; show_help;; + esac + shift +done + +echo "--- Network diagnostics start ---" + +# 1. Internet connectivity +if command -v curl >/dev/null 2>&1; then + echo "Testing internet reachability with curl..." + if curl -s -o /dev/null --max-time 5 "https://www.google.com"; then + echo "Internet reachable (curl)." + else + echo "Internet NOT reachable (curl)." + fi +elif command -v wget >/dev/null 2>&1; then + echo "Testing internet reachability with wget..." + if wget -q --timeout=5 --spider "https://www.google.com"; then + echo "Internet reachable (wget)." + else + echo "Internet NOT reachable (wget)." + fi +else + echo "Neither curl nor wget installed; skipping internet test." +fi + +# 2. DNS lookup +if command -v dig >/dev/null 2>&1; then + echo "Performing DNS lookup for $host..." + dig +short "$host" | head -n 3 || echo "DNS lookup failed." +elif command -v nslookup >/dev/null 2>&1; then + echo "Performing DNS lookup for $host..." + nslookup "$host" | awk '/^Address: / {print $2}' | head -n 3 || echo "DNS lookup failed." +else + echo "Neither dig nor nslookup installed; skipping DNS test." +fi + +# 3. Ping test +if command -v ping >/dev/null 2>&1; then + echo "Pinging $ping_ip..." + if ping -c 2 "$ping_ip" >/dev/null; then + echo "Ping successful." + else + echo "Ping failed." + fi +else + echo "ping command not found; skipping ping test." +fi + +# 4. Port checks on default gateway (if reachable) +if command -v ip >/dev/null 2>&1; then + gateway=$(ip route | awk '/default/ {print $3}' | head -n1 || true) + if [[ -n "$gateway" ]]; then + echo "Default gateway detected: $gateway" + for p in $ports; do + echo "Checking TCP port $p on $gateway..." + if command -v nc >/dev/null 2>&1; then + nc -z -w2 "$gateway" "$p" && echo "Port $p open" || echo "Port $p closed" + elif command -v timeout >/dev/null 2>&1 && command -v bash >/dev/null 2>&1; then + timeout 2 bash -c " Date: Thu, 24 Sep 2026 22:32:07 +0530 Subject: [PATCH 19/39] feat(process): add process-info top resource inspector --- scripts/process/process-info.sh | 45 +++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100755 scripts/process/process-info.sh diff --git a/scripts/process/process-info.sh b/scripts/process/process-info.sh new file mode 100755 index 0000000..a40da3a --- /dev/null +++ b/scripts/process/process-info.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash + +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: $(basename "$0") [OPTIONS] + +Display information about running processes. + +Options: + -a Show all processes (default uses ps -e) + -u USER Filter by user + -h Show this help message +EOF +} + +ALL=false +USER_FILTER="" +while getopts "au:h" opt; do + case $opt in + a) ALL=true ;; + u) USER_FILTER="$OPTARG" ;; + h) show_help; exit 0 ;; + *) show_help; exit 1 ;; + esac +done + +if ! command -v ps >/dev/null 2>&1; then + echo "Error: 'ps' command not found." >&2 + exit 1 +fi + +if $ALL; then + CMD="ps -ef" +else + CMD="ps -e" +fi + +if [[ -n "$USER_FILTER" ]]; then + CMD="$CMD -u $USER_FILTER" +fi + +echo "Process list:" +$CMD From 38a0ac2b0478bc68e3f7d8ea8adafd0d451f60db Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:32:07 +0530 Subject: [PATCH 20/39] feat(process): add kill-process safe termination tool --- scripts/process/kill-process.sh | 79 +++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100755 scripts/process/kill-process.sh diff --git a/scripts/process/kill-process.sh b/scripts/process/kill-process.sh new file mode 100755 index 0000000..0afed35 --- /dev/null +++ b/scripts/process/kill-process.sh @@ -0,0 +1,79 @@ +#!/usr/bin/env bash +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: $(basename "$0") [options] + +Options: + -h, --help Show this help message and exit + -s, --signal Signal to send (default: SIGTERM) + -f, --force Skip confirmation prompt (use with caution) + +Safely terminates a process identified by PID or name. By default the script +asks for confirmation before sending the signal. It validates the PID and +ensures the target is not the current shell. +EOF + exit 0 +} + +# Default values +signal="SIGTERM" +force="no" + +# Parse arguments +while (( "$#" )); do + case "$1" in + -h|--help) show_help;; + -s|--signal) + signal="$2" + shift 2 + ;; + -f|--force) + force="yes" + shift + ;; + *) + target="$1" + shift + ;; + esac +done + +if [[ -z "${target:-}" ]]; then + echo "Error: PID or process name is required." + show_help +fi + +# Resolve target to PID(s) +if [[ "$target" =~ ^[0-9]+$ ]]; then + pids=($target) +else + # Use pgrep to find matching processes (exclude this script) + mapfile -t pids < <(pgrep -f "${target}" | grep -vw $$ || true) +fi + +if [[ ${#pids[@]} -eq 0 ]]; then + echo "No matching processes found for '$target'." + exit 1 +fi + +echo "Found ${#pids[@]} matching process(es): ${pids[*]}" + +if [[ "$force" != "yes" ]]; then + read -p "Proceed to send $signal to these process(es)? [y/N] " resp + case "$resp" in + y|Y|yes|YES) ;; + *) echo "Aborted."; exit 0;; + esac +fi + +for pid in "${pids[@]}"; do + if ! kill -0 "$pid" 2>/dev/null; then + echo "Process $pid no longer exists."; continue + fi + echo "Sending $signal to PID $pid..." + kill -s "$signal" "$pid" || echo "Failed to send signal to $pid" +done + +echo "Done." From 8b55789bc3361b8436def34a26cf5b9ca6722919 Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:32:15 +0530 Subject: [PATCH 21/39] feat(packages): add install-package with confirmation --- scripts/packages/install-package.sh | 67 +++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100755 scripts/packages/install-package.sh diff --git a/scripts/packages/install-package.sh b/scripts/packages/install-package.sh new file mode 100755 index 0000000..db1c1e5 --- /dev/null +++ b/scripts/packages/install-package.sh @@ -0,0 +1,67 @@ +#!/usr/bin/env bash +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: $(basename "$0") [options] + +Options: + -h Show this help message and exit + -y Automatically answer yes to any prompts (use with caution) + +Installs the specified package using the detected package manager. +The script will prompt for confirmation unless -y is provided. +EOF + exit 0 +} + +# Default values +AUTOYES=false + +# Parse options +while getopts "hy" opt; do + case "$opt" in + h) show_help ;; + y) AUTOYES=true ;; + *) show_help ;; + esac +done + +shift $((OPTIND -1)) + +if [[ $# -lt 1 ]]; then + echo "Error: package name required." + show_help +fi + +PACKAGE="$1" + +# Detect package manager +if command -v pacman >/dev/null 2>&1; then + PM="pacman" + INSTALL_CMD="pacman -S --noconfirm" +elif command -v apt >/dev/null 2>&1; then + PM="apt" + INSTALL_CMD="apt install -y" +elif command -v dnf >/dev/null 2>&1; then + PM="dnf" + INSTALL_CMD="dnf install -y" +elif command -v zypper >/dev/null 2>&1; then + PM="zypper" + INSTALL_CMD="zypper install -y" +else + echo "Unsupported package manager." + exit 1 +fi + +echo "Detected package manager: $PM" + +if $AUTOYES; then + sudo $INSTALL_CMD "$PACKAGE" +else + read -p "Proceed to install '$PACKAGE' using $PM? [y/N] " resp + case "$resp" in + y|Y|yes|YES) sudo $INSTALL_CMD "$PACKAGE" ;; + *) echo "Installation aborted."; exit 0 ;; + esac +fi From 6c431b5f04ca299781af9baae24e1f7849b6732a Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:32:15 +0530 Subject: [PATCH 22/39] feat(packages): add remove-package with safety checks --- scripts/packages/remove-package.sh | 67 ++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100755 scripts/packages/remove-package.sh diff --git a/scripts/packages/remove-package.sh b/scripts/packages/remove-package.sh new file mode 100755 index 0000000..0ba20b9 --- /dev/null +++ b/scripts/packages/remove-package.sh @@ -0,0 +1,67 @@ +#!/usr/bin/env bash +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: $(basename "$0") [options] + +Options: + -h Show this help message and exit + -y Automatically answer yes to any prompts (use with caution) + +Removes the specified package using the detected package manager. +The script will prompt for confirmation unless -y is provided. +EOF + exit 0 +} + +# Default values +AUTOYES=false + +# Parse options +while getopts "hy" opt; do + case "$opt" in + h) show_help ;; + y) AUTOYES=true ;; + *) show_help ;; + esac +done + +shift $((OPTIND -1)) + +if [[ $# -lt 1 ]]; then + echo "Error: package name required." + show_help +fi + +PACKAGE="$1" + +# Detect package manager +if command -v pacman >/dev/null 2>&1; then + PM="pacman" + REMOVE_CMD="pacman -R --noconfirm" +elif command -v apt >/dev/null 2>&1; then + PM="apt" + REMOVE_CMD="apt remove -y" +elif command -v dnf >/dev/null 2>&1; then + PM="dnf" + REMOVE_CMD="dnf remove -y" +elif command -v zypper >/dev/null 2>&1; then + PM="zypper" + REMOVE_CMD="zypper remove -y" +else + echo "Unsupported package manager." + exit 1 +fi + +echo "Detected package manager: $PM" + +if $AUTOYES; then + sudo $REMOVE_CMD "$PACKAGE" +else + read -p "Proceed to remove '$PACKAGE' using $PM? [y/N] " resp + case "$resp" in + y|Y|yes|YES) sudo $REMOVE_CMD "$PACKAGE" ;; + *) echo "Removal aborted."; exit 0 ;; + esac +fi From 586e3fe90a34fb450b265d8874f56471457cdc9e Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:32:15 +0530 Subject: [PATCH 23/39] feat(packages): add search-package tool --- scripts/packages/search-package.sh | 49 ++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100755 scripts/packages/search-package.sh diff --git a/scripts/packages/search-package.sh b/scripts/packages/search-package.sh new file mode 100755 index 0000000..97bc6d2 --- /dev/null +++ b/scripts/packages/search-package.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: $(basename "$0") [options] + +Options: + -h Show this help message and exit + +Searches the package repositories of the detected package manager for the given term. +The search is performed non‑interactively and does not modify the system. +EOF + exit 0 +} + +# Parse options +while getopts "h" opt; do + case "$opt" in + h) show_help ;; + *) show_help ;; + esac +done + +shift $((OPTIND-1)) + +if [[ $# -lt 1 ]]; then + echo "Error: search term required." + show_help +fi + +TERM="$1" + +if command -v pacman >/dev/null 2>&1; then + echo "Searching with pacman for '$TERM'..." + pacman -Ss "$TERM" | grep -v "^\s*#" +elif command -v apt-cache >/dev/null 2>&1; then + echo "Searching with apt for '$TERM'..." + apt-cache search "$TERM" +elif command -v dnf >/dev/null 2>&1; then + echo "Searching with dnf for '$TERM'..." + dnf search "$TERM" +elif command -v zypper >/dev/null 2>&1; then + echo "Searching with zypper for '$TERM'..." + zypper search "$TERM" +else + echo "Unsupported package manager." + exit 1 +fi From ebd20766f8ac8f884372841877657410b0fb198f Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:32:15 +0530 Subject: [PATCH 24/39] feat(packages): add package-info inspector --- scripts/packages/package-info.sh | 45 ++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100755 scripts/packages/package-info.sh diff --git a/scripts/packages/package-info.sh b/scripts/packages/package-info.sh new file mode 100755 index 0000000..db80330 --- /dev/null +++ b/scripts/packages/package-info.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: $(basename "$0") [options] + +Options: + -h Show this help message and exit + +Shows detailed information about the specified package using the detected +package manager. The script does not modify the system. +EOF + exit 0 +} + +# Parse options +while getopts "h" opt; do + case "$opt" in + h) show_help ;; + *) show_help ;; + esac +done + +shift $((OPTIND-1)) + +if [[ $# -lt 1 ]]; then + echo "Error: package name required." + show_help +fi + +PKG="$1" + +if command -v pacman >/dev/null 2>&1; then + pacman -Qi "$PKG" +elif command -v apt >/dev/null 2>&1; then + apt show "$PKG" +elif command -v dnf >/dev/null 2>&1; then + dnf info "$PKG" +elif command -v zypper >/dev/null 2>&1; then + zypper info "$PKG" +else + echo "Unsupported package manager." + exit 1 +fi From 4496956b9de8b35cbe1309e794d501be700be983 Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:32:15 +0530 Subject: [PATCH 25/39] feat(packages): add package-manager-info detection tool --- scripts/packages/package-manager-info.sh | 39 ++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100755 scripts/packages/package-manager-info.sh diff --git a/scripts/packages/package-manager-info.sh b/scripts/packages/package-manager-info.sh new file mode 100755 index 0000000..d1169bb --- /dev/null +++ b/scripts/packages/package-manager-info.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: $(basename "$0") [options] + +Options: + -h Show this help message and exit + +Detects the system's package manager (pacman, apt, dnf, zypper) and prints +basic information about it (name, version, and a brief description). +EOF + exit 0 +} + +while getopts "h" opt; do + case "$opt" in + h) show_help ;; + *) show_help ;; + esac +done + +if command -v pacman >/dev/null 2>&1; then + echo "Package manager: pacman (Arch Linux)" + pacman --version | head -n1 +elif command -v apt >/dev/null 2>&1; then + echo "Package manager: apt (Debian/Ubuntu)" + apt --version | head -n1 +elif command -v dnf >/dev/null 2>&1; then + echo "Package manager: dnf (Fedora/RHEL)" + dnf --version | head -n1 +elif command -v zypper >/dev/null 2>&1; then + echo "Package manager: zypper (openSUSE)" + zypper --version | head -n1 +else + echo "No supported package manager detected." + exit 1 +fi From 125c604a013ab814863a61174d774ceb6b56d920 Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:32:22 +0530 Subject: [PATCH 26/39] feat(hardware): add cpu-info and hardware-summary --- scripts/hardware/cpu-info.sh | 36 +++++++++++++++ scripts/hardware/hardware-summary.sh | 65 ++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100755 scripts/hardware/cpu-info.sh create mode 100755 scripts/hardware/hardware-summary.sh diff --git a/scripts/hardware/cpu-info.sh b/scripts/hardware/cpu-info.sh new file mode 100755 index 0000000..8d4218b --- /dev/null +++ b/scripts/hardware/cpu-info.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: $(basename "$0") [options] + +Options: + -h Show this help message and exit + +Displays CPU information using lscpu (if available) and /proc/cpuinfo. +The script is read‑only and safe to run on any Linux system. +EOF + exit 0 +} + +while getopts "h" opt; do + case "$opt" in + h) show_help ;; + *) show_help ;; + esac +done + +echo "=== lscpu output (if available) ===" +if command -v lscpu >/dev/null 2>&1; then + lscpu +else + echo "lscpu not found." +fi + +echo -e "\n=== /proc/cpuinfo (first 20 lines) ===" +if [[ -r /proc/cpuinfo ]]; then + head -n 20 /proc/cpuinfo +else + echo "/proc/cpuinfo not readable." +fi diff --git a/scripts/hardware/hardware-summary.sh b/scripts/hardware/hardware-summary.sh new file mode 100755 index 0000000..49de137 --- /dev/null +++ b/scripts/hardware/hardware-summary.sh @@ -0,0 +1,65 @@ +#!/usr/bin/env bash +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: $(basename "$0") [options] + +Options: + -h Show this help message and exit + +Displays a summary of hardware information by invoking the individual +hardware utility scripts (cpu, gpu, memory, usb, pci, battery). +The script simply aggregates their outputs; it does not modify the system. +EOF + exit 0 +} + +while getopts "h" opt; do + case "$opt" in + h) show_help ;; + *) show_help ;; + esac +done + +echo "=== CPU Information ===" +if [[ -x "$(dirname "$0")/../hardware/cpu-info.sh" ]]; then + "$(dirname "$0")/../hardware/cpu-info.sh" || true +else + echo "cpu-info.sh not found or not executable" +fi + +echo -e "\n=== GPU Information ===" +if [[ -x "$(dirname "$0")/../hardware/gpu-info.sh" ]]; then + "$(dirname "$0")/../hardware/gpu-info.sh" || true +else + echo "gpu-info.sh not found or not executable" +fi + +echo -e "\n=== Memory Information ===" +if [[ -x "$(dirname "$0")/../hardware/memory-info.sh" ]]; then + "$(dirname "$0")/../hardware/memory-info.sh" || true +else + echo "memory-info.sh not found or not executable" +fi + +echo -e "\n=== USB Devices ===" +if [[ -x "$(dirname "$0")/../hardware/usb-devices.sh" ]]; then + "$(dirname "$0")/../hardware/usb-devices.sh" || true +else + echo "usb-devices.sh not found or not executable" +fi + +echo -e "\n=== PCI Devices ===" +if [[ -x "$(dirname "$0")/../hardware/pci-devices.sh" ]]; then + "$(dirname "$0")/../hardware/pci-devices.sh" || true +else + echo "pci-devices.sh not found or not executable" +fi + +echo -e "\n=== Battery Information ===" +if [[ -x "$(dirname "$0")/../hardware/battery-info.sh" ]]; then + "$(dirname "$0")/../hardware/battery-info.sh" || true +else + echo "battery-info.sh not found or not executable" +fi From 618d26bba96e671f181938f77f240d732d4d75ba Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:32:22 +0530 Subject: [PATCH 27/39] feat(hardware): add gpu-info graphics detection --- scripts/hardware/gpu-info.sh | 50 ++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100755 scripts/hardware/gpu-info.sh diff --git a/scripts/hardware/gpu-info.sh b/scripts/hardware/gpu-info.sh new file mode 100755 index 0000000..b2d621e --- /dev/null +++ b/scripts/hardware/gpu-info.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash + +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: gpu-info.sh [options] + +Options: + -h, --help Show this help message and exit + +Description: + Detects and displays basic information about GPUs present on the system. + It uses 'lspci' to list PCI devices and optionally 'glxinfo' for OpenGL details. +EOF + exit 0 +} + +# Parse options +while (( "$#" )); do + case "$1" in + -h|--help) show_help;; + *) echo "Unknown option: $1" >&2; exit 1;; + esac + shift +done + +# Check required commands +if ! command -v lspci >/dev/null 2>&1; then + echo "Error: 'lspci' command not found. Install pciutils." >&2 + exit 1 +fi + +# Find GPU entries +GPU_DEVS=$(lspci -nn | grep -i "vga\|3d\|display" || true) +if [[ -z "$GPU_DEVS" ]]; then + echo "No GPU devices detected." + exit 0 +fi + +echo "Detected GPU(s):" +printf "%s\n" "$GPU_DEVS" + +# Optional OpenGL info +if command -v glxinfo >/dev/null 2>&1; then + echo "\nOpenGL renderer information (via glxinfo):" + glxinfo | grep -i "renderer" | head -n 5 || true +else + echo "\nTip: Install 'mesa-utils' to get OpenGL details via glxinfo." +fi From 70b4f6c5eec5da2e97f20469b9a73ec6263de98c Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:32:22 +0530 Subject: [PATCH 28/39] feat(hardware): add memory-info RAM analyzer --- scripts/hardware/memory-info.sh | 39 +++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100755 scripts/hardware/memory-info.sh diff --git a/scripts/hardware/memory-info.sh b/scripts/hardware/memory-info.sh new file mode 100755 index 0000000..821dfea --- /dev/null +++ b/scripts/hardware/memory-info.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash + +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: memory-info.sh [options] + +Options: + -h, --help Show this help message and exit + +Description: + Displays total and free memory information. + Uses 'free -h' for a human‑readable summary and + prints the first few lines of /proc/meminfo for details. +EOF + exit 0 +} + +# Parse arguments +while (( "$#" )); do + case "$1" in + -h|--help) show_help;; + *) echo "Unknown option: $1" >&2; exit 1;; + esac + shift +done + +# Ensure required commands are present +if ! command -v free >/dev/null 2>&1; then + echo "Error: 'free' command not found. Install procps." >&2 + exit 1 +fi + +echo "Memory usage (human readable):" +free -h + +echo "\nDetailed memory info from /proc/meminfo (first 20 lines):" +head -n 20 /proc/meminfo From 4c57111fc588fb76a40317d7471fa36bc9dba242 Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:32:22 +0530 Subject: [PATCH 29/39] feat(hardware): add usb-devices and pci-devices listing tools --- scripts/hardware/pci-devices.sh | 32 +++++++++++++++++++++++ scripts/hardware/usb-devices.sh | 46 +++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100755 scripts/hardware/pci-devices.sh create mode 100755 scripts/hardware/usb-devices.sh diff --git a/scripts/hardware/pci-devices.sh b/scripts/hardware/pci-devices.sh new file mode 100755 index 0000000..4e0d2b7 --- /dev/null +++ b/scripts/hardware/pci-devices.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash + +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: pci-devices.sh [options] + +Options: + -h, --help Show this help message and exit + +Description: + Lists PCI devices present on the system using 'lspci'. +EOF + exit 0 +} + +while (( "$#" )); do + case "$1" in + -h|--help) show_help;; + *) echo "Unknown option: $1" >&2; exit 1;; + esac + shift +done + +if ! command -v lspci >/dev/null 2>&1; then + echo "Error: 'lspci' command not found. Please install pciutils." >&2 + exit 1 +fi + +echo "=== PCI Devices ===" +lspci diff --git a/scripts/hardware/usb-devices.sh b/scripts/hardware/usb-devices.sh new file mode 100755 index 0000000..72bda4b --- /dev/null +++ b/scripts/hardware/usb-devices.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash + +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: usb-devices.sh [options] + +Options: + -h, --help Show this help message and exit + +Description: + Lists USB devices attached to the system using 'lsusb'. + If 'lsusb' is not installed, it falls back to reading /sys/bus/usb/devices/. +EOF + exit 0 +} + +while (( "$#" )); do + case "$1" in + -h|--help) show_help;; + *) echo "Unknown option: $1" >&2; exit 1;; + esac + shift +done + +echo "=== USB Devices ===" +if command -v lsusb >/dev/null 2>&1; then + lsusb +elif [[ -d /sys/bus/usb/devices ]]; then + found=0 + for dev in /sys/bus/usb/devices/*; do + if [[ -f "$dev/product" ]]; then + prod=$(cat "$dev/product" 2>/dev/null || true) + manuf=$(cat "$dev/manufacturer" 2>/dev/null || true) + echo "$(basename "$dev"): ${manuf:+[$manuf] }${prod}" + found=1 + fi + done + if [[ $found -eq 0 ]]; then + echo "No USB devices detected in /sys/bus/usb/devices." + fi +else + echo "Error: 'lsusb' not found and /sys/bus/usb/devices is unavailable." >&2 + exit 1 +fi From 65c4275b44c35353c1bf9e9810c3a0040510560c Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:32:22 +0530 Subject: [PATCH 30/39] feat(hardware): add battery-info power supply monitor --- scripts/hardware/battery-info.sh | 57 ++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100755 scripts/hardware/battery-info.sh diff --git a/scripts/hardware/battery-info.sh b/scripts/hardware/battery-info.sh new file mode 100755 index 0000000..aa5c933 --- /dev/null +++ b/scripts/hardware/battery-info.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash + +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: battery-info.sh [options] + +Options: + -h, --help Show this help message and exit + +Description: + Displays battery status and power supply information. + Uses 'upower' if available, otherwise queries /sys/class/power_supply/. +EOF + exit 0 +} + +while (( "$#" )); do + case "$1" in + -h|--help) show_help;; + *) echo "Unknown option: $1" >&2; exit 1;; + esac + shift +done + +echo "=== Battery & Power Information ===" +found=0 + +if command -v upower >/dev/null 2>&1; then + devices=$(upower -e | grep -E 'battery|DisplayDevice' || true) + if [[ -n "$devices" ]]; then + while IFS= read -r dev; do + [[ -z "$dev" ]] && continue + echo "--- Device: $dev ---" + upower -i "$dev" | grep -E "state|to\ full|percentage|capacity|technology|model|vendor" || true + found=1 + done <<< "$devices" + fi +fi + +if [[ $found -eq 0 && -d /sys/class/power_supply ]]; then + for ps in /sys/class/power_supply/*; do + if [[ -d "$ps" ]]; then + type=$(cat "$ps/type" 2>/dev/null || echo "Unknown") + echo "--- Power Supply: $(basename "$ps") ($type) ---" + [[ -f "$ps/status" ]] && echo "Status: $(cat "$ps/status")" + [[ -f "$ps/capacity" ]] && echo "Capacity: $(cat "$ps/capacity")%" + [[ -f "$ps/health" ]] && echo "Health: $(cat "$ps/health")" + found=1 + fi + done +fi + +if [[ $found -eq 0 ]]; then + echo "No battery or power supply devices detected (common in desktop or VM environments)." +fi From 6d36b95500279320d8172566c789076e05493906 Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:32:26 +0530 Subject: [PATCH 31/39] feat(ssh): add ssh-key-setup and ssh-config-check --- scripts/ssh/ssh-config-check.sh | 40 +++++++++++++++ scripts/ssh/ssh-key-setup.sh | 91 +++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100755 scripts/ssh/ssh-config-check.sh create mode 100755 scripts/ssh/ssh-key-setup.sh diff --git a/scripts/ssh/ssh-config-check.sh b/scripts/ssh/ssh-config-check.sh new file mode 100755 index 0000000..113bd10 --- /dev/null +++ b/scripts/ssh/ssh-config-check.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash + +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: ssh-config-check.sh [options] + +Options: + -h, --help Show this help message and exit + +Description: + Validates the syntax of the user's SSH client configuration file (~/.ssh/config). + It runs 'ssh -G ' which forces ssh to parse the config. + Any syntax errors are reported. No changes are made. +EOF + exit 0 +} + +while (( "$#" )); do + case "$1" in + -h|--help) show_help;; + *) echo "Unknown option: $1" >&2; exit 1;; + esac + shift +done + +CONFIG_FILE="$HOME/.ssh/config" +if [[ ! -f "$CONFIG_FILE" ]]; then + echo "SSH config file not found at $CONFIG_FILE. Nothing to validate." + exit 0 +fi + +# Use a dummy host to force parsing; ssh will ignore unknown host but parse config. +if ssh -G dummyhost >/dev/null 2>&1; then + echo "SSH config syntax is valid." +else + echo "SSH config contains syntax errors." + exit 1 +fi diff --git a/scripts/ssh/ssh-key-setup.sh b/scripts/ssh/ssh-key-setup.sh new file mode 100755 index 0000000..b3912a7 --- /dev/null +++ b/scripts/ssh/ssh-key-setup.sh @@ -0,0 +1,91 @@ +#!/usr/bin/env bash + +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: ssh-key-setup.sh [options] + +Options: + -h, --help Show this help message and exit + -t, --type TYPE Key type to generate (ed25519 or rsa; default: ed25519) + -c, --comment TEXT Key comment (default: user@hostname) + -f, --force Overwrite existing key if present (with confirmation) + +Description: + Checks existing SSH keys and optionally generates a new secure key pair. + Defaults to modern Ed25519 keys and never overwrites existing keys without confirmation. +EOF + exit 0 +} + +KEY_TYPE="ed25519" +COMMENT="" +FORCE=false + +while (( "$#" )); do + case "$1" in + -h|--help) show_help;; + -t|--type) + shift + KEY_TYPE="${1:-ed25519}" + ;; + -c|--comment) + shift + COMMENT="${1:-}" + ;; + -f|--force) FORCE=true;; + *) echo "Unknown option: $1" >&2; exit 1;; + esac + shift +done + +if [[ -z "$COMMENT" ]]; then + hname=$(command -v hostname >/dev/null 2>&1 && hostname || uname -n) + COMMENT="$(whoami)@$hname" +fi + +SSH_DIR="$HOME/.ssh" +mkdir -p "$SSH_DIR" +chmod 700 "$SSH_DIR" + +TARGET_KEY="$SSH_DIR/id_$KEY_TYPE" + +echo "=== SSH Key Setup ===" +echo "Checking existing keys in $SSH_DIR:" +existing_keys=0 +for pub in "$SSH_DIR"/*.pub; do + if [[ -f "$pub" ]]; then + echo " Found: $pub" + existing_keys=$((existing_keys + 1)) + fi +done + +if [[ -f "$TARGET_KEY" ]]; then + echo "Target key '$TARGET_KEY' already exists." + if [[ "$FORCE" == false ]]; then + echo "Use -f / --force to regenerate this key." + exit 0 + fi + read -rp "Are you sure you want to overwrite '$TARGET_KEY'? [y/N]: " confirm + case "$confirm" in + [yY]|[yY][eE][sS]) ;; + *) echo "Operation cancelled."; exit 0;; + esac +fi + +if ! command -v ssh-keygen >/dev/null 2>&1; then + echo "Error: 'ssh-keygen' command not found. Install openssh-client." >&2 + exit 1 +fi + +echo "Generating $KEY_TYPE SSH key pair..." +ssh-keygen -t "$KEY_TYPE" -C "$COMMENT" -f "$TARGET_KEY" + +echo "" +echo "Key successfully generated!" +echo "Private key: $TARGET_KEY" +echo "Public key : $TARGET_KEY.pub" +echo "" +echo "Public key contents:" +cat "$TARGET_KEY.pub" From 6968ef5e6f4295c00a55cdfb0b46254e8f7eb10c Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:32:26 +0530 Subject: [PATCH 32/39] feat(ssh): add ssh-host-info and read-only ssh-hardening-check --- scripts/ssh/ssh-hardening-check.sh | 88 ++++++++++++++++++++++++++++++ scripts/ssh/ssh-host-info.sh | 84 ++++++++++++++++++++++++++++ 2 files changed, 172 insertions(+) create mode 100755 scripts/ssh/ssh-hardening-check.sh create mode 100755 scripts/ssh/ssh-host-info.sh diff --git a/scripts/ssh/ssh-hardening-check.sh b/scripts/ssh/ssh-hardening-check.sh new file mode 100755 index 0000000..57fdfd3 --- /dev/null +++ b/scripts/ssh/ssh-hardening-check.sh @@ -0,0 +1,88 @@ +#!/usr/bin/env bash + +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: ssh-hardening-check.sh [options] + +Options: + -h, --help Show this help message and exit + -c, --config FILE Path to sshd_config (default: /etc/ssh/sshd_config) + +Description: + READ-ONLY security audit tool for OpenSSH daemon (sshd) configuration. + Inspects key hardening recommendations (root login, password auth, empty passwords, + authentication attempts, etc.) and reports findings with recommendations. + NEVER modifies or rewrites configuration files. +EOF + exit 0 +} + +CONFIG_FILE="/etc/ssh/sshd_config" + +while (( "$#" )); do + case "$1" in + -h|--help) show_help;; + -c|--config) + shift + CONFIG_FILE="${1:-/etc/ssh/sshd_config}" + ;; + *) echo "Unknown option: $1" >&2; exit 1;; + esac + shift +done + +echo "=== SSH Daemon Security Hardening Audit ===" +echo "Target config: $CONFIG_FILE" +echo "Note: This check is strictly READ-ONLY." +echo "" + +if [[ ! -r "$CONFIG_FILE" ]]; then + if [[ -f "$CONFIG_FILE" ]]; then + echo "Warning: $CONFIG_FILE exists but is not readable without root privileges." + echo "Tip: Run with sudo or inspect as root to read the config." + exit 0 + else + echo "Notice: $CONFIG_FILE not found on this system." + exit 0 + fi +fi + +get_sshd_setting() { + local key="$1" + # Search active (uncommented) directives first, case-insensitive + local val + val=$(grep -i -E "^[[:space:]]*${key}[[:space:]]+" "$CONFIG_FILE" 2>/dev/null | tail -n 1 | awk '{print $2}' || true) + if [[ -z "$val" && -d "/etc/ssh/sshd_config.d" ]]; then + val=$(grep -h -i -E "^[[:space:]]*${key}[[:space:]]+" /etc/ssh/sshd_config.d/*.conf 2>/dev/null | tail -n 1 | awk '{print $2}' || true) + fi + echo "$val" +} + +check_rule() { + local name="$1" + local key="$2" + local recommended="$3" + local current + current=$(get_sshd_setting "$key") + + printf "%-32s " "$name:" + if [[ -z "$current" ]]; then + echo "DEFAULT / NOT SET (Recommended: $recommended)" + elif [[ "${current,,}" == "${recommended,,}" ]]; then + echo "PASS ($current)" + else + echo "WARN (Current: $current | Recommended: $recommended)" + fi +} + +check_rule "PermitRootLogin" "PermitRootLogin" "no" +check_rule "PasswordAuthentication" "PasswordAuthentication" "no" +check_rule "PermitEmptyPasswords" "PermitEmptyPasswords" "no" +check_rule "X11Forwarding" "X11Forwarding" "no" +check_rule "MaxAuthTries" "MaxAuthTries" "4" +check_rule "ClientAliveCountMax" "ClientAliveCountMax" "2" + +echo "" +echo "Hardening check completed. All recommendations are advisory." diff --git a/scripts/ssh/ssh-host-info.sh b/scripts/ssh/ssh-host-info.sh new file mode 100755 index 0000000..33e8700 --- /dev/null +++ b/scripts/ssh/ssh-host-info.sh @@ -0,0 +1,84 @@ +#!/usr/bin/env bash + +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: ssh-host-info.sh [options] [hostname|IP] + +Options: + -h, --help Show this help message and exit + -p, --port NUM SSH port (default: 22) + +Description: + Retrieves SSH host key fingerprints and server banner for a target host. + If no host is given, summarizes known hosts in ~/.ssh/known_hosts. +EOF + exit 0 +} + +PORT=22 +TARGET="" + +while (( "$#" )); do + case "$1" in + -h|--help) show_help;; + -p|--port) + shift + PORT="${1:-22}" + ;; + -*) echo "Unknown option: $1" >&2; exit 1;; + *) + if [[ -z "$TARGET" ]]; then + TARGET="$1" + else + echo "Unexpected argument: $1" >&2 + exit 1 + fi + ;; + esac + shift +done + +echo "=== SSH Host Info ===" + +if [[ -z "$TARGET" ]]; then + KNOWN_HOSTS="$HOME/.ssh/known_hosts" + if [[ -f "$KNOWN_HOSTS" ]]; then + count=$(grep -c -v '^#' "$KNOWN_HOSTS" 2>/dev/null || echo 0) + echo "Known hosts file: $KNOWN_HOSTS" + echo "Total entries: $count" + echo "Recent host entries:" + tail -n 10 "$KNOWN_HOSTS" | awk '{print $1}' + else + echo "No ~/.ssh/known_hosts found." + fi + echo "" + echo "Tip: Run '$0 ' to query remote host fingerprints." + exit 0 +fi + +if ! command -v ssh-keyscan >/dev/null 2>&1; then + echo "Error: 'ssh-keyscan' command not found. Install openssh-client." >&2 + exit 1 +fi + +echo "Querying host keys for $TARGET on port $PORT..." +keys=$(ssh-keyscan -p "$PORT" -T 5 "$TARGET" 2>/dev/null || true) + +if [[ -z "$keys" ]]; then + echo "Could not reach SSH service on $TARGET:$PORT." + exit 1 +fi + +echo "Detected Host Keys:" +while IFS= read -r line; do + [[ -z "$line" || "$line" =~ ^# ]] && continue + key_type=$(echo "$line" | awk '{print $2}') + if command -v ssh-keygen >/dev/null 2>&1; then + fp=$(echo "$line" | ssh-keygen -lf - 2>/dev/null || true) + echo " $key_type: $fp" + else + echo " $key_type" + fi +done <<< "$keys" From 636c727fbcf25e58585dafbcc328f748013f0807 Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:32:32 +0530 Subject: [PATCH 33/39] feat(developer): add dev-environment-info, git-info, and docker-info --- scripts/developer/dev-environment-info.sh | 63 +++++++++++++++++++++++ scripts/developer/docker-info.sh | 47 +++++++++++++++++ scripts/developer/git-info.sh | 58 +++++++++++++++++++++ 3 files changed, 168 insertions(+) create mode 100755 scripts/developer/dev-environment-info.sh create mode 100755 scripts/developer/docker-info.sh create mode 100755 scripts/developer/git-info.sh diff --git a/scripts/developer/dev-environment-info.sh b/scripts/developer/dev-environment-info.sh new file mode 100755 index 0000000..5a7263e --- /dev/null +++ b/scripts/developer/dev-environment-info.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash + +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: dev-environment-info.sh [options] + +Options: + -h, --help Show this help message and exit + +Description: + Inspects the system and reports detected programming languages, compilers, + runtimes, package managers, and developer tools. +EOF + exit 0 +} + +while (( "$#" )); do + case "$1" in + -h|--help) show_help;; + *) echo "Unknown option: $1" >&2; exit 1;; + esac + shift +done + +echo "=== Developer Environment Summary ===" + +check_tool() { + local name="$1" + local cmd="$2" + local ver_flag="${3:---version}" + + printf "%-18s: " "$name" + if command -v "$cmd" >/dev/null 2>&1; then + local ver + ver=$("$cmd" $ver_flag 2>&1 | head -n 1 || echo "installed") + echo "$ver ($cmd)" + else + echo "Not installed" + fi +} + +echo "[Core SCM & Build]" +check_tool "Git" "git" "--version" +check_tool "Make" "make" "--version" +check_tool "CMake" "cmake" "--version" +check_tool "GCC" "gcc" "--version" +check_tool "Clang" "clang" "--version" + +echo "" +echo "[Runtimes & Interpreters]" +check_tool "Python 3" "python3" "--version" +check_tool "Node.js" "node" "--version" +check_tool "Go" "go" "version" +check_tool "Rust (rustc)" "rustc" "--version" +check_tool "Java" "java" "-version" + +echo "" +echo "[Containers & Cloud]" +check_tool "Docker" "docker" "--version" +check_tool "Podman" "podman" "--version" +check_tool "Kubectl" "kubectl" "version --client" diff --git a/scripts/developer/docker-info.sh b/scripts/developer/docker-info.sh new file mode 100755 index 0000000..757923c --- /dev/null +++ b/scripts/developer/docker-info.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash + +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: docker-info.sh [options] + +Options: + -h, --help Show this help message and exit + +Description: + Displays Docker client and server versions, running containers, images, + and storage driver status. +EOF + exit 0 +} + +while (( "$#" )); do + case "$1" in + -h|--help) show_help;; + *) echo "Unknown option: $1" >&2; exit 1;; + esac + shift +done + +echo "=== Docker Information ===" +if ! command -v docker >/dev/null 2>&1; then + echo "Docker is not installed on this system." + exit 0 +fi + +docker --version + +echo "" +if ! docker info >/dev/null 2>&1; then + echo "Docker daemon is either not running or current user does not have permission to access the Docker socket." + echo "Tip: Check 'systemctl status docker' or ensure user is in the 'docker' group." + exit 0 +fi + +echo "Containers:" +docker ps -a --format "table {{.ID}}\t{{.Image}}\t{{.Status}}\t{{.Names}}" | head -n 10 + +echo "" +echo "Images (first 10):" +docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}" | head -n 11 diff --git a/scripts/developer/git-info.sh b/scripts/developer/git-info.sh new file mode 100755 index 0000000..a2fda72 --- /dev/null +++ b/scripts/developer/git-info.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash + +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: git-info.sh [options] + +Options: + -h, --help Show this help message and exit + +Description: + Displays Git version, global user configuration, and if executed within + a Git repository, shows current branch, remote status, and working tree state. +EOF + exit 0 +} + +while (( "$#" )); do + case "$1" in + -h|--help) show_help;; + *) echo "Unknown option: $1" >&2; exit 1;; + esac + shift +done + +if ! command -v git >/dev/null 2>&1; then + echo "Error: 'git' command not found. Please install git." >&2 + exit 1 +fi + +echo "=== Git Information ===" +git --version + +echo "" +echo "Global Configuration:" +name=$(git config --global user.name 2>/dev/null || echo "Not set") +email=$(git config --global user.email 2>/dev/null || echo "Not set") +echo " user.name : $name" +echo " user.email: $email" + +echo "" +if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then + echo "Current Repository Status:" + echo " Root Directory: $(git rev-parse --show-toplevel)" + echo " Current Branch: $(git branch --show-current 2>/dev/null || echo "detached")" + remotes=$(git remote -v 2>/dev/null | head -n 2 || true) + if [[ -n "$remotes" ]]; then + echo " Remotes:" + echo "$remotes" | sed 's/^/ /' + fi + echo " Latest Commit :" + git log -1 --oneline 2>/dev/null | sed 's/^/ /' || echo " No commits yet" + echo " Working Tree Status:" + git status --short | sed 's/^/ /' || true +else + echo "Notice: Current directory is not inside a Git repository." +fi From f6fe44efca0c916886dce8a21ad03b3ae88d8eda Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:32:32 +0530 Subject: [PATCH 34/39] feat(developer): add python-info, node-info, and command-exists --- scripts/developer/command-exists.sh | 34 ++++++++++++++++++ scripts/developer/node-info.sh | 52 +++++++++++++++++++++++++++ scripts/developer/python-info.sh | 55 +++++++++++++++++++++++++++++ 3 files changed, 141 insertions(+) create mode 100755 scripts/developer/command-exists.sh create mode 100755 scripts/developer/node-info.sh create mode 100755 scripts/developer/python-info.sh diff --git a/scripts/developer/command-exists.sh b/scripts/developer/command-exists.sh new file mode 100755 index 0000000..386a111 --- /dev/null +++ b/scripts/developer/command-exists.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: $(basename "$0") COMMAND + +Check whether a command exists in PATH. + +Options: + -h Show this help message +EOF +} + +if [[ "${1-}" == "-h" ]]; then + show_help + exit 0 +fi + +if [[ $# -ne 1 ]]; then + echo "Error: Exactly one command name required." >&2 + show_help + exit 1 +fi + +CMD="$1" +if command -v "$CMD" >/dev/null 2>&1; then + echo "Command '$CMD' is available at $(command -v "$CMD")" + exit 0 +else + echo "Command '$CMD' is NOT found in PATH" + exit 1 +fi diff --git a/scripts/developer/node-info.sh b/scripts/developer/node-info.sh new file mode 100755 index 0000000..9089cb8 --- /dev/null +++ b/scripts/developer/node-info.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash + +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: node-info.sh [options] + +Options: + -h, --help Show this help message and exit + +Description: + Displays Node.js and NPM versions, global packages installed, and + detects alternative package managers (yarn, pnpm, bun). +EOF + exit 0 +} + +while (( "$#" )); do + case "$1" in + -h|--help) show_help;; + *) echo "Unknown option: $1" >&2; exit 1;; + esac + shift +done + +echo "=== Node.js Environment Information ===" + +if ! command -v node >/dev/null 2>&1; then + echo "Node.js is not installed." + exit 0 +fi + +echo "Node Version : $(node --version)" +echo "Node Path : $(command -v node)" + +if command -v npm >/dev/null 2>&1; then + echo "NPM Version : $(npm --version)" + echo "" + echo "Global NPM packages (depth=0):" + npm list -g --depth=0 2>/dev/null | tail -n +2 | head -n 15 | sed 's/^/ /' || echo " None or inaccessible" +fi + +echo "" +echo "Alternative Package Managers:" +for mgr in yarn pnpm bun; do + if command -v "$mgr" >/dev/null 2>&1; then + echo " $mgr: $($mgr --version 2>/dev/null || echo "installed")" + else + echo " $mgr: Not installed" + fi +done diff --git a/scripts/developer/python-info.sh b/scripts/developer/python-info.sh new file mode 100755 index 0000000..0e953b2 --- /dev/null +++ b/scripts/developer/python-info.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash + +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: python-info.sh [options] + +Options: + -h, --help Show this help message and exit + +Description: + Displays Python 3 version, executable location, active virtual environment + status, and installed pip packages summary. +EOF + exit 0 +} + +while (( "$#" )); do + case "$1" in + -h|--help) show_help;; + *) echo "Unknown option: $1" >&2; exit 1;; + esac + shift +done + +echo "=== Python Environment Information ===" + +if ! command -v python3 >/dev/null 2>&1; then + echo "Python 3 is not installed." + exit 0 +fi + +echo "Python Version : $(python3 --version)" +echo "Executable Path: $(command -v python3)" + +if [[ -n "${VIRTUAL_ENV:-}" ]]; then + echo "Virtualenv : Active ($VIRTUAL_ENV)" +elif [[ -n "${CONDA_PREFIX:-}" ]]; then + echo "Conda Env : Active ($CONDA_PREFIX)" +else + echo "Virtualenv : None (System Python)" +fi + +echo "" +if command -v pip3 >/dev/null 2>&1 || command -v pip >/dev/null 2>&1; then + PIP_CMD="pip3" + command -v pip3 >/dev/null 2>&1 || PIP_CMD="pip" + pkg_count=$($PIP_CMD list --format=freeze 2>/dev/null | wc -l || echo 0) + echo "Installed packages ($PIP_CMD): $pkg_count total" + echo "Top 10 packages:" + $PIP_CMD list 2>/dev/null | head -n 12 | tail -n +3 | sed 's/^/ /' || true +else + echo "pip is not installed." +fi From a3498ce9eeb16ac9a677411efaf25188889a417b Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:32:36 +0530 Subject: [PATCH 35/39] feat(maintenance): add backup and universal extract tools --- scripts/maintenance/backup.sh | 50 +++++++++++++++++++++++++++++++ scripts/maintenance/extract.sh | 55 ++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100755 scripts/maintenance/backup.sh create mode 100755 scripts/maintenance/extract.sh diff --git a/scripts/maintenance/backup.sh b/scripts/maintenance/backup.sh new file mode 100755 index 0000000..8d492ac --- /dev/null +++ b/scripts/maintenance/backup.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash + +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: $(basename "$0") [OPTIONS] + +Create a timestamped backup of a directory using tar.gz. + +Options: + -d DIR Directory to backup (default: current directory) + -o DIR Output directory for backup files (default: ./backups) + -h Show this help message +EOF +} + +# Default values +SRC_DIR="." +OUT_DIR="./backups" + +while getopts "d:o:h" opt; do + case $opt in + d) SRC_DIR="$OPTARG" ;; + o) OUT_DIR="$OPTARG" ;; + h) show_help; exit 0 ;; + *) show_help; exit 1 ;; + esac +done + +if ! command -v tar >/dev/null 2>&1; then + echo "Error: 'tar' command not found." >&2 + exit 1 +fi + +# Resolve absolute paths +SRC_DIR=$(realpath "$SRC_DIR") +OUT_DIR=$(realpath "$OUT_DIR") + +mkdir -p "$OUT_DIR" + +TIMESTAMP=$(date +%Y%m%d_%H%M%S) +BASE_NAME=$(basename "$SRC_DIR") +BACKUP_FILE="$OUT_DIR/${BASE_NAME}_backup_${TIMESTAMP}.tar.gz" + +echo "Creating backup of '$SRC_DIR' at '$BACKUP_FILE' ..." + +tar -czf "$BACKUP_FILE" -C "$(dirname "$SRC_DIR")" "$(basename "$SRC_DIR")" + +echo "Backup completed: $BACKUP_FILE" diff --git a/scripts/maintenance/extract.sh b/scripts/maintenance/extract.sh new file mode 100755 index 0000000..41f00e8 --- /dev/null +++ b/scripts/maintenance/extract.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash + +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: $(basename "$0") [OPTIONS] ARCHIVE [DEST] + +Extract common archive types to a destination directory. +If DEST is omitted, extracts to the current directory. + +Options: + -h Show this help message +EOF +} + +if [[ "${1-}" == "-h" ]]; then + show_help + exit 0 +fi + +if [[ $# -lt 1 || $# -gt 2 ]]; then + echo "Error: Invalid number of arguments." >&2 + show_help + exit 1 +fi + +ARCHIVE="$1" +DEST="${2:-.}" + +if [[ ! -f "$ARCHIVE" ]]; then + echo "Error: Archive file '$ARCHIVE' does not exist." >&2 + exit 1 +fi + +if [[ ! -d "$DEST" ]]; then + echo "Error: Destination '$DEST' is not a directory." >&2 + exit 1 +fi + +# Determine archive type based on extension +case "$ARCHIVE" in + *.tar.gz|*.tgz) tar -xzf "$ARCHIVE" -C "$DEST" ;; + *.tar.bz2|*.tbz2) tar -xjf "$ARCHIVE" -C "$DEST" ;; + *.tar.xz|*.txz) tar -xJf "$ARCHIVE" -C "$DEST" ;; + *.zip) unzip -d "$DEST" "$ARCHIVE" ;; + *.rar) unrar x "$ARCHIVE" "$DEST" ;; + *.7z) 7z x "$ARCHIVE" -o"$DEST" ;; + *) + echo "Error: Unsupported archive format: $ARCHIVE" >&2 + exit 1 + ;; +esac + +echo "Extraction of '$ARCHIVE' completed." From 2e6418f499322ec67164373a81c4138578274de5 Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:32:36 +0530 Subject: [PATCH 36/39] feat(maintenance): add file-organizer and log-inspect tools --- scripts/maintenance/file-organizer.sh | 107 ++++++++++++++++++++++++++ scripts/maintenance/log-inspect.sh | 71 +++++++++++++++++ 2 files changed, 178 insertions(+) create mode 100755 scripts/maintenance/file-organizer.sh create mode 100755 scripts/maintenance/log-inspect.sh diff --git a/scripts/maintenance/file-organizer.sh b/scripts/maintenance/file-organizer.sh new file mode 100755 index 0000000..620ccfa --- /dev/null +++ b/scripts/maintenance/file-organizer.sh @@ -0,0 +1,107 @@ +#!/usr/bin/env bash + +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: file-organizer.sh [options] [directory] + +Options: + -h, --help Show this help message and exit + -n, --dry-run Show what would be moved without moving any files + -d, --dir DIR Target directory to organize (default: current directory) + +Description: + Safely organizes unorganized loose files in a directory into subfolders + based on their file extensions (Images, Documents, Archives, Audio, Video, Code). + - Skips directories, hidden files (starting with .), and scripts. + - Safely handles filenames with spaces. + - Safe dry-run mode enabled via -n / --dry-run. +EOF + exit 0 +} + +TARGET_DIR="." +DRY_RUN=false + +while (( "$#" )); do + case "$1" in + -h|--help) show_help;; + -n|--dry-run) DRY_RUN=true;; + -d|--dir) + shift + TARGET_DIR="${1:-.}" + ;; + -*) echo "Unknown option: $1" >&2; exit 1;; + *) TARGET_DIR="$1";; + esac + shift +done + +if [[ ! -d "$TARGET_DIR" ]]; then + echo "Error: Directory '$TARGET_DIR' does not exist." >&2 + exit 1 +fi + +TARGET_DIR="$(cd "$TARGET_DIR" && pwd)" +echo "=== File Organizer ===" +echo "Target directory: $TARGET_DIR" +if $DRY_RUN; then + echo "Mode: DRY RUN (no files will be moved)" +fi +echo "" + +get_category() { + local ext="${1,,}" + case "$ext" in + jpg|jpeg|png|gif|bmp|svg|webp|tiff) echo "Images" ;; + pdf|doc|docx|txt|rtf|odt|xls|xlsx|ppt|pptx|csv) echo "Documents" ;; + zip|tar|gz|bz2|xz|7z|rar) echo "Archives" ;; + mp3|wav|ogg|flac|aac|m4a) echo "Audio" ;; + mp4|mkv|avi|mov|wmv|flv|webm) echo "Video" ;; + py|js|ts|c|cpp|h|hpp|go|rs|java|html|css|json|yaml|yml|sh) echo "Code" ;; + *) echo "" ;; + esac +} + +moved_count=0 + +# Iterate over regular files in TARGET_DIR (non-recursive, ignore hidden files) +while IFS= read -r -d '' file; do + filename="$(basename "$file")" + # Skip hidden files + [[ "$filename" == .* ]] && continue + + # Extract extension + ext="${filename##*.}" + if [[ "$ext" == "$filename" ]]; then + # No extension + continue + fi + + category="$(get_category "$ext")" + if [[ -n "$category" ]]; then + dest_dir="$TARGET_DIR/$category" + dest_file="$dest_dir/$filename" + + if $DRY_RUN; then + echo "[DRY RUN] Would move '$filename' -> '$category/'" + else + mkdir -p "$dest_dir" + if [[ -e "$dest_file" ]]; then + echo "Skipping '$filename': already exists in '$category/'" + else + mv -- "$file" "$dest_file" + echo "Moved '$filename' -> '$category/'" + moved_count=$((moved_count + 1)) + fi + fi + fi +done < <(find "$TARGET_DIR" -maxdepth 1 -type f -print0) + +echo "" +if $DRY_RUN; then + echo "Dry run completed." +else + echo "Organization complete. Files moved: $moved_count" +fi diff --git a/scripts/maintenance/log-inspect.sh b/scripts/maintenance/log-inspect.sh new file mode 100755 index 0000000..00458d6 --- /dev/null +++ b/scripts/maintenance/log-inspect.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: $(basename "$0") [options] -f + +Options: + -f Path to the log file to inspect (required) + -n Number of tail lines to display (default: 20) + -e Grep pattern to filter the log output (optional) + -h, --help Show this help message and exit + +The script safely displays the last N lines of a log file, optionally filtering +by a grep pattern. It validates the file size to avoid overwhelming the terminal. +EOF + exit 0 +} + +# Default values +lines=20 +pattern="" +logfile="" + +# Parse arguments +while (( "$#" )); do + case "$1" in + -f) + logfile="$2" + shift 2 + ;; + -n) + lines="$2" + shift 2 + ;; + -e) + pattern="$2" + shift 2 + ;; + -h|--help) + show_help + ;; + *) + echo "Unknown option: $1" + show_help + ;; + esac +done + +if [[ -z "$logfile" ]]; then + echo "Error: log file must be specified with -f" + show_help +fi + +if [[ ! -f "$logfile" ]]; then + echo "Error: file '$logfile' does not exist or is not a regular file" + exit 1 +fi + +# Prevent reading extremely large files (e.g., >100M) without warning +max_size=$((100 * 1024 * 1024)) +file_size=$(stat -c%s "$logfile") +if (( file_size > max_size )); then + echo "Warning: log file is larger than 100M (${file_size} bytes). Displaying only the last $lines lines." +fi + +if [[ -n "$pattern" ]]; then + tail -n "$lines" "$logfile" | grep --color=auto -i "$pattern" || true +else + tail -n "$lines" "$logfile" +fi From 1b15d300fe6d5bc3f617bbb0b836a38b2da7739c Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:32:39 +0530 Subject: [PATCH 37/39] feat(cli): add interactive bin/linux-toolbox dashboard --- bin/linux-toolbox | 149 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100755 bin/linux-toolbox diff --git a/bin/linux-toolbox b/bin/linux-toolbox new file mode 100755 index 0000000..a82171f --- /dev/null +++ b/bin/linux-toolbox @@ -0,0 +1,149 @@ +#!/usr/bin/env bash + +# linux-toolbox – interactive menu front-end for the LinuxScripts utility collection. +# Presents categories and lets the user select a script to run. +# Does not duplicate script logic; invokes utility scripts directly. + +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: linux-toolbox [options] + +Options: + -h, --help Show this help message and exit + +Description: + Provides a keyboard-friendly menu to launch utility scripts located under + the repository's scripts/ directory. Categories: + 1) System + 2) Storage + 3) Network + 4) Processes + 5) Packages + 6) Hardware + 7) SSH + 8) Developer + 9) Maintenance + 10) Exit +EOF + exit 0 +} + +while (( "$#" )); do + case "$1" in + -h|--help) show_help;; + *) echo "Unknown option: $1" >&2; exit 1;; + esac + shift +done + +# Resolve repository root relative to script location +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +SCRIPTS_DIR="$REPO_ROOT/scripts" + +declare -A CATEGORY_MAP=( + [1]="system" + [2]="storage" + [3]="network" + [4]="process" + [5]="packages" + [6]="hardware" + [7]="ssh" + [8]="developer" + [9]="maintenance" +) + +main_menu() { + echo "" + echo "==============================" + echo " Linux Toolbox Main Menu " + echo "==============================" + echo " 1) System" + echo " 2) Storage" + echo " 3) Network" + echo " 4) Processes" + echo " 5) Packages" + echo " 6) Hardware" + echo " 7) SSH" + echo " 8) Developer" + echo " 9) Maintenance" + echo "10) Exit" + echo "------------------------------" + read -rp "Select a category [1-10]: " cat_choice + + case "$cat_choice" in + 10) + echo "Exiting Linux Toolbox. Goodbye!" + exit 0 + ;; + [1-9]) + sub_menu "${CATEGORY_MAP[$cat_choice]}" + ;; + *) + echo "Invalid selection. Please choose a number between 1 and 10." + main_menu + ;; + esac +} + +sub_menu() { + local category="$1" + local dir="$SCRIPTS_DIR/$category" + + if [[ ! -d "$dir" ]]; then + echo "Category directory not found: $dir" + main_menu + return + fi + + mapfile -t scripts < <(find "$dir" -maxdepth 1 -type f -name "*.sh" | sort) + if [[ ${#scripts[@]} -eq 0 ]]; then + echo "No scripts found in $category." + main_menu + return + fi + + echo "" + echo "------------------------------" + echo " Category: $category" + echo "------------------------------" + for i in "${!scripts[@]}"; do + printf "%2d) %s\n" $((i+1)) "$(basename "${scripts[$i]}")" + done + echo " 0) Back to main menu" + echo "------------------------------" + read -rp "Select a script [0-${#scripts[@]}]: " script_choice + + if [[ "$script_choice" =~ ^[0-9]+$ ]]; then + if [[ "$script_choice" -eq 0 ]]; then + main_menu + return + elif (( script_choice >= 1 && script_choice <= ${#scripts[@]} )); then + local selected_script="${scripts[$((script_choice-1))]}" + echo "" + echo "Running $(basename "$selected_script")..." + read -rp "Enter arguments for the script (press Enter for none): " extra_args + echo "" + + if [[ -n "$extra_args" ]]; then + # Parse into array to avoid eval vulnerabilities + read -ra arg_arr <<< "$extra_args" + "$selected_script" "${arg_arr[@]}" || echo "Script exited with non-zero status ($?)" + else + "$selected_script" || echo "Script exited with non-zero status ($?)" + fi + + echo "" + read -rp "Press Enter to return to $category menu..." _ + sub_menu "$category" + return + fi + fi + + echo "Invalid choice. Please enter a valid number." + sub_menu "$category" +} + +main_menu From f7158ca1943d3b7e9821cb97491c02509a62138a Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:32:44 +0530 Subject: [PATCH 38/39] test: add automated test harness and CI workflow --- .github/workflows/shellcheck.yml | 24 ++++++++++ tests/fixtures/.gitkeep | 1 + tests/test_all.sh | 78 ++++++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+) create mode 100644 .github/workflows/shellcheck.yml create mode 100644 tests/fixtures/.gitkeep create mode 100755 tests/test_all.sh diff --git a/.github/workflows/shellcheck.yml b/.github/workflows/shellcheck.yml new file mode 100644 index 0000000..b86081e --- /dev/null +++ b/.github/workflows/shellcheck.yml @@ -0,0 +1,24 @@ +name: Lint and Test + +on: + push: + branches: [ main, 'feat/**' ] + pull_request: + branches: [ main ] + +jobs: + shellcheck: + name: ShellCheck and Validation + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y shellcheck + + - name: Run test suite + run: | + bash tests/test_all.sh diff --git a/tests/fixtures/.gitkeep b/tests/fixtures/.gitkeep new file mode 100644 index 0000000..3bb0efd --- /dev/null +++ b/tests/fixtures/.gitkeep @@ -0,0 +1 @@ +# Test fixtures directory for automated tests diff --git a/tests/test_all.sh b/tests/test_all.sh new file mode 100755 index 0000000..0f4a1a9 --- /dev/null +++ b/tests/test_all.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash + +# Test suite for LinuxScripts repository. +# Discovers all *.sh scripts under the repository and performs basic validation: +# 1. Syntax check (bash -n) +# 2. ShellCheck (if available) +# 3. Ensure executable permission +# 4. Run help output (-h) and expect exit status 0 (if script implements it) + +set -euo pipefail + +show_help() { + cat <<'EOF' +Usage: test_all.sh [options] + +Options: + -h, --help Show this help message and exit + +Description: + Discovers all utility scripts in the repository, validates syntax (bash -n), + runs ShellCheck if installed, verifies executable permissions, and tests --help/-h. +EOF + exit 0 +} + +# Handle options +while (( "$#" )); do + case "$1" in + -h|--help) show_help ;; + *) echo "Unknown option: $1" >&2; exit 1 ;; + esac + shift +done + +ROOT_DIR="$(git rev-parse --show-toplevel)" +FAILED=0 +SELF="$(realpath "$0")" + +while IFS= read -r script; do + # Skip self to prevent recursive execution + if [[ "$(realpath "$script")" == "$SELF" ]]; then + continue + fi + echo "Testing $script" + # 1. Syntax + if ! bash -n "$script"; then + echo " ❌ Syntax error in $script" + FAILED=$((FAILED+1)) + continue + fi + # 2. ShellCheck (optional) + if command -v shellcheck >/dev/null 2>&1; then + if ! shellcheck "$script"; then + echo " ❌ ShellCheck warnings/errors in $script" + FAILED=$((FAILED+1)) + fi + fi + # 3. Executable permission + if [[ ! -x "$script" ]]; then + echo " ⚠️ Adding executable permission to $script" + chmod +x "$script" + fi + # 4. Help flag test (-h or --help) + if "$script" -h >/dev/null 2>&1 || "$script" --help >/dev/null 2>&1; then + echo " ✅ Help flag works" + else + echo " ❌ Help flag (-h / --help) failed" + FAILED=$((FAILED+1)) + fi +done < <(find "$ROOT_DIR/scripts" -type f -name "*.sh" | sort) + +if [[ $FAILED -eq 0 ]]; then + echo "All tests passed." + exit 0 +else + echo "$FAILED test(s) failed." + exit 1 +fi From 3617dd4720afe2f4cb43d5586dc1fec9483a07ac Mon Sep 17 00:00:00 2001 From: ashishsinghbora <135435891+ashishsinghbora@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:32:48 +0530 Subject: [PATCH 39/39] docs: add comprehensive README, CONTRIBUTING, LICENSE, and SECURITY --- CONTRIBUTING.md | 33 ++++++ LICENSE | 21 ++++ README.md | 284 ++++++++++++++++++++++++++++++------------------ SECURITY.md | 17 +++ 4 files changed, 249 insertions(+), 106 deletions(-) create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 SECURITY.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..dd39a1e --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,33 @@ +# Contributing to LinuxScripts + +Thank you for your interest in improving LinuxScripts! + +## Principles & Guidelines + +1. **Standards:** + - Every script must start with `#!/usr/bin/env bash` and `set -euo pipefail`. + - Implement a `--help` / `-h` flag describing usage, options, and dependencies. + - Quote all variables properly and handle filenames containing spaces safely. + - Minimize external dependencies; prefer core POSIX / standard Linux utilities. + - Gracefully detect dependencies using `command -v`. + +2. **Safety First:** + - Default to read-only or dry-run modes where practical. + - Destructive operations (process termination, package removal, cache clearing) must require explicit user confirmation or flags. + - Never run unvalidated `rm -rf` commands. + - SSH audits and checks must remain strictly read-only. + +3. **Testing:** + - Verify syntax: `bash -n