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

  1. Què és un script i quan val la pena escriure'l
  2. El shebang: la primera línia que ho canvia tot
  3. Les quatre formes d'executar un script
  4. Permisos d'execució i per què cal el ./
  5. Anatomia d'un script ben format
  6. Comentaris que serveixen d'alguna cosa
  7. Codis de sortida: exit N com a contracte
  8. Noms i ubicació dins del toolkit
  9. informe-diari.sh, versió 1

  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
Acceptar arguments Sí (reescrivint-la) No
Diverses línies i lògica Molt incòmode No
Documentar-se i versionar-se No Amb prou feines
Executar-se sola de matinada No No
Compartir-se amb un company Copiant text No

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.

  1. 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:

#!/usr/bin/env bash

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 de systemd o un altre usuari amb un altre shell, s'interpretarà amb sh i 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.

  1. 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 Procés nou segons el shebang
script.sh (pel PATH) 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.

  1. 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:

ls -l ~/veloz-ops/bin/informe-diari.sh
-rw-rw-r-- 1 joan joan 412 ago  3 12:04 /home/joan/veloz-ops/bin/informe-diari.sh

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-x

755 é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.

  1. 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.

  1. 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

  1. Codis de sortida: exit N com a contracte

A 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 0 significa «tot correcte». És l'únic valor que significa èxit.
  • exit N amb N diferent 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é.

  1. 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 ni script2.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 .sh per claredat didàctica.
  • Ubicació a bin/: com que ~/veloz-ops/bin ja és al teu PATH des 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 ./.

  1. informe-diari.sh, versió 1

Ha 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 0

Desa'l, dona-li permisos i executa'l:

chmod 755 ~/veloz-ops/bin/informe-diari.sh
informe-diari.sh
===================================================
  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 incidencia

Repassa 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 denegat i codi de sortida 126. É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 \r invisible i veuràs missatges absurds com ara bash: ./informe-diari.sh: /usr/bin/env bash^M: no such file or directory o bad interpreter. Diagnostica-ho amb file informe-diari.sh (dirà with CRLF line terminators) i arregla-ho amb dos2unix informe-diari.sh o sed -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/sh fent servir sintaxi de Bash. A Ubuntu això és dash: fallarà a [[ ]], arrays i aritmètica. Si és Bash, digues-ho.
  • Executar eines amb source. Un exit a 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 nano et deixa escriure però no desar, has perdut la feina. Comprova-ho abans amb ls -l o edita amb sudoedit.
  • Anomenar un script igual que una ordre existent. Un fitxer anomenat test o ls al teu bin/ provocarà caos. Verifica-ho abans amb type -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 Bash

Só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 0

Recorda 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

Mòdul 2: Ordres Bàsiques de Bash

Mòdul 3: Fonaments de Scripting

Mòdul 4: Scripting Intermedi

Mòdul 5: Tècniques Avançades de Scripting

Mòdul 6: Treballar amb Eines Externes

Mòdul 7: Automatització i Programació

Mòdul 8: Bones Pràctiques i Optimització

Mòdul 9: Projectes del Món Real

© Copyright 2026. Tots els drets reservats