estat-servei.sh ja distingeix procés, port i aplicació, però es queda a la porta: sap que /salud retorna un 200, no què diu. La veloz-api respon JSON —estat de la base de dades, enviaments a la cua, versió desplegada, mètriques—, i aquí el toolkit deixa de llegir fitxers que algú va deixar al disc per integrar-se amb la resta del sistema. Aquesta lliçó cobreix curl a fons per parlar amb APIs i jq per manejar JSON de debò: extreure'l, filtrar-lo, convertir-lo en columnes i també construir-lo de forma segura, perquè al final informe-diari.sh publicarà el seu resum diari en JSON.
Contingut
curlals scripts: el trio-sSf- Mètodes, capçaleres i cossos
- Fitxers, redireccions i temps d'espera
- Credencials sense deixar rastre
- Codis HTTP: què ha de distingir un script
- Cos i codi d'estat en una sola crida
- Per què NO s'analitza JSON amb
greposed jq: el model de filtres- Seleccionar, filtrar i agregar
- Controlar la sortida:
-r,-c,-ei@tsv - Construir JSON de forma segura
- Llegir JSON a Bash, i JSON com a configuració
- Aplicació: el toolkit parla amb l'API i publica JSON
curl als scripts: el trio -sSf
curl als scripts: el trio -sSfPer defecte curl està pensat per a una persona en un terminal: escriu una barra de progrés i, si el servidor contesta un error, imprimeix la pàgina d'error i retorna 0. En un script això és exactament el contrari del que vols. Tres opcions ho arreglen:
| Opció | Efecte | Per què |
|---|---|---|
-s |
Silenciós: sense barra de progrés ni missatges | La barra embruta la sortida i els registres |
-S |
Però sí que mostra els errors de curl |
Amb -s a seques, una fallada de xarxa seria muda |
-f |
Falla (codi 22) davant de respostes HTTP 4xx i 5xx | Sense això, $? val 0 encara que el servidor contesti 500 |
Memoritza -sSf com un bloc: silenciós, però que es queixi, i que falli de debò. És l'error més estès als scripts que parlen amb APIs, i produeix la pitjor de les fallades possibles: una de silenciosa que fa creure que tot va bé.
- Mètodes, capçaleres i cossos
Per a APIs REST calen quatre opcions més:
curl -sSf -X POST -H 'Content-Type: application/json' -H "Authorization: Bearer $VELOZ_TOKEN" \
-d '{"ciutat":"Madrid","estat":"incidencia"}' http://localhost:8080/envios-X fixa el mètode (GET, POST, PUT, DELETE); no cal amb -d, que ja implica POST. -H afegeix una capçalera i es repeteix tantes vegades com calgui. -d envia el cos —si comença per @, el llegeix d'un fitxer: -d @cos.json—. Per a paràmetres amb caràcters especials existeix --data-urlencode, que codifica el valor: curl -sSfG --data-urlencode "ciudad=Palma de Mallorca" http://localhost:8080/envios. Aquest -G converteix les dades en paràmetres de l'URL en lloc de cos, així que el resultat és /envios?ciudad=Palma%20de%20Mallorca. Escriure aquest URL a mà amb una variable de Bash és una fallada esperant a passar: un espai, un & o un accent al valor i la petició canvia de significat.
- Fitxers, redireccions i temps d'espera
| Opció | Què fa |
|---|---|
-o fitxer |
Desa el cos en aquest fitxer (-o /dev/null per llençar-lo) |
-O |
Desa amb el nom que té a l'URL |
-L |
Segueix les redireccions 301/302 (no ho fa per defecte) |
--connect-timeout N |
Màxim per establir la connexió |
--max-time N |
Màxim per a tota l'operació |
Els dos temps d'espera són diferents i cal posar-los tots dos. --connect-timeout 5 talla ràpid quan la màquina no hi és; --max-time 30 protegeix del servidor que accepta la connexió i després es queda pensant indefinidament. Un curl sense --max-time en un script automàtic és una bomba de rellotgeria: el dia que el servei s'encalli, la teva tasca de cron es quedarà penjada per sempre i bloquejarà les següents (07-01).
- Credencials sense deixar rastre
-u usuari:clau fa autenticació bàsica, però escrita així la contrasenya apareix a ps, a l'historial (02-06) i a qualsevol registre de l'ordre. Les dues formes correctes:
curl -sSf --netrc-file ~/.netrc https://api.veloz.example/envios # credencials en fitxer 600
curl -sSf -H "Authorization: Bearer $VELOZ_TOKEN" http://localhost:8080/metricas--netrc-file llegeix màquina, usuari i clau d'un fitxer amb permisos 600, igual que veloz-ops.conf (05-06). La segona opció fa servir una variable d'entorn carregada des d'aquest fitxer de configuració: no queda a l'historial, encara que sí que és visible a /proc/<pid>/environ per al mateix usuari i per a root. El que no s'ha de fer mai és incrustar la credencial a l'URL, com ja es va veure a 06-04.
- Codis HTTP: què ha de distingir un script
| Família | Significat | Què ha de fer l'script |
|---|---|---|
| 2xx | Correcte | Continuar |
| 3xx | Redirecció | Seguir-la amb -L, o tractar-la com a configuració incorrecta |
| 4xx | Tu t'has equivocat (401, 403, 404, 422) | Fallar i no reintentar: reintentar no ho arreglarà |
| 5xx | El servidor ha fallat (500, 502, 503) | Reintentar amb retrocés (06-04); pot ser temporal |
| Sense resposta | Xarxa, DNS, temps esgotat | Distingir-ho d'un 5xx al missatge |
Aquesta distinció entre 4xx i 5xx és la que fa útil un script d'integració: reintentar un 404 és perdre el temps, i no reintentar un 503 és donar per caigut un servei que s'estava reiniciant. I recorda el punt de partida: sense -f, curl retorna 0 amb qualsevol codi, així que sense ell ni tan sols te n'assabentes.
- Cos i codi d'estat en una sola crida
-f et diu que hi ha hagut error, però descarta el cos, que sol contenir l'explicació. Per tenir totes dues coses sense fer dues peticions, es demana el codi amb -w al final i se separa després:
resposta=$(curl -sS -w '\n%{http_code}' --max-time 10 "http://localhost:8080/envios?ciudad=Madrid")
codi="${resposta##*$'\n'}" # ultima linia: el codi
cos="${resposta%$'\n'*}" # tot l'anterior: el cos
case "$codi" in
2??) veloz_log_info "consulta correcta" ;;
4??) veloz_morir 1 "peticio incorrecta ($codi): $cos" ;;
5??) veloz_log_error "error del servidor ($codi), reintentant"; return 1 ;;
*) veloz_morir 1 "sense resposta de l'API" ;;
esacAquí es juxtaposen tres coses de mòduls anteriors: -w '\n%{http_code}' afegeix el codi en una línia nova al final, les expansions ${var##*} i ${var%*} de 04-04 el separen del cos sense llançar processos, i el case amb globs de 04-05 classifica per família amb 2??. Fixa't que aquí no es fa servir -f: volem el cos de l'error, així que la decisió la pren el case.
- Per què NO s'analitza JSON amb
grep o sed
grep o sedLa temptació és enorme i el resultat sempre acaba malament. Per treure l'estat de /salud, el que tothom escriu la primera vegada és curl -s $API/salud | grep -o '"estat":"[^"]*"' | cut -d'"' -f4. Funciona fins que deixa de fer-ho, i les raons no són rebuscades: el JSON pot venir compacte o amb salts de línia (la teva regex depèn del format, que el servidor pot canviar sense avisar); l'ordre de les claus no està garantit; pot aparèixer un objecte imbricat amb una altra clau estat i el teu grep agafarà la primera que trobi; un valor pot contenir cometes escapades ("missatge":"error \"greu\"") que destrossen [^"]*; i null, els números i els booleans no porten cometes, així que el patró ni els veu. En resum: JSON no és un format de línies, i les eines de línies no el poden entendre amb fiabilitat. El que fa falta és un analitzador, i aquest és jq.
jq: el model de filtres
jq: el model de filtresjq és un llenguatge de filtres: rep un document JSON, li aplica una expressió i emet JSON. La idea central és que tot filtre transforma una entrada en zero, una o diverses sortides, i s'encadenen amb | com les canonades del shell.
Suposem que /salud retorna {"estat":"ok","versio":"2.4.1","bd":{"connectada":true,"latencia_ms":12},"cua":[3,7,2]}:
| Filtre | Resultat | Què fa |
|---|---|---|
. |
Tot el document formatat | Identitat; útil per llegir-lo |
.estat |
"ok" |
Accedeix a una clau |
.bd.latencia_ms |
12 |
Camí imbricat |
.cua[0] |
3 |
Índex d'un array |
.cua[1:] |
[7,2] |
Llesca |
.cua[] |
3, 7, 2 |
Itera: emet tres sortides separades |
.cua | length |
3 |
Longitud d'array, objecte o cadena |
keys |
["bd","cua","estat","versio"] |
Claus ordenades |
has("estat") |
true |
Existeix aquesta clau? |
.inexistent |
null |
Una clau inexistent no és un error |
.estat // "desconegut" |
"ok" |
Valor per defecte si és null o false |
.bd.x? |
(res) | ? suprimeix l'error si el tipus no encaixa |
Les dues últimes files són les que eviten la meitat dels ensurts: // dona un valor per defecte quan l'API omet un camp, i ? impedeix que un error de tipus avorti tot el filtre. La diferència entre .cua (un array) i .cua[] (tres sortides) és el concepte que cal interioritzar: la majoria dels filtres interessants treballen sobre fluxos de valors, no sobre un de sol.
- Seleccionar, filtrar i agregar
Sobre una resposta de /envios?ciudad=Madrid, que retorna un array d'objectes amb id, estat i import:
curl -sSf "$API/envios?ciudad=Madrid" | jq '.[] | select(.estat == "incidencia")'
curl -sSf "$API/envios?ciudad=Madrid" | jq '[.[] | .import] | add'| Filtre | Què fa |
|---|---|
select(cond) |
Deixa passar només els elements que compleixen la condició |
map(f) |
Aplica f a cada element d'un array ([.[] | f] abreujat) |
add |
Suma els elements d'un array (o els concatena) |
length |
Nombre d'elements, claus o caràcters |
sort_by(.camp) |
Ordena un array per aquest camp |
min / max / min_by(.c) |
Extrems |
group_by(.camp) |
Agrupa en un array d'arrays (cal ordenar pel mateix camp) |
to_entries |
Converteix {"a":1} en [{"key":"a","value":1}] per poder iterar objectes |
Els claudàtors de [.[] | .import] són importants: .[] | .import emet tres valors solts, i add necessita un array, així que cal recollir-los. Confondre «flux de valors» amb «array» és l'error número u amb jq, i s'arregla sempre amb [ ] o amb map(). Veuràs que group_by + map és la mateixa agregació que feies amb arrays associatius a awk (06-01), només que sobre JSON.
- Controlar la sortida:
-r, -c, -e i @tsv
-r, -c, -e i @tsvPer defecte jq emet JSON, així que una cadena surt entre cometes: "ok", no ok. En assignar-la a una variable de Bash, aquestes cometes hi viatgen i espatllen qualsevol comparació posterior.
| Opció | Efecte |
|---|---|
-r |
Raw: emet les cadenes sense cometes |
-c |
Compacte: cada resultat en una sola línia |
-e |
El codi de sortida reflecteix el resultat: 1 si ha estat null o false |
-n |
No llegeix entrada; construeix des de zero (secció 11) |
estat=$(curl -sSf "$API/salud" | jq -r '.estat') # "ok" -> ok
[[ "$estat" == ok ]] || veloz_log_error "API en estat $estat"
curl -sSf "$API/salud" | jq -e '.bd.connectada' >/dev/null || veloz_log_error "BD desconnectada"-e converteix una consulta JSON en una condició de shell, sense variables intermèdies. I per tornar al terreny d'awk, @tsv i @csv converteixen arrays en columnes:
curl -sSf "$API/envios?ciudad=Madrid" | jq -r '.[] | [.id, .estat, .import] | @tsv' |
awk -F'\t' '{ s[$2] += $3 } END { for (e in s) printf "%-12s %8.2f\n", e, s[e] }'Aquest encadenament és el pont entre els dos mons: jq entén l'estructura i l'aplana a columnes; awk agrega. @csv posa els camps entre cometes segons les regles de CSV, i tots dos necessiten -r perquè no surti tot com una cadena JSON escapada.
- Construir JSON de forma segura
Generar JSON a mà —printf '{"ciutat":"%s","nota":"%s"}\n' "$ciutat" "$nota"— funciona fins al primer valor amb una cometa, una barra invertida o un salt de línia, i llavors produeix JSON invàlid o, pitjor, JSON vàlid amb el contingut canviat. La forma correcta és jq -n, que construeix des de zero, amb --arg per a cadenes i --argjson per a valors que ja són JSON (números, booleans, objectes):
jq -n --arg data "$DATA" --arg host "$(hostname)" \
--argjson total "$total" --argjson taxa "$taxa" \
'{data: $data, host: $host, total: $total, taxa_lliurament: $taxa}'
# -> {"data":"2026-08-03","host":"srv-veloz-01","total":1001,"taxa_lliurament":87.3}jq s'encarrega de l'escapada: una cometa dins de $nota surt com a \", un salt de línia com a \n i els accents es codifiquen correctament. La distinció entre --arg i --argjson és el parany habitual: --arg total 1001 produeix "1001" (cadena) i --argjson total 1001 produeix 1001 (número). Si el valor pot venir buit, --argjson fallarà —jq no accepta JSON invàlid—, així que convé un ${total:-0}. I com amb awk -v a 06-01, el principi és el mateix: els valors de Bash entren com a paràmetres, mai interpolats dins del filtre, perquè interpolar-los és injecció de codi.
- Llegir JSON a Bash, i JSON com a configuració
Per recórrer una resposta a Bash, la combinació és jq -r '.[] | @tsv' amb el bucle de 04-01:
while IFS=$'\t' read -r id estat import; do
[[ "$estat" == incidencia ]] && veloz_log_error "enviament $id amb incidencia ($import EUR)"
done < <(curl -sSf "$API/envios?ciudad=Madrid" | jq -r '.[] | [.id, .estat, .import] | @tsv')@tsv és preferible a separar per espais perquè els valors en poden contenir, i a més escapa els tabuladors i els salts de línia que hi hagués dins d'un camp. La substitució de processos < <( ) de 05-05 manté el bucle al shell actual. Quan el que necessites és un array de Bash amb una sola columna, mapfile -t ids < <(jq -r '.[].id' <<< "$json") (04-03) és més directe.
JSON també serveix com a format de configuració, i jq el llegeix amb les mateixes regles: jq -r '.llindars.disc // 85' etc/veloz.json retorna el valor o el defecte si falta. Davant del clau=valor de veloz-ops.conf (05-06), guanya en estructura imbricada i tipus, i perd en què no es pot carregar amb source i no admet comentaris. Per a YAML —el format dels fitxers de CI i de Kubernetes— existeix yq, que replica la sintaxi de jq sobre YAML i fins i tot converteix entre tots dos amb yq -o=json. Si ja saps jq, saps yq.
- Aplicació: el toolkit parla amb l'API i publica JSON
Primer, estat-servei.sh consulta l'API de debò i distingeix caiguda d'error d'aplicació, que és la diferència entre reiniciar el servei i avisar l'equip de desenvolupament:
comprovar_api_json() {
local api="http://localhost:8080" cos codi sortida
sortida=$(curl -sS -w '\n%{http_code}' --connect-timeout 3 --max-time 10 "$api/salud") || {
veloz_log_error "veloz-api: sense resposta (xarxa, DNS o servei caigut)"; return 1; }
codi="${sortida##*$'\n'}"; cos="${sortida%$'\n'*}"
[[ "$codi" == 2?? ]] || {
veloz_log_error "veloz-api: HTTP $codi — $(jq -r '.missatge // "sense detall"' <<< "$cos")"
return 1; }
jq -e '.estat == "ok"' <<< "$cos" >/dev/null ||
veloz_log_error "veloz-api: viva pero degradada ($(jq -r '.estat' <<< "$cos"))"
veloz_log_info "veloz-api $(jq -r '.versio' <<< "$cos") — BD $(jq -r 'if .bd.connectada then "ok" else "KO" end' <<< "$cos")"
}Els tres desenllaços són diferents a propòsit: sense resposta (el curl falla), resposta amb error HTTP (s'extreu .missatge del cos per a l'avís) i resposta correcta però amb estat degradat. jq -e fa servir el JSON com a condició i l'if ... then ... else ... end de jq formata el booleà per al missatge. Fixa't en el <<< "$cos", la cadena-document de 05-05: evita rellegir la resposta de la xarxa cada vegada.
I informe-diari.sh tanca el cercle publicant el seu resum com a JSON, construït amb jq -n:
publicar_resum() {
local desti="$BASE_DIR/logs/resum-$(date +%F).json" tmp
tmp=$(mktemp) && trap 'rm -f "$tmp"' RETURN
jq -n --arg data "$(date +%F)" --arg host "$(hostname -f)" \
--argjson total "${total:-0}" --argjson taxa "${taxa:-0}" \
'{generat: (now | todate), data: $data, host: $host,
resum: {enviaments: $total, taxa_lliurament: $taxa}}' > "$tmp" && mv "$tmp" "$desti"
veloz_log_info "resum publicat a $desti"
}El mktemp amb trap de 05-01 i el mv final garanteixen que ningú no llegeixi mai un fitxer a mig escriure: o existeix el resum complet o existeix el del dia anterior. now | todate genera la marca de temps en UTC ISO-8601 sense cridar date. I ara l'informe ja no és només un text per llegir: és una dada que un altre programa —un panell, una alerta, el projecte 09-05— pot consumir sense tornar a analitzar res.
Errors Habituals i Consells
curlsense-f(o sense comprovar el codi). Retorna 0 amb un 500 i l'script continua com si res. Fes servir-sSf, o-w '%{http_code}'i uncase.curlsense--max-time. Un servei encallat penja la tasca de cron indefinidament.- Analitzar JSON amb
grep/sed. Falla amb el format compacte, l'ordre de claus, els imbricats i les cometes escapades. Fes servirjq. - Oblidar
-r.estat=$(jq '.estat')desa"ok"amb cometes i[[ $estat == ok ]]falla. - Confondre flux amb array.
.[] | .importemet valors solts;addnecessita[.[] | .import]. --argper a números. Produeix"1001"en comptes de1001; per a números i booleans,--argjson.- Interpolar variables de Bash dins del filtre
jq. Mateix risc d'injecció que a awk: fes servir--arg. - Reintentar un 4xx. No s'arreglarà sol. Reintenta els 5xx i les fallades de xarxa, amb retrocés (06-04).
- Consell: construeix els filtres per passos (
jq '.', desprésjq '.camp'…) contra una resposta d'exemple desada en un fitxer: és més ràpid que cridar l'API, funciona sense connexió ijqes depura molt millor en increments que d'una tirada.
Exercicis
Exercici 1. Escriu una funció veloz_api_get per a lib/comu.sh que faci GET a un camí de l'API, retorni el cos per la sortida estàndard, distingeixi xarxa / 4xx / 5xx amb missatges diferents i codis de sortida diferents, i no es pugui penjar.
Exercici 2. Amb /metricas retornant {"peticions":48210,"errors":37,"latencia_p95_ms":210,"enviaments_cua":14}, escriu una comprovació que avisi si la taxa d'errors supera el 0,1 % o si la latència p95 passa de 500 ms, tractant els camps que faltin com a 0.
Exercici 3. Converteix la sortida de /envios?ciudad=Madrid (array d'objectes amb id, repartidor, estat, import) en un resum per repartidor amb nombre d'enviaments i import total, ordenat de major a menor, fent servir només jq.
Solucions
Solució 1.
# veloz_api_get — GET a l'API. Us: veloz_api_get <cami>. Retorna el cos per stdout.
veloz_api_get() {
local cami="${1:?falta el cami}" base="${VELOZ_API:-http://localhost:8080}" sortida codi
sortida=$(curl -sS -w '\n%{http_code}' --connect-timeout 3 --max-time 15 "$base$cami") ||
{ veloz_log_error "API: sense resposta a $cami"; return 69; }
codi="${sortida##*$'\n'}"
case "$codi" in
2??) printf '%s\n' "${sortida%$'\n'*}" ;;
4??) veloz_log_error "API: peticio incorrecta ($codi) a $cami"; return 64 ;;
*) veloz_log_error "API: error del servidor ($codi) a $cami"; return 75 ;;
esac
}Els tres codis són deliberats i segueixen la taula de 05-03: 69 (EX_UNAVAILABLE) quan no hi ha resposta, 64 (EX_USAGE) per a un 4xx —l'error és nostre— i 75 (EX_TEMPFAIL) per a un 5xx, que és precisament el codi que diu a qui la crida «això és temporal, pots reintentar». El cos surt net per stdout i els diagnòstics per stderr (02-04), de manera que dades=$(veloz_api_get /salud) captura només el que interessa.
Solució 2.
metriques=$(veloz_api_get /metricas) || exit $?
read -r peticions errors p95 < <(jq -r '[.peticions // 0, .errors // 0,
.latencia_p95_ms // 0] | @tsv' <<< "$metriques")
awk -v e="$errors" -v p="$peticions" 'BEGIN { exit !(p > 0 && 100*e/p > 0.1) }' &&
veloz_log_error "taxa d'errors per sobre del 0.1% ($errors de $peticions)"
(( p95 > 500 )) && veloz_log_error "latencia p95 de ${p95}ms per sobre del llindar"El // 0 de cada camp evita que una mètrica absent es converteixi en null i trenqui els comptes. Els tres valors s'extreuen en una sola invocació de jq amb @tsv i un read, en comptes de cridar-lo tres vegades. La taxa d'errors és decimal, així que la comparació va a awk amb l'idioma exit !(...) de 06-03; la latència és entera i en té prou amb (( )).
Solució 3.
veloz_api_get "/envios?ciudad=Madrid" |
jq -r 'group_by(.repartidor)
| map({repartidor: .[0].repartidor, enviaments: length, total: (map(.import) | add)})
| sort_by(-.total)
| .[] | [.repartidor, .enviaments, (.total | tostring)] | @tsv' |
column -tgroup_by produeix un array d'arrays —un per repartidor—, i map el converteix en objectes: .[0].repartidor pren el nom de qualsevol element del grup, length compta i map(.import) | add suma. sort_by(-.total) ordena descendent negant el valor, més net que ordenar i després reverse. Al final, @tsv aplana a columnes i column -t (02-02) les alinea. És exactament l'agregació de la solució 1 de 06-01, però partint de JSON en comptes de CSV.
Conclusió
Parlar amb una API des d'un script són dues eines i unes quantes regles. De curl: -sSf com un bloc indivisible —silenciós, queixós davant de fallades de xarxa i fallant de debò davant d'un error HTTP, perquè sense -f retorna 0 amb un 500—; -X, -H, -d i --data-urlencode per construir la petició; -L, -o/-O per al cos; --connect-timeout i --max-time sempre, o el dia que el servei s'encalli penjaràs la tasca de cron; credencials per --netrc o capçalera des d'un fitxer 600, mai a l'URL; i -w '\n%{http_code}' per quedar-te amb cos i codi en una sola crida i classificar amb un case que distingeixi 4xx (no reintentar) de 5xx (reintentar amb retrocés). De jq: un llenguatge de filtres encadenats amb | on .camp, .a.b, .[], select, map, group_by, add, sort_by, length, to_entries, // i ? cobreixen gairebé tot; -r per treure cadenes sense cometes, -e per fer servir JSON com a condició, @tsv/@csv per tornar al terreny d'awk; i jq -n --arg/--argjson per construir JSON amb l'escapada resolta, passant els valors de Bash com a paràmetres i mai interpolats. I la regla que ho engloba tot: JSON no és un format de línies, així que grep i sed no serveixen per llegir-lo.
Amb això es tanca el Mòdul 6 i el toolkit de Veloz Envíos canvia de naturalesa. informe-diari.sh agrega en una sola passada amb awk i publica el seu resum en JSON; estat-servei.sh reuneix el context del sistema, comprova xarxa i port, interroga la veloz-api i distingeix una caiguda d'un error d'aplicació. Ja no és un lector de fitxers: és una peça integrada amb la resta del sistema. Però fixa't en el que tenen en comú totes les execucions d'aquest mòdul: has estat tu qui ha escrit l'ordre. L'informe diari només existeix si algú es recorda de llançar-lo, i una comprovació d'estat que s'executa quan ja sospites que alguna cosa va malament arriba tard per definició. Al Mòdul 7 això s'acaba: cron perquè les tasques s'executin soles (07-01), el disseny de tasques veritablement desateses (07-02), còpies de seguretat automàtiques (07-03), monitoratge i registre continus (07-04), serveis i temporitzadors de systemd (07-05) i automatització remota amb ssh (07-06). El toolkit deixa d'esperar les teves ordres.
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
