Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
173 changes: 117 additions & 56 deletions scripts/network/network-diagnostics.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,99 +3,160 @@ set -euo pipefail

show_help() {
cat <<'EOF'
Usage: $(basename "$0") [options]
Usage: network-diagnostics.sh [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.
Description:
Runs a comprehensive non-destructive network diagnostics suite:
* Internet HTTP/HTTPS reachability
* DNS resolution test
* ICMP Ping connectivity
* Gateway detection and reachability
Clearly reports test status using [PASS], [FAIL], [SKIPPED], [UNKNOWN].
EOF
exit 0
}

# Default values
host="google.com"
ping_ip="8.8.8.8"
ports="80 443"

# Parse arguments
for arg in "$@"; do
case "$arg" in
-h|--help) show_help ;;
*) echo "Unknown option: $arg" >&2; exit 1 ;;
-h|--help)
show_help
;;
*)
echo "Error: Unknown option: $arg" >&2
exit 1
;;
esac
done

echo "--- Network diagnostics start ---"
echo "=== Network Diagnostics Suite ==="
echo ""

PASS_COUNT=0
FAIL_COUNT=0
SKIP_COUNT=0
UNKNOWN_COUNT=0

report_pass() {
echo " [PASS] $1"
PASS_COUNT=$((PASS_COUNT + 1))
}

report_fail() {
echo " [FAIL] $1"
FAIL_COUNT=$((FAIL_COUNT + 1))
}

report_skip() {
echo " [SKIPPED] $1"
SKIP_COUNT=$((SKIP_COUNT + 1))
}

report_unknown() {
echo " [UNKNOWN] $1"
UNKNOWN_COUNT=$((UNKNOWN_COUNT + 1))
}

# 1. Internet connectivity
# 1. Internet Connectivity
echo "[1/4] Checking internet reachability..."
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)."
if curl -s -o /dev/null --connect-timeout 4 --max-time 6 "https://1.1.1.1" || curl -s -o /dev/null --connect-timeout 4 --max-time 6 "https://8.8.8.8"; then
report_pass "Direct IP HTTPS reachability"
else
echo "Internet NOT reachable (curl)."
report_fail "Could not reach internet endpoints via HTTPS"
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)."
if wget -q --timeout=5 --spider "https://1.1.1.1" || wget -q --timeout=5 --spider "https://8.8.8.8"; then
report_pass "Direct IP HTTPS reachability (wget)"
else
echo "Internet NOT reachable (wget)."
report_fail "Could not reach internet endpoints via HTTPS (wget)"
fi
else
echo "Neither curl nor wget installed; skipping internet test."
report_skip "Neither curl nor wget is installed"
fi

# 2. DNS lookup
# 2. DNS Resolution
echo "[2/4] Testing DNS resolution..."
TEST_DOMAINS=("cloudflare.com" "google.com")
DNS_SUCCESS=false

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."
for dom in "${TEST_DOMAINS[@]}"; do
if dig +short +time=3 +tries=1 "$dom" 2>/dev/null | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+'; then
report_pass "Resolved $dom via dig"
DNS_SUCCESS=true
break
fi
done
if ! $DNS_SUCCESS; then
report_fail "DNS resolution failed for test domains via dig"
fi
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."
for dom in "${TEST_DOMAINS[@]}"; do
if nslookup "$dom" 2>/dev/null | awk '/^Address: / {print $2}' | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+'; then
report_pass "Resolved $dom via nslookup"
DNS_SUCCESS=true
break
fi
done
if ! $DNS_SUCCESS; then
report_fail "DNS resolution failed for test domains via nslookup"
fi
elif command -v getent >/dev/null 2>&1; then
if getent hosts "${TEST_DOMAINS[0]}" >/dev/null 2>&1; then
report_pass "Resolved ${TEST_DOMAINS[0]} via getent hosts"
else
report_fail "DNS resolution failed via getent"
fi
else
echo "Neither dig nor nslookup installed; skipping DNS test."
report_skip "No DNS diagnostic tool (dig/nslookup/getent) available"
fi

# 3. Ping test
# 3. ICMP Ping Test
echo "[3/4] Testing ICMP reachability..."
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."
# Try pinging 1.1.1.1 or 8.8.8.8 (1 packet, 3s timeout)
if ping -c 1 -W 3 1.1.1.1 >/dev/null 2>&1 || ping -c 1 -W 3 8.8.8.8 >/dev/null 2>&1; then
report_pass "ICMP ping to public resolver responded"
else
echo "Ping failed."
# ICMP is frequently filtered by cloud firewalls / ISP networks
report_unknown "Ping unacknowledged (ICMP may be filtered by firewall or network policy)"
fi
else
echo "ping command not found; skipping ping test."
report_skip "ping utility is not installed"
fi

