#!/bin/bash # Funcție pentru a afișa utilizarea și a ieși show_help() { echo "Utilizare: $0 [-i ] [-t ]" echo " -i : Specifică interfața de rețea de monitorizat (ex: eth0, enp0s3)." echo " Dacă nu este specificată, se va detecta interfața implicită." echo " -t : Intervalul de timp în secunde pentru calculul mediei și refresh (implicit: 1)." echo " Va afișa media ultimelor și se va actualiza la fiecare ." echo "" echo "Exemple:" echo " $0 # Monitorizează interfața implicită la fiecare secundă" echo " $0 -i enp0s3 # Monitorizează enp0s3 la fiecare secundă" echo " $0 -t 5 # Monitorizează interfața implicită la fiecare 5 secunde" echo " $0 -i eth0 -t 10 # Monitorizează eth0 la fiecare 10 secunde" exit 0 } # Valori implicite INTERFACE="" INTERVAL=1 # Procesează argumentele din linia de comandă while getopts "i:t:h" opt; do case ${opt} in i ) INTERFACE=$OPTARG ;; t ) INTERVAL=$OPTARG ;; h ) show_help ;; \? ) echo "Opțiune invalidă: -$OPTARG" >&2; show_help ;; : ) echo "Opțiunea -$OPTARG necesită un argument." >&2; show_help ;; esac done # Verifică dacă INTERVAL este un număr valid if ! [[ "$INTERVAL" =~ ^[0-9]+$ ]] || [ "$INTERVAL" -eq 0 ]; then echo "Eroare: Intervalul de timp trebuie să fie un număr pozitiv." show_help fi # --- Funcție pentru a returna scriptul AWK de parsare a rutei --- get_awk_route_parser() { cat <<'EOF_AWK' { dev_name = ""; metric_val = "0"; # Initialize dev_name as empty, metric_val as 0 (default metric) for (i=1; i<=NF; i++) { if ($i == "dev") { dev_name = $(i+1); } if ($i == "metric") { metric_val = $(i+1); } } if (dev_name != "") { # Only dev_name is mandatory print dev_name " " metric_val; } } EOF_AWK } # Detectează interfața implicită dacă nu este specificată if [ -z "$INTERFACE" ]; then # Vom colecta toate rutele default găsite, împreună cu interfața și metricul # Format: "interfață metric" DEFAULT_ROUTES_CANDIDATES="" # Stochează scriptul AWK într-o variabilă AWK_SCRIPT_CONTENT=$(get_awk_route_parser) # 1. Caută ruta default în tabela 'main' (comportament normal) # Folosim ip route show (fara 'table main' explicit) pentru a acoperi cazurile in care main e implicita MAIN_DEFAULT=$(ip route show | awk '/^default/ { print | "cat" }' | awk "$AWK_SCRIPT_CONTENT") if [ -n "$MAIN_DEFAULT" ]; then DEFAULT_ROUTES_CANDIDATES="$MAIN_DEFAULT" fi # 2. Caută rute default în tabelele custom definite de ip rules CUSTOM_TABLES=$(ip rule | awk '{ for (i=1; i<=NF; i++) { if ($i == "lookup" && $(i+1) !~ /^(local|main|default)$/) { print $(i+1); } } }' | sort -u) # Folosim sort -u pentru a evita duplicaturile for TABLE_NAME in $CUSTOM_TABLES; do TABLE_DEFAULT=$(ip route show table "$TABLE_NAME" | awk '/^default/ { print | "cat" }' | awk "$AWK_SCRIPT_CONTENT") if [ -n "$TABLE_DEFAULT" ]; then if [ -n "$DEFAULT_ROUTES_CANDIDATES" ]; then DEFAULT_ROUTES_CANDIDATES="${DEFAULT_ROUTES_CANDIDATES}\n${TABLE_DEFAULT}" else DEFAULT_ROUTES_CANDIDATES="$TABLE_DEFAULT" fi fi done # Acum că avem toți candidații, sortează-i după metric și ia-l pe cel cu metricul cel mai mic if [ -n "$DEFAULT_ROUTES_CANDIDATES" ]; then INTERFACE=$(echo -e "$DEFAULT_ROUTES_CANDIDATES" | sort -nk2 | head -n1 | awk '{print $1}') fi if [ -z "$INTERFACE" ]; then echo "Eroare: Nu s-a putut detecta o interfață implicită." echo "Vă rugăm să specificați una folosind -i ." exit 1 fi echo "Interfață implicită detectată: $INTERFACE" fi # Verifică dacă interfața există if ! ip link show "$INTERFACE" &> /dev/null; then echo "Eroare: Interfața '$INTERFACE' nu există sau nu este activă." exit 1 fi echo "Monitorizare interfață: $INTERFACE | Interval: $INTERVAL secunde" echo "---------------------------------------------------------------" echo " Rx (KB/s) | Tx (KB/s) | Total (KB/s)" echo "---------------------------------------------------------------" # Inițializarea valorilor anterioare PREV_RX_BYTES=$(cat "/sys/class/net/$INTERFACE/statistics/rx_bytes") PREV_TX_BYTES=$(cat "/sys/class/net/$INTERFACE/statistics/tx_bytes") LAST_TIMESTAMP=$(date +%s) while true; do sleep "$INTERVAL" CURRENT_RX_BYTES=$(cat "/sys/class/net/$INTERFACE/statistics/rx_bytes") CURRENT_TX_BYTES=$(cat "/sys/class/net/$INTERFACE/statistics/tx_bytes") CURRENT_TIMESTAMP=$(date +%s) TIME_DIFF=$((CURRENT_TIMESTAMP - LAST_TIMESTAMP)) # Prevenim împărțirea la zero și resetăm dacă intervalul este prea mic sau negativ (nu ar trebui) if [ "$TIME_DIFF" -le 0 ]; then PREV_RX_BYTES=$CURRENT_RX_BYTES PREV_TX_BYTES=$CURRENT_TX_BYTES LAST_TIMESTAMP=$CURRENT_TIMESTAMP continue fi # Calculează ratele în bytes/secundă RX_RATE_BPS=$(( (CURRENT_RX_BYTES - PREV_RX_BYTES) / TIME_DIFF )) TX_RATE_BPS=$(( (CURRENT_TX_BYTES - PREV_TX_BYTES) / TIME_DIFF )) # !!! Modificare AICI: Forțează locales pentru calcule și printf !!! # Convertește în KB/secundă (rotunjire la 2 zecimale cu printf) # Folosim bash arithmetic pentru a calcula valorile intregi pentru a minimiza dependintele, # apoi bc pentru float. RX_RATE_KBPS=$(LC_NUMERIC=C bc -l <<< "scale=2; $RX_RATE_BPS / 1024") TX_RATE_KBPS=$(LC_NUMERIC=C bc -l <<< "scale=2; $TX_RATE_BPS / 1024") TOTAL_RATE_KBPS=$(LC_NUMERIC=C bc -l <<< "scale=2; ($RX_RATE_BPS + $TX_RATE_BPS) / 1024") # Afișează rezultatele formatat LC_NUMERIC=C printf "%10.2f | %11.2f | %12.2f\n" "$RX_RATE_KBPS" "$TX_RATE_KBPS" "$TOTAL_RATE_KBPS" # Actualizează valorile anterioare pentru următoarea iterație PREV_RX_BYTES=$CURRENT_RX_BYTES PREV_TX_BYTES=$CURRENT_TX_BYTES LAST_TIMESTAMP=$CURRENT_TIMESTAMP done