La lliçó anterior va acabar amb un diagnòstic i una tasca pendent: la còpia de seguretat nocturna de Tramontana s'executa a l'hora equivocada, amb la prioritat equivocada i sobre més dades de les necessàries. Algú la va programar en algun moment i ningú no hi ha tornat a mirar. És el retrat exacte de l'automatització mal feta: funciona fins que un dia tira el servei a terra.
cron és el temporitzador d'Unix. Porta funcionant des del 1975 i continua sent la manera més estesa de dir a un servidor «fes això cada dia a les quatre». La seva sintaxi és breu i les seves fallades són sempre les mateixes tres, repetides a totes les empreses del món. Aquesta lliçó et dona la sintaxi completa i, sobretot, aquestes tres fallades amb la seva solució, perquè són el 90 % de les incidències reals de cron.
Una precisió d'abast: aquí les tasques seran d'una sola línia o crides a ordres existents. Escriure l'script de còpia amb les seves comprovacions i la seva gestió d'errors és el Mòdul 4.
Contingut
- Què s'automatitza bé i què s'automatitza malament
- Crontab d'usuari i crontab del sistema
- Els cinc camps
- El conflicte entre dia del mes i dia de la setmana
- Fallada clàssica 1: el PATH de cron
- Fallada clàssica 2: la sortida que ningú llegeix
- Fallada clàssica 3: la zona horària
- Depurar una tasca de cron
- Solapament i
flock anacroni els temporitzadors de systemd- Cas Tramontana: la còpia nocturna i la purga
- Què s'automatitza bé i què s'automatitza malament
| Bon candidat | Mal candidat |
|---|---|
| Idempotent: repetir-lo no trenca res | Acumula efectes a cada execució |
| Durada acotada i predictible | Pot durar hores indefinidament |
| Falla de manera visible i registrada | Falla en silenci |
| No necessita decisions humanes | Requereix criteri cas per cas |
| Els seus recursos estan controlats | Competeix lliurement amb el servei |
La còpia nocturna de Tramontana suspenia a les dues últimes files: no limitava la seva prioritat d'E/S i ningú no en llegia el resultat. Una tasca automàtica que falla en silenci és pitjor que no tenir-la, perquè genera la confiança que la feina està feta. La primera vegada que descobreixes que les còpies porten tres mesos fallant sol ser el dia que en necessites restaurar una.
- Crontab d'usuari i crontab del sistema
El dimoni cron (paquet cron a Ubuntu) llegeix diversos llocs diferents:
| Ubicació | Camp d'usuari | S'edita amb | Per a què |
|---|---|---|---|
crontab -e de l'usuari |
no | crontab -e |
tasques d'un compte |
/etc/crontab |
sí | editor + sudo |
tasques del sistema |
/etc/cron.d/<fitxer> |
sí | editor + sudo |
tasques de paquets o serveis |
/etc/cron.{hourly,daily,weekly,monthly}/ |
— | scripts executables | tasques periòdiques simples |
operador@srv-tramontana:~$ crontab -l
30 3 * * * tar -czf /srv/tramontana/backups/enviaments/nocturna.tar.gz /opt/tramontanaAquí està la culpable de la incidència d'ahir a la nit.
| Opció | Efecte |
|---|---|
crontab -l |
llistar |
crontab -e |
editar (fa servir $EDITOR, que vas fixar a 03-01) |
crontab -r |
esborrar el crontab sencer, sense preguntar |
crontab fitxer |
reemplaçar el crontab pel contingut d'un fitxer |
crontab -u usuari -l |
veure el d'un altre usuari (requereix root) |
Compte amb crontab -r. No demana confirmació i no hi ha paperera: esborra totes les teves tasques de cop. I és just al costat de -e al teclat. El costum professional és senzill: mantén el teu crontab en un fitxer versionat i carrega'l amb crontab fitxer. Així una pulsació desafortunada costa un crontab ~/cron/operador.cron, no una reconstrucció de memòria.
La diferència clau entre els dos formats és que les línies de /etc/crontab i de /etc/cron.d/ porten un camp extra amb l'usuari que executa la tasca, just abans de l'ordre:
Oblidar aquest camp és un error freqüent: cron interpreta el nom d'usuari com el primer argument de l'ordre i la tasca falla d'una manera desconcertant.
Els directoris cron.daily i companyia els executa run-parts, que té una peculiaritat: ignora els fitxers el nom dels quals contingui un punt. Un script anomenat copia.sh a /etc/cron.daily/ no s'executarà mai. S'ha de dir copia, sense extensió, i ser executable.
- Els cinc camps
┌───── minut (0-59) │ ┌─── hora (0-23) │ │ ┌─ dia del mes (1-31) │ │ │ ┌───── mes (1-12 o jan-dec) │ │ │ │ ┌─── dia set (0-7, on 0 i 7 són diumenge, o sun-sat) │ │ │ │ │ * * * * * ordre
| Sintaxi | Significa |
|---|---|
* |
qualsevol valor |
5 |
aquell valor exacte |
1,15,30 |
llista |
9-17 |
rang |
*/5 |
cada 5 unitats des de 0 |
0-30/10 |
cada 10, dins del rang |
| Expressió | Quan s'executa |
|---|---|
* * * * * |
cada minut |
*/15 * * * * |
als minuts 0, 15, 30 i 45 |
30 4 * * * |
cada dia a les 04:30 |
0 9-18 * * 1-5 |
en punt, de 9 a 18, de dilluns a divendres |
0 4 1 * * |
el dia 1 de cada mes a les 04:00 |
15 2 * * 6 |
els dissabtes a les 02:15 |
0 0 1 1,7 * |
l'1 de gener i l'1 de juliol |
*/10 2-4 * * * |
cada 10 minuts, entre les 2 i les 4 |
5 0 * * * |
a les 00:05 (no a les 00:00: evita el minut de màxima concurrència) |
Aquesta última fila és un consell real. A les 00:00 en punt arrenca tot el que algú va programar sense pensar; desplaçar-ho cinc minuts evita competir-hi.
Dreceres que substitueixen els cinc camps:
| Drecera | Equival a |
|---|---|
@reboot |
un cop, en arrencar el sistema |
@hourly |
0 * * * * |
@daily / @midnight |
0 0 * * * |
@weekly |
0 0 * * 0 |
@monthly |
0 0 1 * * |
@yearly |
0 0 1 1 * |
- El conflicte entre dia del mes i dia de la setmana
Aquí hi ha una regla que contradiu la intuïció i que fa que moltes tasques s'executin més vegades de les previstes.
Si els camps «dia del mes» i «dia de la setmana» són tots dos diferents de *, es combinen amb OR, no amb AND. La tasca s'executa si es compleix qualsevol dels dos.
La intenció habitual —«només els divendres 13»— exigeix comprovar-ho dins de l'ordre, perquè cron no la sap expressar:
(Fixa't en el \%: en un crontab, el símbol % té un significat especial que veurem a l'apartat 6.)
Quan un dels dos és *, no hi ha ambigüitat i mana l'altre. La taula resumeix els quatre casos:
| Dia mes | Dia setmana | Resultat |
|---|---|---|
* |
* |
tots els dies |
15 |
* |
només el dia 15 |
* |
1 |
només els dilluns |
15 |
1 |
els dies 15 i a més tots els dilluns |
- Fallada clàssica 1: el PATH de cron
És, amb diferència, la número u. El símptoma sempre és el mateix: l'ordre funciona perfectament quan l'escrius tu i no fa res des de cron.
La causa la coneixes des de 03-01: cron no llança un shell de login ni interactiu, així que no llegeix /etc/profile, ni ~/.profile, ni ~/.bashrc. Res del teu entorn no existeix allà. El PATH que cron proporciona per defecte és:
Dos directoris. No hi ha /usr/local/bin, ni /usr/sbin, ni per descomptat /home/operador/scripts que vas afegir a 03-01. Tampoc existeixen els teus àlies, ni les teves variables, ni la configuració regional que tens definida.
Si rsync estigués instal·lat a /usr/local/bin, una tasca que l'invoqui pel seu nom fallaria cada vegada, en silenci i sense deixar rastre visible.
Les tres solucions, per ordre de preferència:
-
Rutes absolutes sempre. Esbrina-les amb
command -vi escriu-les tal qual.command -v rsync tar findte les dona totes de cop:/usr/bin/rsync,/usr/bin/tar,/usr/bin/find. -
Declarar el PATH a la capçalera del crontab. Les assignacions de variables es posen abans de les tasques i s'apliquen a totes:
- Fer que l'script es carregui l'entorn amb
. ~/.profilecom a primera línia. Funciona, però acobla la tasca a la configuració personal d'un compte, i això és fràgil.
La regla que apliquem a Tramontana és la 1 reforçada amb la 2: rutes absolutes a les ordres i un PATH explícit a la capçalera, per al que l'ordre pugui invocar internament.
- Fallada clàssica 2: la sortida que ningú llegeix
Cron captura stdout i stderr de cada tasca i els envia per correu local a l'usuari propietari. En un servidor sense MTA configurat —com srv-tramontana— aquell correu no arriba enlloc: es descarta o es queda a /var/mail/operador sense que ningú l'obri mai.
Resultat: si no rediriges la sortida, no t'assabentes de res. Ni dels èxits ni, sobretot, de les fallades.
| Redirecció | Què aconsegueixes |
|---|---|
| (res) | correu local que ningú llegeix |
> /dev/null |
silencia la sortida; els errors sí que generen correu |
> /dev/null 2>&1 |
silenci absolut. Evita-ho |
>> /var/log/... 2>&1 |
el correcte: tot queda registrat |
30 4 * * * /usr/bin/rsync -a /home/operador/dades/ /srv/tramontana/backups/enviaments/ >> /var/log/tramontana/cron-copia.log 2>&1
El 2>&1 va al final, pel que vas aprendre a 03-04: primer es redirigeix stdout al fitxer i després es copia aquell destí sobre stderr. A l'inrevés, els errors —que són justament el que t'importa— acabarien al correu fantasma.
Un registre amb data s'aconsegueix anteposant un date:
30 4 * * * { /usr/bin/date '+--- %F %T inici'; /usr/bin/rsync -a /home/operador/dades/ /srv/tramontana/backups/enviaments/; } >> /var/log/tramontana/cron-copia.log 2>&1MAILTO controla el destí del correu: [email protected] l'envia a una adreça real (si hi ha MTA), i MAILTO="" desactiva l'enviament del tot. La combinació professional és MAILTO="" més redirecció a un fitxer de registre, i que sigui un sistema de monitoratge qui vigili aquell fitxer.
I la peculiaritat del %: en un crontab, % s'interpreta com un salt de línia que alimenta l'entrada estàndard de l'ordre. Per això date +%F dins d'un crontab s'ha d'escriure date +\%F. És una font d'errors desproporcionada per al poc habitual que és el detall.
- Fallada clàssica 3: la zona horària
cron fa servir la zona horària del sistema, no la de l'usuari. Comprova-la sempre:
A les zones amb horari d'estiu hi ha dos dies l'any problemàtics. Quan el rellotge s'avança al març, les 02:30 no existeixen: una tasca programada a aquella hora no s'executa aquell dia. Quan s'endarrereix a l'octubre, les 02:30 passen dues vegades, i segons la implementació la tasca es pot executar dues vegades.
Tres maneres de protegir-se:
- Programar fora de la franja 01:00–03:00. És la solució més simple i la que resol el problema de debò.
- Fer servir UTC al servidor (
sudo timedatectl set-timezone UTC), pràctica habitual en servidors, a canvi d'haver de traduir mentalment els horaris. - Declarar
CRON_TZ=UTCa la capçalera del crontab, que fixa la zona només per a aquelles tasques.
Aquí hi ha una coincidència que convé subratllar: la còpia de Tramontana estava a les 03:30, dins de la franja de risc, i a més xocava amb el pic de càrrega. Moure-la resol dos problemes de cop.
- Depurar una tasca de cron
flowchart TD
A["La tasca no fa el que s'espera"] --> B{"S'ha executat?<br/>grep CRON /var/log/syslog"}
B -->|No| C["Revisa la sintaxi dels 5 camps<br/>i que el crontab estigui carregat"]
B -->|Sí| D{"Hi ha registre<br/>al teu fitxer de log?"}
D -->|No| E["Falta la redirecció:<br/>afegeix >> log 2>&1"]
D -->|Sí| F{"Què diu l'error?"}
F -->|"ordre no trobada"| G["PATH: fes servir rutes absolutes"]
F -->|"permís denegat"| H["Usuari equivocat<br/>o permisos del destí"]
F -->|"un altre"| I["Reprodueix amb env -i"]
On es registra. El dimoni anota cada execució al syslog:
operador@srv-tramontana:~$ grep CRON /var/log/syslog | tail -3
Aug 18 03:30:01 srv-tramontana CRON[2210]: (operador) CMD (tar -czf /srv/tramontana/backups/enviaments/nocturna.tar.gz /opt/tramontana)
Aug 18 04:30:01 srv-tramontana CRON[2455]: (operador) CMD (/usr/bin/rsync -a /home/operador/dades/ /srv/tramontana/backups/enviaments/)
Aug 18 04:30:02 srv-tramontana CRON[2455]: (CRON) info (No MTA installed, discarding output)Tres coses: la còpia va arrencar a les 03:30:01, coincidint amb la incidència; l'rsync també va córrer; i el missatge «No MTA installed, discarding output» és cron dient-te literalment que ha tirat la sortida a les escombraries. Aquí hi ha la fallada 2, confessada al mateix registre.
Aquest registre et diu si la tasca s'ha executat, però no si ha funcionat: cron no comprova el codi de sortida. Per a això cal el teu propi fitxer de registre.
Abocar l'entorn de cron. El truc definitiu per a la fallada 1: programa una tasca temporal que guardi el seu entorn i compara'l amb el teu.
operador@srv-tramontana:~$ cat /tmp/entorn-cron.txt
SHELL=/bin/sh
PWD=/home/operador
LOGNAME=operador
PATH=/usr/bin:/bin
HOME=/home/operadorCinc variables. Ni LANG, ni el teu PATH ampliat. Fixa't a més que SHELL és /bin/sh, no bash: les construccions específiques de Bash poden fallar. Si les necessites, declara SHELL=/bin/bash a la capçalera.
Provar l'ordre amb l'entorn de cron, sense esperar que es dispari:
operador@srv-tramontana:~$ env -i SHELL=/bin/sh PATH=/usr/bin:/bin HOME=/home/operador \
/bin/sh -c 'rsync -a /home/operador/dades/ /srv/tramontana/backups/enviaments/'
/bin/sh: 1: rsync: not foundReproduït en dos segons. env -i arrenca l'ordre sense cap variable heretada i li afegeix només les que li indiquis: és una simulació fidel de cron. Qualsevol tasca nova s'hauria de provar així abans de programar-la.
- Solapament i
flock
flockSi una execució dura més que l'interval, cron llança la següent igualment. Dues còpies escrivint al mateix fitxer produeixen un fitxer corromput; dues purgues simultànies poden trepitjar-se mútuament.
flock resol el problema amb un fitxer de bloqueig:
30 4 * * * /usr/bin/flock -n /var/lock/tramontana-copia.lock /usr/bin/tar -czf /srv/tramontana/backups/enviaments/nocturna.tar.gz /opt/tramontana/app/ >> /var/log/tramontana/cron-copia.log 2>&1
| Opció | Comportament si el bloqueig està pres |
|---|---|
-n |
surt immediatament amb codi 1 |
-w 60 |
espera fins a 60 segons i després es rendeix |
| (res) | espera indefinidament |
-n és gairebé sempre l'opció correcta per a una tasca periòdica: si l'anterior continua en marxa, aquesta hi sobra. Sense -n, les execucions es van encuant i acabes amb vint processos esperant.
El bloqueig s'allibera sol quan el procés acaba, fins i tot si mor de cop, perquè el gestiona el nucli a través del descriptor de fitxer. No hi ha fitxers de bloqueig orfes per netejar a mà, que és exactament el problema d'implementar-ho amb un touch i un rm.
anacron i els temporitzadors de systemd
anacron i els temporitzadors de systemdcron suposa que la màquina està encesa a l'hora prevista. Si el servidor estava apagat, la tasca no es recupera. anacron cobreix aquest buit: treballa amb granularitat de dies i, en arrencar, executa el que va quedar pendent. A Ubuntu, cron.daily, cron.weekly i cron.monthly els gestiona anacron precisament per això.
| cron | anacron | temporitzador de systemd | |
|---|---|---|---|
| Granularitat | minuts | dies | segons |
| Recupera el que s'ha perdut | no | sí | sí (Persistent=true) |
| Registre | syslog | syslog | journalctl -u <unitat> |
| Dependències entre tasques | no | no | sí |
| Aleatoritzar l'arrencada | no | sí | RandomizedDelaySec |
| Complexitat | mínima | baixa | alta (dos fitxers per tasca) |
Quan triar cadascun. cron per al que és simple i periòdic en un servidor sempre encès: és universal, cap en una línia i qualsevol administrador l'entén. anacron per a portàtils i màquines que s'apaguen. Els temporitzadors de systemd quan necessites dependències entre unitats, control de recursos, reintents o el registre integrat del sistema; s'estudien a 05-05. Per a la còpia de Tramontana, cron és suficient i més llegible.
- Cas Tramontana: la còpia nocturna i la purga
Refem la tasca culpable aplicant-hi tot l'anterior. El crontab es manté en un fitxer versionat i es carrega des d'allà.
operador@srv-tramontana:~$ crontab -l > ~/cron-operador.bak-$(date +%F)
operador@srv-tramontana:~$ nano ~/cron/operador.cron# Crontab d'operador — Tramontana Reserves SHELL=/bin/bash PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin MAILTO="" CRON_TZ=Europe/Madrid # Còpia diària de dades i del release actiu. 04:20 (fora del pic i del canvi d'hora). 20 4 * * * /usr/bin/flock -n /var/lock/tramontana-copia.lock /usr/bin/ionice -c 3 /usr/bin/tar -czf /srv/tramontana/backups/enviaments/dades-$(/usr/bin/date +\%F).tar.gz /home/operador/dades /opt/tramontana/app/ >> /var/log/tramontana/cron-copia.log 2>&1 # Purga de còpies de més de 30 dies. Diumenges a les 05:10. 10 5 * * 0 /usr/bin/find /srv/tramontana/backups/enviaments -type f -name 'dades-*.tar.gz' -mtime +30 -delete >> /var/log/tramontana/cron-purga.log 2>&1
Es carrega amb crontab ~/cron/operador.cron i es comprova amb crontab -l. Repassa cada decisió, perquè cadascuna corregeix un problema concret:
- 04:20 en comptes de 03:30: fora del pic d'errors que vas identificar a 03-05 i fora de la franja del canvi d'hora.
flock -n: si una còpia anterior continua en marxa, aquesta no arrenca.ionice -c 3: la còpia només fa servir el disc quan el servei no el necessita. És la correcció directa de la incidència de 03-06./opt/tramontana/app/amb barra final en comptes de/opt/tramontanasencer:appés l'enllaç simbòlic al release actiu, i la barra fa quetarsegueixi l'enllaç. Es copia un release en comptes de quatre, i sempre el que està servint.- Nom amb data:
dades-2026-08-18.tar.gz, amb\%Fescapat. Cada dia el seu fitxer, en comptes de sobreescriure l'única còpia que tenies. >> ... 2>&1a totes dues tasques: tot queda registrat, amb el2>&1al final.- Rutes absolutes a totes les ordres, inclòs el
datede dins de la substitució. - La purga en tasca a part i amb
find -mtime +30: saps de 03-03 que això significa 31 dies o més, marge de sobres per a una retenció mensual.
Verificació abans d'anar cap a casa: es prova l'ordre amb l'entorn de cron i es comprova el resultat.
operador@srv-tramontana:~$ env -i SHELL=/bin/bash PATH=/usr/bin:/bin HOME=/home/operador /bin/bash -c \
'/usr/bin/flock -n /var/lock/tramontana-copia.lock /usr/bin/ionice -c 3 /usr/bin/tar -czf /tmp/prova.tar.gz /home/operador/dades /opt/tramontana/app/'
operador@srv-tramontana:~$ echo $?; ls -lh /tmp/prova.tar.gz
0
-rw-r----- 1 operador operador 47M Aug 18 13:40 /tmp/prova.tar.gz
operador@srv-tramontana:~$ tar -tzvf /tmp/prova.tar.gz | head -2
drwxr-x--- operador/tramontana 0 2026-08-18 09:14 home/operador/dades/
-rw-r----- operador/tramontana 1284 2026-08-14 11:02 home/operador/dades/reserves.csvCodi 0, 47 MB —un release, no quatre— i tar -tzvf confirma que el contingut és l'esperat abans de donar la tasca per bona. És la convenció del curs aplicada aquí: mirar dins del fitxer abans de confiar-hi.
Informe per a la Marta. La còpia nocturna s'ha reprogramat a les 04:20, amb la prioritat de disc més baixa i limitada al release en servei en comptes dels quatre. Això protegeix que la còpia torni a deixar l'aplicació sense disc, que dues còpies se solapin i la pèrdua de la còpia anterior en generar-se la nova. No protegeix davant d'una fallada de la còpia: encara ningú no vigila /var/log/tramontana/cron-copia.log, de manera que un error continuaria passant desapercebut, ni tampoc davant de la pèrdua del servidor sencer, perquè les còpies continuen al mateix disc. Totes dues coses requereixen decisions que excedeixen l'ajust tècnic i s'aborden al mòdul d'administració.
Errors Comuns i Consells
crontab -ren comptes de-e. Esborra tot sense preguntar. Mantén el crontab en un fitxer i carrega'l ambcrontab fitxer.- Oblidar el camp d'usuari a
/etc/cron.d/. Cron el pren com a argument de l'ordre. - Posar una extensió a un script de
/etc/cron.daily/.run-partsignora els noms amb punt. - Suposar que existeix el teu PATH. Cron dona
/usr/bin:/bini res més. Rutes absolutes. %sense escapar. Dins d'un crontab,%és un salt de línia. Escriu\%.- No redirigir la sortida. Sense
>> log 2>&1les fallades desapareixen. - Posar
2>&1abans de la redirecció de sortida. Va al final, sempre. - Programar entre les 02:00 i les 03:00. És la franja del canvi d'hora.
* * * * *de prova i oblidar-se de treure'l. Deixa una tasca corrent cada minut per sempre.- Consell: documenta cada tasca amb un comentari que digui què fa i per què a aquella hora. D'aquí a un any ho agrairàs tu, no un altre.
- Consell: fes que la tasca escrigui una marca d'èxit amb data. Comprovar «l'última línia del registre és d'avui?» és una revisió trivial i detecta el 90 % dels problemes.
Exercicis
Exercici 1. Escriu les expressions de cron per a: cada 20 minuts entre les 8 i les 20 els dies laborables; l'últim dia de cada mes a les 23:50; i a les 06:15 els dies 1 i 15. Justifica el segon cas, que té truc.
Exercici 2. Programa una tasca que registri cada hora el nombre d'errors 500 d'errors.log a /var/log/tramontana/errors-500.log juntament amb la data. Aplica les tres proteccions contra les fallades clàssiques i demostra que funcionaria a l'entorn de cron abans d'instal·lar-la.
Exercici 3. Una tasca programada */5 * * * * /home/operador/scripts/sincronitzar >> /tmp/sync.log 2>&1 no produeix cap línia al seu registre, encara que l'ordre funciona quan l'executes tu. Descriu el procediment complet de diagnòstic, en ordre, indicant què comprovaries a cada pas i què conclouries de cada resultat.
Solucions
Solució 1.
*/20 8-20 * * 1-5 # cada 20 min, de 8 a 20, de dilluns a divendres 15 6 1,15 * * # a les 06:15 els dies 1 i 15
El segon, «l'últim dia de cada mes», no es pot expressar amb els cinc camps: cron no sap quants dies té el mes, i 31 es saltaria febrer, abril, juny, setembre i novembre. La solució idiomàtica és programar-ho cada dia i deixar que l'ordre decideixi:
Es pregunta quin dia serà demà: si és dia 1, avui és l'últim del mes, sigui quina sigui la seva llargada i encara que l'any sigui de traspàs. És un bon exemple de la frontera de cron: quan la condició no cap en els cinc camps, s'executa diàriament i es comprova a dins. El \% va escapat, com sempre.
Solució 2. Primer es prova l'ordre a l'entorn de cron:
operador@srv-tramontana:~$ env -i PATH=/usr/bin:/bin HOME=/home/operador /bin/sh -c \
'echo "$(/usr/bin/date +%F\ %T) $(/usr/bin/grep -c "ERROR 500" /var/log/tramontana/errors.log)"'
2026-08-18 13:52 41Funciona amb només /usr/bin:/bin al PATH, per tant no depenem de res que cron no tingui. Ara la línia de crontab:
0 * * * * /usr/bin/flock -n /var/lock/errors-500.lock /bin/sh -c 'echo "$(/usr/bin/date +\%F\ \%T) $(/usr/bin/grep -c \"ERROR 500\" /var/log/tramontana/errors.log)"' >> /var/log/tramontana/errors-500.log 2>&1
Les tres proteccions: rutes absolutes per a date i grep, de manera que el PATH mínim no importi; >> ... 2>&1 perquè tant el resultat com qualsevol error quedin al fitxer i no a un correu que ningú llegeix; i CRON_TZ declarat a la capçalera del crontab —juntament amb l'elecció del minut 0 de cada hora, lluny de la franja del canvi horari— perquè les marques de temps siguin coherents. S'hi afegeix flock perquè és un costum barat, encara que aquí el risc de solapament sigui mínim. I els % van escapats: sense les barres, cron tallaria l'ordre al primer % i li passaria la resta com a entrada estàndard, que és una fallada especialment difícil de reconèixer.
Una línia que comença a acumular escapades com aquesta és el senyal que el contingut demana un script propi. Això és el que resoldrà el Mòdul 4.
Solució 3. El procediment, en ordre, del més extern al més intern:
- Existeix la tasca?
crontab -l | grep sincronitzar. Si no apareix, es va editar un altre crontab —el deroot, per exemple— o uncrontab -rse la va endur. - S'està executant?
grep CRON /var/log/syslog | grep sincronitzar | tail -3. Si no hi ha entrades, cron no la llança: revisa la sintaxi dels camps i que el dimoni estigui actiu. Si n'hi ha, cron la llança i el problema és més endins. - Existeix el fitxer de registre i amb quins permisos?
ls -l /tmp/sync.log. Un registre buit però existent confirma que la redirecció funciona i que l'ordre no escriu res; que el fitxer no existeixi apunta que l'ordre ni tan sols va arribar a arrencar. - És executable i amb la ruta correcta?
ls -l /home/operador/scripts/sincronitzar. Sense el bitx, cron obté «permission denied». I aquí hi ha el sospitós principal: la tasca fa servir una ruta absoluta a l'script, però l'script per dins probablement invoca ordres pel seu nom, i aquestes sí que depenen del PATH. - Reproduir amb l'entorn de cron:
env -i PATH=/usr/bin:/bin HOME=/home/operador /bin/sh /home/operador/scripts/sincronitzar. Aquest pas gairebé sempre reprodueix la fallada a l'instant. - Verificar l'escriptura sobre el destí amb
sudo -u operador touchal directori de destí, per si la tasca corre amb un usuari diferent del que et penses.
La conclusió més probable és la del pas 5. I hi ha una pista que hi apunta des del principi: si el registre està buit en comptes de contenir un missatge d'error, l'ordre no va arribar a produir sortida, cosa que encaixa amb un shell que ni tan sols va poder arrencar el binari. Un registre buit és informació, no absència d'informació.
Conclusió
Has convertit una tasca automàtica perillosa en una tasca automàtica defensable.
- Saps què s'automatitza bé: el que és idempotent, acotat, amb recursos controlats i amb fallada visible. I distingeixes el crontab d'usuari del crontab del sistema, amb el seu camp extra d'usuari, i coneixes
run-partsi la seva mania amb els punts als noms. - Domines els cinc camps amb llistes, rangs, passos i dreceres, i saps que dia del mes i dia de la setmana es combinen amb OR, no amb AND.
- Tens resoltes les tres fallades clàssiques: el PATH mínim de cron —rutes absolutes sempre—, la sortida que ningú llegeix —
>> log 2>&1amb el2>&1al final— i la zona horària amb la seva franja de risc entre les 02:00 i les 03:00. - Depures una tasca amb mètode:
grep CRON /var/log/syslogper saber si s'ha executat, el teu propi registre per saber si ha funcionat, l'abocament de l'entorn ambenvi la reproducció exacta ambenv -i. - Evites el solapament amb
flock -n, sabent que el bloqueig l'allibera el nucli i no deixa restes. - Coneixes
anacronper a màquines que s'apaguen i saps quan un temporitzador de systemd compensa la seva complexitat. - I has reprogramat la còpia de Tramontana amb hora nova, bloqueig, prioritat d'E/S, abast reduït al release actiu, nom amb data i registre, amb la purga en tasca a part i un informe honest sobre el que la mesura no cobreix.
Queda un front sense tocar. Tot el que has fet fins ara passa dins de srv-tramontana, i un servidor només existeix per a qui hi pugui arribar. L'última lliçó del mòdul, Comandes de Xarxa, et dona les eines per mirar cap enfora: ip per llegir la configuració real de la màquina, ping, traceroute i mtr per al camí, dig i /etc/hosts per a la resolució de noms, ss per saber quins ports escolten i qui els ocupa, i curl per comprovar si el servei respon de debò. Tot plegat ordenat en una metodologia de diagnòstic per capes que aplicaràs al cas que t'espera: la Marta avisa que el web de reserves «no carrega», i cal esbrinar exactament on és el tall.
Curs de Linux: De Principiant a Administrador de Sistemes
Mòdul 1: Introducció a Linux
- Què és Linux?
- Història de Linux
- Distribucions de Linux
- Instal·lant Linux
- Primer Contacte amb el Sistema
- Estructura del Sistema de Fitxers de Linux
Mòdul 2: Comandes Bàsiques de Linux
- Introducció a la Línia de Comandes
- Obtenir Ajuda i Documentació del Sistema
- Navegant pel Sistema de Fitxers
- Operacions amb Fitxers i Directoris
- Visualització i Edició de Fitxers
- Enllaços Durs i Simbòlics
- Permisos i Propietat dels Fitxers
Mòdul 3: Habilitats Avançades en la Línia de Comandes
- L'Entorn del Shell: Variables, Àlies i Historial
- Ús de Comodins i Expressions Regulars
- Cerca de Fitxers i Contingut: find, locate i grep
- Canonades i Redirecció
- Processament de Text: cut, sort, uniq, sed i awk
- Gestió de Processos
- Programació de Tasques amb Cron
- Comandes de Xarxa
Mòdul 4: Scripting en Shell
- Introducció al Scripting en Shell
- Variables i Tipus de Dades
- Entrada, Sortida i Arguments d'un Script
- Estructures de Control
- Funcions i Biblioteques
- Depuració i Gestió d'Errors
- Scripts de Producció: Bones Pràctiques
Mòdul 5: Administració del Sistema
- Gestió d'Usuaris i Grups
- sudo i Permisos Especials
- Gestió de Paquets
- Gestió de Discs
- systemd i la Gestió de Serveis
- Registres del Sistema: journald i syslog
- Monitoratge del Sistema i Optimització del Rendiment
- Còpies de Seguretat i Restauració
Mòdul 6: Xarxes i Seguretat
- Configuració de Xarxes
- SSH i Accés Remot
- Tallafocs i Seguretat Perimetral
- Sistemes de Detecció d'Intrusions
- Gestió de Secrets i Certificats TLS
- Assegurant Sistemes Linux
Mòdul 7: Temes Avançats
- El Procés d'Arrencada i la Recuperació del Sistema
- Diagnòstic Avançat: strace, perf i eBPF
- Optimització del Nucli de Linux
- Virtualització amb Linux
- Contenidors de Linux i Docker
- Automatització amb Ansible
- Alta Disponibilitat i Balanceig de Càrrega
