Tancàvem el Mòdul 2 amb un límit ben concret: un àlies no accepta arguments, una canonada de cinc filtres no es pot documentar ni versionar, i res del que teclegis avui s'executarà demà a les set del matí sense tu al davant. Aquesta lliçó trenca aquest límit. Desaràs aquestes línies en un fitxer, diràs al sistema com executar-lo i el convertiràs en una ordre de ple dret dins de ~/veloz-ops/bin. En acabar tindràs la primera versió real d'informe-diari.sh, l'script que creixerà amb tu durant tot el mòdul fins a convertir-se en l'eina central del toolkit de Veloz Envíos.
Contingut
- Què és un script i quan val la pena escriure'l
- El shebang: la primera línia que ho canvia tot
- Les quatre formes d'executar un script
- Permisos d'execució i per què cal el
./ - Anatomia d'un script ben format
- Comentaris que serveixen d'alguna cosa
- Codis de sortida:
exit Ncom a contracte - Noms i ubicació dins del toolkit
informe-diari.sh, versió 1
- Què és un script i quan val la pena escriure'l
Un script de Bash és un fitxer de text pla amb ordres, una per línia, que el shell llegeix i executa de dalt a baix. No hi ha compilació, no hi ha projecte, no hi ha dependències: exactament les mateixes ordres que teclegis al terminal, desades en un fitxer.
Aquesta simplicitat enganya, perquè el que aporta el fitxer no és potència sinó permanència. Compara-ho amb el que has fet fins ara:
| Necessitat | Canonada teclejada | Àlies | Script |
|---|---|---|---|
| Executar-la demà sense recordar-la | No | Sí | Sí |
| Acceptar arguments | Sí (reescrivint-la) | No | Sí |
| Diverses línies i lògica | Molt incòmode | No | Sí |
| Documentar-se i versionar-se | No | Amb prou feines | Sí |
| Executar-se sola de matinada | No | No | Sí |
| Compartir-se amb un company | Copiant text | No | Sí |
La regla pràctica per decidir és senzilla i val la pena que la interioritzis: si has de repetir una seqüència més de dues o tres vegades, o si necessites que algú altre l'executi exactament igual, escriu un script. Per a una consulta puntual, el terminal continua sent l'eina correcta; escriure un script per a una cosa que faràs un sol cop és feina perduda.
Hi ha un tercer criteri, menys obvi però decisiu en operacions: si l'error humà surt car, escriu un script. Una cadena de filtres que teclegis cada matí acabarà tenint una errada algun dia. L'script la teclea sempre igual.
- El shebang: la primera línia que ho canvia tot
Quan el nucli de Linux executa un fitxer, necessita saber quin intèrpret l'ha de llegir. Aquesta informació va a la primeríssima línia, que comença pels caràcters #! (anomenats shebang, de sharp + bang) seguits del camí de l'intèrpret:
El shebang ha de ser la línia 1, columna 1. Ni una línia en blanc abans, ni un espai davant del #. Per al shell és un comentari més (comença per #), però per al nucli és una instrucció.
N'hi ha dues formes habituals i convé entendre'n la diferència:
| Forma | Com funciona | Avantatges | Inconvenients |
|---|---|---|---|
#!/bin/bash |
Executa el binari d'aquest camí exacte | Explícit, sense intermediaris; immune a un PATH manipulat |
Falla si Bash no és a /bin (macOS amb Homebrew, alguns BSD); fa servir sempre el Bash del sistema, encara que sigui antic |
#!/usr/bin/env bash |
Executa env, que busca bash al PATH |
Portable entre sistemes; respecta les versions instal·lades per l'usuari | Depèn del PATH; no admet opcions addicionals de manera portable |
Recomanació per a aquest curs: #!/usr/bin/env bash. És l'estàndard de facto en scripts que es comparteixen, i a srv-veloz-01 funciona igual de bé. El que mai no has d'escriure si fas servir funcionalitats pròpies de Bash és #!/bin/sh: a Ubuntu 24.04 aquest enllaç apunta a dash, un shell POSIX molt més limitat que no entén [[ ]], ni arrays ni moltes altres coses que faràs servir a partir de la lliçó següent (la portabilitat POSIX es tracta a fons a 08-07).
I si falta el shebang? L'script no dona error necessàriament, i això és el perillós. Passa el següent:
- Si l'executes amb
bash informe-diari.sh, funciona: ja has dit tu quin intèrpret cal fer servir. - Si l'executes amb
./informe-diari.sh, el nucli no sap què fer-ne i el shell interactiu l'intenta executar amb una còpia d'ell mateix. Al teu terminal Bash semblarà que funciona. - Si l'executa
cron(Mòdul 7), un servei desystemdo un altre usuari amb un altre shell, s'interpretarà ambshi fallarà de maneres desconcertants.
És a dir: l'absència de shebang produeix un script que funciona al teu terminal i falla en producció, que és el pitjor tipus de fallada possible. Per això el shebang no és cap adorn.
- Les quatre formes d'executar un script
Hi ha quatre maneres de llançar un script i no són equivalents. Entendre'n la diferència connecta directament amb els subshells de la lliçó 01-04.
bash ~/veloz-ops/bin/informe-diari.sh # 1. intèrpret explícit
./informe-diari.sh # 2. executable, indicant-ne el camí
informe-diari.sh # 3. pel seu nom, via PATH
source ~/veloz-ops/bin/informe-diari.sh # 4. source (abreujat: un punt)
. ~/veloz-ops/bin/informe-diari.sh # equivalent a l'anterior| Forma | Cal permís x? |
Respecta el shebang? | On s'executa? |
|---|---|---|---|
bash script.sh |
No | No (l'ignora, ja has triat tu) | Procés Bash nou (subshell) |
./script.sh |
Sí | Sí | Procés nou segons el shebang |
script.sh (pel PATH) |
Sí | Sí | Procés nou segons el shebang |
source script.sh |
No | No | Al teu shell actual |
Les tres primeres creen un procés fill. Aquí reviu la lliçó 01-04: les variables que l'script defineixi moren amb ell, i un cd dins de l'script no canvia el teu directori actual. Això és exactament el que vols d'una eina: que faci la seva feina i no toqui la teva sessió.
source és l'excepció radical: no crea cap procés nou, executa les línies del fitxer dins del teu shell. Per això source ~/.bashrc aplica els àlies a la sessió en curs (lliçó 01-02), i per això source és la manera correcta de carregar un fitxer de configuració o una llibreria de funcions —el patró que faràs servir amb ~/veloz-ops/etc/veloz-ops.conf i que es formalitza a 05-06—. I per això mateix no has de fer servir source per executar una eina: si l'script fa exit 1, amb source estaràs tancant el teu propi terminal.
- Permisos d'execució i per què cal el
./
./Un fitxer acabat de crear no és executable. Recupera el bit x de la lliçó 02-03:
Sense x als permisos, ./informe-diari.sh respon Permís denegat. S'arregla amb:
chmod +x ~/veloz-ops/bin/informe-diari.sh # ràpida, respecta l'umask
chmod 755 ~/veloz-ops/bin/informe-diari.sh # explícita: rwxr-xr-x755 és el permís canònic d'un script a bin/: l'amo pot llegir, escriure i executar; els altres poden llegir i executar. Si l'script contingués secrets faries servir 700, però la bona pràctica és que els secrets visquin a etc/veloz-ops.conf amb permisos 600, no pas al codi.
Queda la pregunta del ./. Quan escrius un nom sol, Bash el busca només als directoris del PATH, i el directori actual no hi és (ni hi ha de ser: si hi fos, un fitxer maliciós anomenat ls en un directori compartit s'executaria en lloc de l'ls real). El ./ converteix el nom en un camí relatiu explícit —«el fitxer que es diu així, en aquest directori»— i desactiva la cerca pel PATH. És una mesura de seguretat, no cap caprici de sintaxi.
- Anatomia d'un script ben format
Un script professional té una estructura recognoscible. Aquest és l'esquelet que faràs servir a partir d'ara:
#!/usr/bin/env bash
#
# informe-diari.sh - Resum diari d'activitat de Veloz Envíos
#
# Propòsit : Comptar els errors d'app.log i agrupar els enviaments per estat.
# Autor : Joan Costa <[email protected]>
# Creat : 2026-08-03
# Ús : informe-diari.sh
# Sortida : Informe per stdout.
# Codis : 0 correcte | 1 error d'execució
#
# --- Cos ---------------------------------------------------------------
echo "hola des del toolkit"
exit 0 # --- Sortida ---Les quatre parts, per ordre: shebang (línia 1, sense excepcions); capçalera de comentaris amb què fa, qui el va escriure, com es fa servir i què retorna —d'aquí a sis mesos, aquesta capçalera seràs tu explicant-te a tu mateix per què existeix aquest fitxer—; cos, amb les ordres agrupades en blocs separats visualment; i exit final amb el codi explícit. Aquesta estructura és la convenció que espera qualsevol que obri el fitxer, i a 08-01 l'ampliarem amb criteris de llegibilitat més fins.
- Comentaris que serveixen d'alguna cosa
Tot el que segueix un # fins al final de la línia s'ignora (llevat del shebang de la línia 1), tant en línia pròpia com al final d'una ordre. Bash no té comentaris de bloc; per comentar diverses línies es posa # a cadascuna, cosa que qualsevol editor fa amb una drecera.
L'error clàssic del principiant és comentar què fa l'ordre, que ja es llegeix a la mateixa ordre. El que té valor és comentar per què:
# MALAMENT: compta els errors
grep -c ERROR /var/log/veloz/app.log
# BÉ: veloz-api registra els 500 com a ERROR; aquest recompte alimenta l'avís
# diari a suport. Llindar acordat amb negoci: 50 errors/dia.
grep -c ERROR /var/log/veloz/app.log
- Codis de sortida:
exit N com a contracte
exit N com a contracteA la lliçó 01-04 vas conèixer $?. Ara et toca produir-lo. Quan el teu script acaba, retorna un número entre 0 i 255 que és la seva única manera de comunicar-se amb qui l'ha cridat: un altre script, cron, systemd o un canal de CI.
exit 0significa «tot correcte». És l'únic valor que significa èxit.exit NambNdiferent de 0 significa error, i el número concret indica quin error.
Si ometes l'exit, l'script retorna el codi de l'última ordre executada, que gairebé mai no és el que vols comunicar. Sigues explícit. Alguns codis tenen un significat convingut al sistema:
| Codi | Significat |
|---|---|
0 |
Èxit |
1 |
Error genèric |
2 |
Ús incorrecte de l'ordre (falten arguments, opció desconeguda) |
3… |
Errors específics que defineixes tu: p. ex. falta el fitxer de dades |
126 |
El fitxer existeix però no és executable (falta l'x) |
127 |
Ordre no trobada (no és al PATH, o el shebang apunta a un intèrpret inexistent) |
130 |
Acabat amb Ctrl-C (128 + senyal 2) |
Els codis 126 i 127 són les teves dues millors pistes de diagnòstic en aquesta lliçó: 126 és «et falta el chmod +x» i 127 és «el nom o el shebang estan malament».
Aquest contracte és el que permet escriure informe-diari.sh && enviar-correu.sh, amb el && de la lliçó 03-03: el correu només s'envia si l'informe ha acabat bé.
- Noms i ubicació dins del toolkit
Convencions que aplicarem a ~/veloz-ops/bin durant tot el curs:
- Minúscules i guions, nom descriptiu:
informe-diari.sh,rotar-logs.sh. Res d'espais, accents, majúscules niscript2.sh. El nom ha de dir què fa. - Extensió
.sh: útil mentre aprens, perquè identifica el llenguatge i activa el ressaltat de l'editor. En eines madures se sol ometre (les ordres del sistema no en porten); mantindrem.shper claredat didàctica. - Ubicació a
bin/: com que~/veloz-ops/binja és al teuPATHdes de 01-02, qualsevol script que hi deixis i marquis com a executable es converteix automàticament en una ordre del sistema, invocable des de qualsevol directori i sense./.
informe-diari.sh, versió 1
informe-diari.sh, versió 1Ha arribat el moment. Traslladarem al fitxer les canonades que ja escrivies a mà al Mòdul 2.
Obre el fitxer amb nano ~/veloz-ops/bin/informe-diari.sh i escriu-hi:
#!/usr/bin/env bash
#
# informe-diari.sh - Resum diari d'activitat de Veloz Envíos
#
# Propòsit : Comptar els ERROR d'app.log i agrupar els enviaments per estat.
# Autor : Joan Costa <[email protected]>
# Creat : 2026-08-03
# Ús : informe-diari.sh
# Codis : 0 correcte
#
echo "==================================================="
echo " INFORME DIARI - VELOZ ENVIOS"
date +" Generat: %F %T"
echo "==================================================="
# --- Errors registrats per l'aplicació -------------------------------
echo
echo "-- Errors a app.log --"
grep -c ERROR /var/log/veloz/app.log
# --- Enviaments per estat --------------------------------------------
echo
echo "-- Enviaments per estat --"
tail -n +2 /srv/veloz/dades/enviaments.csv | cut -d, -f5 | sort | uniq -c | sort -rn
exit 0Desa'l, dona-li permisos i executa'l:
===================================================
INFORME DIARI - VELOZ ENVIOS
Generat: 2026-08-03 12:11:47
===================================================
-- Errors a app.log --
37
-- Enviaments per estat --
981 lliurat
148 en_repartiment
118 incidenciaRepassa el que acaba de passar. No l'has invocat amb ./ ni amb el camí complet: has escrit informe-diari.sh a seques, des de qualsevol directori, perquè ~/veloz-ops/bin és al PATH i el fitxer té el bit x. Acabes de crear una ordre nova a srv-veloz-01.
Fixa't també en tail -n +2, que descarta la línia de capçalera del CSV: sense això, la paraula estat apareixeria com si fos un estat més. I en el fet que l'script escriu a stdout, sense redirigir res, cosa deliberada: qui el cridi decidirà si el vol veure per pantalla, desar-lo amb > informe.txt o totes dues coses amb tee. Un script ben fet no decideix pel seu invocador.
Aquest script encara té una debilitat evident: els camins i els números estan escrits a pèl, repartits pel fitxer. Si enviaments.csv canvia de lloc, cal buscar i reemplaçar. Aquest és justament el problema que resol la lliçó següent.
Errors Habituals i Consells
- Oblidar el
chmod +x. Símptoma:Permís denegati codi de sortida126. És, de llarg, la primera ensopegada de tothom. - Finals de línia CRLF. Si edites l'script a Windows, cada línia acaba amb un
\rinvisible i veuràs missatges absurds com arabash: ./informe-diari.sh: /usr/bin/env bash^M: no such file or directoryobad interpreter. Diagnostica-ho ambfile informe-diari.sh(dirà with CRLF line terminators) i arregla-ho ambdos2unix informe-diari.shosed -i 's/\r$//' informe-diari.sh. - Espai o línia en blanc abans del shebang. Deixa de ser shebang i passa a ser un comentari qualsevol.
- Escriure
#!/bin/shfent servir sintaxi de Bash. A Ubuntu això ésdash: fallarà a[[ ]], arrays i aritmètica. Si és Bash, digues-ho. - Executar eines amb
source. Unexita dins tancarà el teu terminal i les variables de l'script contaminaran la teva sessió.sourceés per a configuració i llibreries. - Editar un script del sistema sense permisos. Si el
nanoet deixa escriure però no desar, has perdut la feina. Comprova-ho abans ambls -lo edita ambsudoedit. - Anomenar un script igual que una ordre existent. Un fitxer anomenat
testolsal teubin/provocarà caos. Verifica-ho abans ambtype -a nom(lliçó 01-04).
Exercicis
Exercici 1 — Diagnòstic d'un script que no arrenca. Un company ha creat /home/juan/veloz-ops/bin/resum.sh, però en executar resum.sh obté bash: resum.sh: no s'ha trobat l'ordre, i amb ./resum.sh obté bash: ./resum.sh: Permís denegat. Explica tots dos missatges i dona les ordres que ho arreglen.
Exercici 2 — El teu segon script. Crea ~/veloz-ops/bin/estat-servidor.sh amb capçalera completa, que mostri el nom del servidor, el temps encès, l'espai lliure al disc i les tres IP que més hi han accedit segons acces.log. Ha d'acabar amb exit 0 i ser invocable pel seu nom des de qualsevol directori.
Exercici 3 — Triar la forma d'execució. Per a cada cas, indica quina de les quatre formes és la correcta i per què: (a) executar l'informe diari des de cron a les 07:00; (b) carregar les variables de ~/veloz-ops/etc/veloz-ops.conf a la teva sessió; (c) provar un script acabat de descarregar sense donar-li permisos d'execució; (d) un script que ha de canviar el directori actual del teu terminal.
Solucions
Solució a l'Exercici 1
chmod 755 ~/veloz-ops/bin/resum.sh # dona el bit x que faltava
echo $PATH | tr ':' '\n' | grep veloz # comprova que bin/ és al PATH
hash -r # refresca la memòria cau de camins de BashSón dues fallades diferents, i per això hi ha dos missatges diferents. no s'ha trobat l'ordre (codi 127) significa que Bash ha recorregut el PATH i no hi ha trobat cap fitxer anomenat resum.sh: o el directori no és al PATH, o Bash en té una versió antiga a la memòria cau (d'aquí el hash -r). Permís denegat (codi 126) és l'altre problema: amb ./ sí que troba el fitxer, però li falta el bit x. Convé resoldre tots dos, perquè arreglar només els permisos deixaria l'script sense poder-se invocar pel seu nom.
Solució a l'Exercici 2
#!/usr/bin/env bash
#
# estat-servidor.sh - Estat resumit de srv-veloz-01
#
# Propòsit : Vista ràpida de salut del servidor i del trànsit a veloz-api.
# Autor : Joan Costa <[email protected]>
# Ús : estat-servidor.sh
# Codis : 0 correcte
#
echo "-- Servidor --"; hostname; uptime
echo; echo "-- Disc --"
df -h /srv /var/log
echo; echo "-- Top 3 IP a acces.log --"
cut -d' ' -f1 /var/log/veloz/acces.log | sort | uniq -c | sort -rn | head -3
exit 0Recorda rematar-lo amb chmod 755 ~/veloz-ops/bin/estat-servidor.sh abans d'invocar-lo pel seu nom. Observa que df -h /srv /var/log limita la sortida a les particions que importen en lloc de llistar tots els sistemes de fitxers: un informe operatiu ha de respondre una pregunta, no abocar dades.
Solució a l'Exercici 3
| Cas | Forma correcta | Motiu |
|---|---|---|
(a) Des de cron a les 07:00 |
Camí absolut executable: /home/joan/veloz-ops/bin/informe-diari.sh |
cron arrenca amb un PATH mínim i sense el teu ~/.bashrc; no suposis mai que el teu PATH hi existeix (Mòdul 7) |
(b) Carregar veloz-ops.conf |
source ~/veloz-ops/etc/veloz-ops.conf |
Les variables han de quedar al teu shell; un subshell moriria amb elles |
| (c) Provar sense donar permisos | bash script.sh |
No requereix el bit x i, a més, et permet afegir-hi bash -x per veure cada línia abans de confiar-hi |
| (d) Canviar el directori actual | source (o millor, una funció) |
Un procés fill no pot canviar el directori del seu pare; és una limitació del sistema, no de Bash (lliçó 01-04) |
El cas (d) mereix un matís: que un script hagi de modificar la teva sessió sol ser senyal que el que vols no és un script sinó una funció de shell, i aquestes arriben a 04-02.
Conclusió
Has fet el salt de l'ordre al programa. Saps què és un script i quan no val la pena escriure'l; escrius el shebang correcte i entens per què la seva absència produeix fallades que només apareixen en producció; distingeixes les quatre formes d'execució i saps que source és una categoria a part perquè no crea cap subshell; dones permisos amb chmod 755 i comprens que el ./ és una defensa de seguretat; estructures el fitxer amb capçalera, cos i exit; comentes el perquè en lloc del què; i retornes codis de sortida que converteixen el teu script en una peça componible amb &&.
Sobretot, tens informe-diari.sh funcionant a ~/veloz-ops/bin i invocable pel seu nom des de qualsevol punt de srv-veloz-01. És una ordre de veritat, encara que rígida: /var/log/veloz/app.log i /srv/veloz/dades/enviaments.csv estan escrits literalment enmig del fitxer, i el llindar d'errors que vols vigilar no és enlloc.
A la lliçó 03-02 li donem memòria. Aprendràs a desar valors en variables, a fixar els camins i els llindars com a constants al principi del fitxer amb readonly, i a capturar la sortida d'una ordre dins d'una variable amb $(...). A partir d'aquí, canviar un camí serà modificar una línia, i informe-diari.sh començarà a assemblar-se a un programa.
Curs de Programació en Bash
Mòdul 1: Introducció a Bash
- Què és Bash?
- Configurar el teu Entorn
- Navegació Bàsica per la Línia d'Ordres
- Entendre el Shell
- Trobar Ajuda: man, help i --help
Mòdul 2: Ordres Bàsiques de Bash
- Operacions amb Fitxers i Directoris
- Ordres de Processament de Text
- Permisos i Propietat dels Fitxers
- Redirecció i Canonades
- Comodins i Expansió de Rutes
- Historial i Dreceres de Teclat
Mòdul 3: Fonaments de Scripting
- Crear i Executar un Script
- Variables i Constants
- Operadors Bàsics
- Sentències Condicionals
- Arguments i Entrada de l'Usuari
- Cometes, Expansió i Substitució
Mòdul 4: Scripting Intermedi
- Bucles en Bash
- Funcions en Bash
- Arrays i Arrays Associatius
- Manipulació de Cadenes
- La Sentència case i els Menús Interactius
- Aritmètica i Càlculs Numèrics
Mòdul 5: Tècniques Avançades de Scripting
- Operacions Avançades amb Fitxers
- Gestió de Processos
- Gestió d'Errors i Depuració
- Expressions Regulars
- Entrada/Sortida Avançada: Descriptors i Here-Documents
- Scripts Modulars i Llibreries Reutilitzables
Mòdul 6: Treballar amb Eines Externes
Mòdul 7: Automatització i Programació
- Tasques Cron
- Automatitzar Tasques
- Scripts de Còpia i Restauració
- Monitoratge i Registre
- Serveis i Temporitzadors amb systemd
- Automatització Remota amb SSH
Mòdul 8: Bones Pràctiques i Optimització
- Escriure Codi Llegible
- Optimitzar Scripts en Bash
- Consideracions de Seguretat
- Control de Versions amb Git
- Anàlisi Estàtica amb ShellCheck i shfmt
- Proves Automatitzades amb Bats
- Portabilitat: POSIX sh enfront de Bashismes
