- Activar set -euo pipefail i IFS segur permet que els scripts bash fallin aviat i evitin errors silenciosos en manejar codis de sortida i variables indefinides.
- L'ús de trap per a ERR i senyals com INT o TERM facilita registrar errors, fer neteja controlada i mantenir el sistema en un estat consistent.
- Un sistema de logging centralitzat amb nivells i timestamps millora la traçabilitat, el debugging i la integració de seqüències en entorns DevOps i CI/CD.
- La combinació de programació defensiva, la validació d'entrades i les bones pràctiques de depuració fa que els scripts bash siguin fiables en producció.
Automatitzar tasques amb Bash marca la diferència entre un sistema que t'exigeix estar pendent tot el dia i un altre que simplement funciona sol i t'avisa quan alguna cosa va malament. En entorns DevOps i d'administració de sistemes, un bon scripting no només s'encadena ordres: va d'evitar errors silenciosos, de poder depurar ràpid i de deixar rastres clars a logs per saber què ha passat i quan.
Quan comences a treballar de debò amb scripts, descobreixes que Bash, per defecte, és força permissiu: si alguna cosa falla, el script sol seguir endavant com si res, usant variables buides o resultats incomplets. D'aquí vénen històries de terror com backups truncats (per als que convé sincronitzar amb rsync a Linux), esborrats massius per rutes mal construïdes o desplegaments que semblaven correctes però havien fallat a meitat. Per això té tant sentit aprendre a fer servir bé set -euo pipefail, trap i un sistema de logging decent.
Per què Bash segueix sent clau a DevOps
En el dia a dia de sistemes i DevOps, Bash continua sent l'eina que sempre hi és: en servidors Linux, contenidors, màquines de CI/CD, scripts de manteniment… El seu avantatge més gran és que no depens d'instal·lar runtimes ni llibreries externes; amb l'intèrpret d'ordres que ja porta el sistema pots automatitzar des de revisions de salut fins a desplegaments complets.
Aquest poder té truc: amb scripts mal escrits és massa fàcil que una ordre falli i la resta del script continuï com si tot hagués sortit perfecte. Si a això li sumes tasques crítiques (backups, rotació de logs, esborrament de fitxers, execucions programades), el risc no és teòric: tard o d'hora alguna cosa s'acabarà trencant sense que t'assabentis.
Per això és tan important que, a més d'automatitzar, incloguis des del principi maneig d'errors, depuració i logging estructurat. I aquí entren en joc tres peces que es repeteixen en tots els bons exemples de scripting a Bash modern: set -euo pipefail, trap i un sistema de logs coherent.
Exemple pràctic: script de monitorització amb maneig estricte d'errors
Un patró molt útil és crear un script de monitorització que recopili informació clau del sistema (CPU, memòria, disc, xarxa, processos, logs recents…) i que a més falli de forma segura, deixant traces clares en un fitxer de log. Aquest tipus de script es pot fer servir a mà, des de cron, o de suport en pipelins de CI/CD.
idea general La idea general és tenir un script amb:
- Mode estricte activat amb set -euo pipefail per fallar aviat i no seguir executant sobre estats inconsistents.
- trap sobre ERR i senyals com INT o TERM per registrar errors i fer neteja abans de sortir.
- Funció de logging centralitzada que escriviu a consola ia fitxer amb timestamp i nivell (INFO, WARNING, ERROR).
- Revisions modulars de CPU, memòria, disc, xarxa i logs del sistema.
- Instal·lació opcional de dependències com sysstat, lm-sensors o net-tools, adaptada a Debian/Ubuntu o RHEL/CentOS/Fedora.
habitual En un script d'aquesta mena és habitual veure alguna cosa com:
- Variables de color per ressaltar avisos i errors a la terminal (XARXA, GREEN, YELLOW, BLUE, NC).
- Rutes com
/var/log/system-monitor.logper als logs generals i/var/log/system-metrics.logper a mètriques periòdiques. - Llindars configurables d'alerta: per exemple ALERT_CPU_THRESHOLD=80, ALERT_MEM_THRESHOLD=80, ALERT_DISK_THRESHOLD=85.
- Un interval de monitorització MONITOR_INTERVAL per repetir les revisions cada X segons si executes l'script en bucle.
Amb aquesta base es construeix un script robust que no només recopila informació, sinó que també reacciona correctament davant de fallades, deixa evidències clares i es pot integrar en processos més grans.
Activar el mode estricte: set -euo pipefail i IFS segur
La majoria de problemes “rars” a Bash vénen que l'intèrpret d'ordres, per defecte, no considera greu que una ordre falli o que una variable no existeixi. Per forçar un comportament més segur se sol activar el que molta gent anomena “mode Bash estricte”.
Les peces bàsiques d'aquesta manera estricta són:
- establir -e: fa que l'script acabi així que una ordre retorna un codi de sortida diferent de 0, excepte en alguns contextos especials (if, while, &&, ||…).
- set -u o setembre -o nounset: provoca error quan intentes fer servir una variable que no està definida, en lloc de tractar-la com a cadena buida.
- setembre -o pipefail: fa que en una canonada el codi de sortida sigui el del primer comando que falli, no només el del darrer.
- IFS=$'\n\t': limita el separador de camps intern a salt de línia i tabulador per evitar que els espais trenquin bucles for sobre llistes de fitxers o similars.
En combinar tot queda una cosa molt habitual a la capçalera de scripts seriosos:
set -euo pipefail capçalera segura
IFS=$'\n\t'
Amb això evites situacions en què una ordre intermitja d'una canonada falla, però l'script segueix endavant perquè l'última comanda torna 0. També impedeixes que variables mal escrites o no definides es converteixin silenciosament en cadenes buides, cosa que sol ser l'origen de rutes incorrectes o condicions lògiques que mai no es compleixen.
Els paranys de set -e: per què no és màgia i pot trencar-te l'script
Tot i ser molt útil, set -e no és una bala de plata. El seu comportament té matisos que poden donar ensurts si no entens com funciona. Per exemple, algunes construccions com:
- Comandes dins de
if,whileountil. - Expressions amb
&&y||per a control de flux. - Determinades expansions aritmètiques.
no disparen “l'èxit immediat” com podries esperar. Un cas clàssic és el de expansió aritmètica amb postincrement:
((contador++))
L'expansió aritmètica torna un valor que Bash interpreta com a codi de sortida. En el cas del postincrement, quan l'expressió torna 0 es considera èxit, però en altres moments pot tornar 1, cosa que amb set -e fa que l'script s'acabi allà mateix. Una cosa tan innocent com un comptador dins d'un bucle pot fer que el teu script surti abans d'hora.
En canvi, construccions com ((++i)) o ((i+=1)) es comporten de manera diferent i no disparen el mateix problema. Això demostra que amb set -e has de conèixer bé les construccions que fas servir, perquè hi ha molts casos límit.
Per això, diversos autors i administradors amb experiència recomanen fer servir set -e sobretot en fase de proves, com una forma agressiva de trobar punts febles, però en producció prefereixen un enfocament més explícit: comprovar codis de sortida a mà i decidir exactament quan i com s'avorta l'script.
trap: capturar errors i senyals per netejar i llogar bé
la comanda trampa és l'altre gran protagonista quan parlem de scripting defensiu a Bash. Bàsicament, permet indicar quines ordres o funcions vols executar quan l'intèrpret d'ordres rebi un senyal o un esdeveniment especial (com ERR o EXIT).
usos típics Els usos típics de trap en scripts robusts són:
- trap 'funcio_maneig_error' ERR: executar lògica de maneig derrors just quan una ordre falla.
- trap 'funcio_neteja' INT TERM: reaccionar a senyals com CTRL+C (SIGINT) o peticions de parada (SIGTERM).
- trap 'funcio_finalització' EXIT: executar un bloc en sortir l'script, hagi anat bé o malament.
Imagina un script que, en rebre CTRL+C, en lloc de tallar-se en sec, truqui a una funció neteja que esborri temporals, tanqui connexions o deixi un missatge clar als logs:
trap 'limpieza' TERM INT acció preventiva
function limpieza(){
echo "Ejecutando limpieza, el usuario uso CTRL + C"
# ... lógica de limpieza ...
}
Aquest patró és especialment útil en processos llargs (backups, ETL, desplegaments) on t'interessa poder avortar de forma controlada i sense deixar el sistema en estat inconsistent.
Què pots i què no pots capturar amb trap ERR
exemple comú Moltes guies proposen fer servir alguna cosa com:
trap 'echo "Error en línea $LINENO" >&2' ERR capturar línia
per registrar errors amb el número de línia. Això està bé, però convé entendre els seus límits. Trap pot:
- Executar codi addicional quan es dispara ERR, per exemple escriure en un log amb data, script i línia.
- Accedir al codi de sortida de l'última ordre amb
$?. - conèixer la línia de script amb $LINENO, molt útil per a depuració.
El que no pot fer el trap d'ERR és “rescatar” la sortida estàndard d'error (stderr) d'una ordre que ja ha corregut, tret que tu mateix l'hagis redirigit prèviament a un fitxer o descriptor que després puguis llegir. L'error en si és un flux de text, no un valor únic.
Alguns patrons consisteixen a redirigir l'stderr de tot l'script a un log temporal i, al trap, afegir una capçalera amb data, fitxer i línia per poder correlacionar aquest bloc d'errors amb el punt de l'script on es va produir la decisió. És més feina, però quan alguna cosa peta en producció agraeixes tenir context.
Logging a Bash: registrar el que és just, amb format i sense embrutar
Si automatitzes tasques mínimament crítiques, cal saber què ha passat, quan i amb quin resultat. Per això gairebé tots els exemples de scripting seriós acaben incloent-hi una funció de logging centralitzada que unifiqui el format.
funció típica Una funció típica pot tenir aquest aspecte:
log_message() { format unificat
local level="$1"
local message="$2"
local timestamp=$(date "+%Y-%m-%d %H:%M:%S")
echo -e "${timestamp} ${message}" | tee -a "$LOG_FILE"
}
Example Amb una cosa així pots trucar a:
- log_message «INFO» «Iniciant comprovació de CPU»
- log_message «WARNING» «Ús de disc per sobre del 85%»
- log_message «ERROR» «No s'ha pogut connectar a la base de dades»
i tenir sempre el mateix format, amb data i nivell ben marcats. Usar tee -a a més et permet veure el missatge per pantalla i guardar-lo en un fitxer de log alhora, una cosa molt còmoda tant per a ús interactiu com per a anàlisi posterior.
Una altra bona pràctica és separar logs d'activitat (què fa l'script) i logs de mètriques o resultats (valors de CPU, RAM, disc, etc.) en fitxers diferents. Per exemple:
- /var/log/system-monitor.log per a esdeveniments i missatges.
- /var/log/system-metrics.log per a registres periòdics d'estat.
facilita integració Això facilita després alimentar eines externes, parsers o fins i tot solucions d'observabilitat sense barrejar missatges humans amb dades de màquina.
Revisió d'estat del sistema: CPU, memòria, disc, xarxa i logs
Un ús molt recurrent de Bash en entorns Linux és implementar un script de “verificació ràpida” del sistema que reuneixi de cop la informació bàsica per diagnosticar problemes. Aquest tipus de script sol incloure diversos blocs:
- Càrrega de CPU: usant
mpstatsi està disponible (gràcies al paquet sysstat), o recorrent atopen mode batch per treure un resum dús de CPU. - Top processos per CPU: amb
ps aux --sort=-%cpu | head -n Nper veure què està consumint més recursos. - Espai en disc: amb
df -h, revisant especialment la partició arrel i qualsevol volum crític per a aplicacions o bases de dades (veure com alliberar espai a Linux). - Memòria RAM i SWAP: A través de
free -h, per veure quant s'està usant i si s'està llençant excessivament de swap. - Estat de la xarxa: comprovant connectivitat externa amb un ping a una IP coneguda (típicament 8.8.8.8) i llistant interfícies actives amb
ip addr show, i usant eines com netcat (nc/ncat) per a proves més avançades. - Logs recents del sistema: traient les últimes línies amb
journalctl -no equivalents, per detectar errors de serveis just abans que l'script s'executi.
El resultat sol guardar-se en un fitxer de log o mostrar-se formatat en pantalla, servint com fotografia ràpida de salut del sistema que pots revisar tu o integrar-lo en eines de monitorització.
Instal·lació automàtica de dependències i revisió de privilegis
condicions prèvies Un detall important de molts scripts d'administració és que, abans de fer res seriós, verifiquen que es compleixen dues condicions:
- L'script s'està executant com root (o via sudo).
- Les eines necessàries estan instal·lades en funció del sistema operatiu.
comprovació root La verificació de root sol fer-se amb $EUID:
check_root() { falla si no root
if ; then
log_message "ERROR" "Este script necesita privilegios de root para instalar paquetes."
log_message "WARNING" "Por favor, ejecute con sudo."
exit 1
fi
}
D'aquesta manera evites errors posteriors per permisos insuficients i envies un missatge clar a l'usuari des del principi.
detectar distro La instal·lació de dependències sol recolzar-se en /etc/os-release per detectar la família de distribució:
- En Debian / Ubuntu s'usa
apt-getper instal·lar paquets com sysstat, lm-sensors, net-tools. - En CentOS / RHEL / Fedora es llençaria de
dnfoyumamb paquets equivalents (lm_sensors, net-tools, etc.).
Alertes, cron i exportació de logs: portar l'script a producció
Quan tens un script de revisió o automatització mitjanament robust, el següent pas lògic és integrar-lo al dia a dia:
- Alertes per correu, Slack o altres canals: per exemple, si el disc supera el 90% d'ús, envieu un correu amb mailx o utilitzeu un webhook de Slack. El patró típic és comprovar el valor amb df/awk/sed i, si supera un cert llindar, disparar la notificació.
- Execució periòdica amb cron: afegir una entrada de l'estil
0 8 * * * /ruta/a/script.shperquè s'executi cada dia a una hora concreta. - Redirecció de sortida a fitxers de log: executar
./script.sh > /var/log/system-check.log 2>&1si vols registrar tota la sortida estàndard i derror en un únic fitxer.
Cal tenir clar que, si el teu script està pensat per parar davant el primer error gràcies a set -euo pipefail, això implica que el cron o el pipeline de CI/CD que ho truqui veuran clarament un codi de sortida diferent de zero quan hi hagi una fallada, cosa que et permet disparar fluxos de recuperació, marcar builds com a fallides, etc.
Depuració a Bash: set -x, -v, -ni la traça en fitxer
Bash no té un depurador a l'estil d'altres llenguatges, però sí que en proporciona diverses opcions de depuració molt potents que, usades bé, estalvien moltes hores de “per què nassos passa això?”:
- establir -x o setembre -o xtrace: mostra cada ordre que s'executa amb tots els paràmetres ja expandits. Ideal per veure quins valors reals estan prenent les variables.
- conjunt -v o setembre -o verbose: imprimeix les línies de l'script segons es llegeixen, fins i tot abans de l'expansió. Útil per entendre el flux.
- set -n o set -o noexec: analitza la sintaxi sense arribar a executar el codi, perfecte per caçar cometes, claus o claudàtors que falten.
- set -u: ja comentat, falla quan es fan servir variables no definides, cosa molt útil durant la depuració d'errors lògics.
A més, podeu limitar l'efecte d'aquestes opcions a un fragment concret de l'script embolicant-ho amb set -x / set +x, per exemple:
set -x traça temporal
# bloque problemático
read -p "Pass Dir name : " D_OBJECT
read -p "Pass File name : " F_OBJECT
set +x
#!/bin/bash redirigir traça
exec 6> salida_debug.log
BASH_XTRACEFD="6"
set -x
# ... resto del script ...
Així, tota la informació de depuració es guarda a sortida_debug.log, i tu pots seguir veient a la terminal només la sortida “normal” de l'script.
Exemple típic de bug amb variables no definides
Un problema molt comú quan no utilitzes set -u és invocar variables que no existeixen sense adonar-te'n. Imagina un script que demana un nom d'objecte i comprova si és fitxer o directori, però s'equivoca de nom de variable:
#!/bin/bash error de variable
read -p "Nombre del Objeto : " OBJECT
if ]; then
echo "$OBJECT es un archivo"
elif ]; then
echo "$OBJECT es un directorio"
fi
Com a $OBJECT1 no està definida, Bash l'expandeix a cadena buida, les proves -fy -d no donen error, simplement no es compleixen, i l'script surt amb codi 0. No passa res, però lògicament el resultat no és l'esperat.
Si en canvi executes l'script amb bash -u scriptname o actives set -u, obtindràs immediatament un error de “Unbound variable”, cosa que et porta directe a la fallada de tipat. Combinat amb bash -x scriptname o set -x, veuràs a més en quina línia concreta i quins valors s'estan usant, cosa que fa la depuració molt més suportable.
Redactor apassionat del món dels bytes i la tecnologia en general. M'encanta compartir els meus coneixements a través de l'escriptura, i això és el que faré en aquest bloc, mostrar tot el més interessant sobre gadgets, programari, maquinari, tendències tecnològiques, i més. El meu objectiu és ajudar-te a navegar pel món digital de forma senzilla i entretinguda.