diff --git a/network_info.sh b/network_info.sh index c06350d..7649333 100644 --- a/network_info.sh +++ b/network_info.sh @@ -17,7 +17,12 @@ # # Usage: network_info.sh (no arguments) # Description: Displays network interface addresses, routing table, open ports, and iptables rules. - +# +# Read-only. The iptables section needs root; without it that section +# reports the failure rather than silently showing nothing. + +set -euo pipefail + echo "==== Network Interfaces (IP addresses) ====" if command -v ip &> /dev/null; then ip -brief addr show # brief output of interfaces and addresses @@ -47,7 +52,10 @@ fi echo -e "\n==== Firewall Rules (iptables) ====" if command -v iptables &> /dev/null; then - iptables -L -n -v # list firewall rules with numeric addresses and packet counts + # Needs root; report the failure instead of letting set -e abort here. + iptables -L -n -v || echo "Could not read iptables rules (run as root?)." +elif command -v nft &> /dev/null; then + nft list ruleset || echo "Could not read nftables ruleset (run as root?)." else echo "iptables command not found (no firewall rules to show or using nftables)." fi diff --git a/process_monitor.sh b/process_monitor.sh index b7cb3e2..6dd2025 100644 --- a/process_monitor.sh +++ b/process_monitor.sh @@ -17,24 +17,48 @@ # # Usage: process_monitor.sh [kill ] # Description: Without args, shows top CPU & memory processes. With "kill", terminates process by name or PID. - -if [ "$1" = "kill" ]; then + +set -euo pipefail + +if [ "${1:-}" = "kill" ]; then target="$2" if [ -z "$target" ]; then echo "Usage: $0 kill "; exit 1 fi - # If target is numeric (PID), kill that PID, else kill by name + # Show what will be signalled and confirm first. pkill -x by name can + # match several processes at once, and as root that is an easy way to + # take down more than intended with no warning. if [[ "$target" =~ ^[0-9]+$ ]]; then - kill "$target" && echo "Process $target killed." || echo "Failed to kill process $target." + if ! ps -p "$target" -o pid,user,comm >/dev/null 2>&1; then + echo "No process with PID $target."; exit 1 + fi + ps -p "$target" -o pid,user,comm else - # Use pkill to kill by name (match full process name) - pkill -x "$target" && echo "Processes named '$target' killed." || echo "No process '$target' found or kill failed." + if ! pgrep -x "$target" >/dev/null 2>&1; then + echo "No process named '$target'."; exit 1 + fi + pgrep -x -a "$target" + fi + + if [ "${FORCE:-}" != "1" ]; then + if [ ! -t 0 ]; then + echo "Refusing to kill without confirmation; set FORCE=1 for unattended use." >&2 + exit 1 + fi + read -r -p "Send SIGTERM to the above? (yes/NO): " reply + [ "$reply" = "yes" ] || { echo "Cancelled."; exit 0; } + fi + + if [[ "$target" =~ ^[0-9]+$ ]]; then + kill "$target" && echo "Process $target signalled." || echo "Failed to signal process $target." + else + pkill -x "$target" && echo "Processes named '$target' signalled." || echo "Failed to signal '$target'." fi exit 0 fi echo "==== Top 5 CPU-consuming processes ====" -ps -eo pid,user,comm,%cpu --sort=-%cpu | head -n 6 +ps -eo pid,user,comm,%cpu --sort=-%cpu | head -n 6 || true echo -e "\n==== Top 5 Memory-consuming processes ====" -ps -eo pid,user,comm,%mem --sort=-%mem | head -n 6 +ps -eo pid,user,comm,%mem --sort=-%mem | head -n 6 || true diff --git a/security_audit.sh b/security_audit.sh index 0fa89a7..7836b32 100644 --- a/security_audit.sh +++ b/security_audit.sh @@ -17,18 +17,29 @@ # # Usage: security_audit.sh (no arguments) # Description: Lists world-writable files/dirs, SUID/SGID files, and listening ports. - +# +# Run as root for a complete picture: as an unprivileged user, find +# cannot descend into directories it may not read, so a clean report +# below is not the same as a clean system. + +set -euo pipefail + +# Each find below ends in `|| true`. find exits non-zero when it could +# not read some directory -- routine here, since we deliberately walk the +# whole filesystem -- and without this, set -e would abort the audit part +# way through and still look like it had finished. + # World-writable files (perm bits: others have write) echo "==== World-Writable Files (potentially unsafe) ====" -find / -xdev -type f -perm -0002 -printf '%M %u %g %p\n' 2>/dev/null +find / -xdev -type f -perm -0002 -printf '%M %u %g %p\n' 2>/dev/null || true # World-writable directories without sticky bit echo -e "\n==== World-Writable Directories (no sticky bit) ====" -find / -xdev -type d -perm -0002 ! -perm -1000 -printf '%M %u %g %p\n' 2>/dev/null +find / -xdev -type d -perm -0002 ! -perm -1000 -printf '%M %u %g %p\n' 2>/dev/null || true # SUID/SGID files (files with setuid or setgid bits) echo -e "\n==== SUID/SGID Files ====" -find / -xdev \( -perm -4000 -o -perm -2000 \) -printf '%M %u %g %p\n' 2>/dev/null +find / -xdev \( -perm -4000 -o -perm -2000 \) -printf '%M %u %g %p\n' 2>/dev/null || true # Open listening ports echo -e "\n==== Listening Network Ports ====" diff --git a/sys_monitor.sh b/sys_monitor.sh index 19e86ac..d6da7c1 100644 --- a/sys_monitor.sh +++ b/sys_monitor.sh @@ -17,7 +17,15 @@ # # Usage: sys_monitor.sh (no arguments) # Description: Prints system uptime, memory, disk usage, and top CPU/mem processes. - + +set -euo pipefail + +# `ps | head` is a SIGPIPE waiting to happen: head closes the pipe after +# six lines, and on a host with enough processes ps fills the buffer and +# dies with 141, which pipefail turns into a script exit. That is exactly +# the busy machine you most want this to work on, so those two pipelines +# tolerate it explicitly. + echo "==== System Uptime and Load ====" uptime @@ -30,7 +38,7 @@ df -h -x tmpfs -x devtmpfs echo -e "\n==== Top 5 Processes by CPU Usage ====" # Display header and top 5 CPU-consuming processes -ps -eo pid,user,comm,%cpu --sort=-%cpu | head -n 6 +ps -eo pid,user,comm,%cpu --sort=-%cpu | head -n 6 || true echo -e "\n==== Top 5 Processes by Memory Usage ====" -ps -eo pid,user,comm,%mem --sort=-%mem | head -n 6 +ps -eo pid,user,comm,%mem --sort=-%mem | head -n 6 || true