# 4. Port checks on default gateway (if reachable)
# 4. Default Gateway Reachability
echo "[4/4] Checking default gateway..."
GATEWAY=""
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 "</dev/tcp/$gateway/$p" && echo "Port $p open" || echo "Port $p closed"
else
echo "No tool available to test ports (nc or /dev/tcp)."
break
fi
done
GATEWAY="$(ip route 2>/dev/null | awk '/default/ {print $3}' | head -n1 || true)"
fi

if [[ -n "$GATEWAY" ]]; then
if command -v ping >/dev/null 2>&1; then
if ping -c 1 -W 2 "$GATEWAY" >/dev/null 2>&1; then
report_pass "Default gateway ($GATEWAY) is responsive to ping"
else
report_unknown "Default gateway ($GATEWAY) detected but does not respond to ping"
fi
else
echo "Could not determine default gateway; skipping port checks."
report_pass "Default gateway detected: $GATEWAY (ping tool not available to verify)"
fi
else
echo "ip command not found; cannot determine default gateway."
report_skip "No default gateway route detected in routing table"
fi

echo "--- Network diagnostics end ---"
echo ""
echo "=== Diagnostic Summary ==="
echo "Passed: $PASS_COUNT"
echo "Failed: $FAIL_COUNT"
echo "Skipped: $SKIP_COUNT"
echo "Unknown: $UNKNOWN_COUNT"

if [[ $FAIL_COUNT -gt 0 ]]; then
exit 1
fi
exit 0
83 changes: 63 additions & 20 deletions scripts/process/kill-process.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,58 +3,100 @@ set -euo pipefail

show_help() {
cat <<'EOF'
Usage: $(basename "$0") [options] <pid|process_name>
Usage: kill-process.sh [options] <pid|process_name>

Options:
-h, --help Show this help message and exit
-s, --signal <sig> 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.
Description:
Safely terminates a process identified by PID or name.
- Prompts for confirmation unless -f / --force is given.
- Safeguards against terminating init (PID 1), current shell ($$),
or parent process ($PPID).
EOF
exit 0
}

# Default values
signal="SIGTERM"
force="no"
target=""

# Parse arguments
while (( "$#" )); do
case "$1" in
-h|--help) show_help;;
-h|--help)
show_help
;;
-s|--signal)
signal="$2"
shift 2
if [[ -n "${2-}" && "${2-}" != -* ]]; then
signal="$2"
shift
else
echo "Error: Argument for $1 is missing" >&2
exit 1
fi
;;
-f|--force)
force="yes"
shift
;;
-*)
echo "Error: Unknown option: $1" >&2
exit 1
;;
*)
target="$1"
shift
if [[ -z "$target" ]]; then
target="$1"
else
echo "Error: Unexpected additional argument: $1" >&2
exit 1
fi
;;
esac
shift
done

if [[ -z "${target:-}" ]]; then
echo "Error: PID or process name is required."
show_help
if [[ -z "$target" ]]; then
echo "Error: PID or process name is required." >&2
echo "Run '$0 --help' for usage." >&2
exit 1
fi

# Validate signal
if ! kill -l "$signal" >/dev/null 2>&1; then
echo "Error: Invalid signal '$signal'." >&2
exit 1
fi

declare -a pids=()

# Resolve target to PID(s)
if [[ "$target" =~ ^[0-9]+$ ]]; then
read -ra pids <<< "$target"
if [[ "$target" -eq 1 ]]; then
echo "Error: Refusing to send signal to PID 1 (init/systemd)." >&2
exit 1
fi
if [[ "$target" -eq 0 ]]; then
echo "Error: Refusing to send signal to PID 0." >&2
exit 1
fi
if [[ "$target" -eq $$ || "$target" -eq $PPID ]]; then
echo "Error: Refusing to send signal to self ($$) or parent ($PPID)." >&2
exit 1
fi
pids=("$target")
else
# Use pgrep to find matching processes (exclude this script)
mapfile -t pids < <(pgrep -f "${target}" | grep -vw $$ || true)
# Use pgrep to find matching processes, filtering out self and parent
while IFS= read -r matched_pid; do
[[ -z "$matched_pid" ]] && continue
if [[ "$matched_pid" -ne $$ && "$matched_pid" -ne $PPID && "$matched_pid" -ne 1 ]]; then
pids+=("$matched_pid")
fi
done < <(pgrep -f "${target}" || true)
fi

if [[ ${#pids[@]} -eq 0 ]]; then
echo "No matching processes found for '$target'."
echo "No matching eligible processes found for '$target'."
exit 1
fi

Expand All @@ -70,7 +112,8 @@ fi

for pid in "${pids[@]}"; do
if ! kill -0 "$pid" 2>/dev/null; then
echo "Process $pid no longer exists."; continue
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"
Expand Down
Loading
Loading