Vas tancar el Mòdul 2 amb criteri per decidir qui accedeix a què. Comences el Mòdul 3 amb una cosa més íntima: el lloc on treballes. Cada vegada que obres una sessió a srv-tramontana, Bash construeix al teu voltant un entorn —un conjunt de variables, dreceres, rutes de cerca i memòria del que ja has fet— que determina com es comporten totes les ordres que executis després. Fins ara l'has fet servir tal com venia de fàbrica. A partir d'aquí l'entens i el modeles.
No és un caprici estètic. El 90 % dels «però si a mi em funcionava» d'un administrador de sistemes —l'script que va des del teu terminal i falla a cron, el sort que ordena diferent al teu portàtil i al servidor, l'ordre que existeix per a operador però no per a root— són problemes d'entorn. Entendre què s'hereta, què no i des de quin fitxer es carrega cada cosa és el que separa depurar en cinc minuts de perdre una tarda.
Contingut
- Què és l'entorn d'un procés
- Variables de shell i variables d'entorn
- L'herència cap als processos fills
PATH: com troba Bash un executable- Les altres variables que importen
- Expansió de variables i cometes, amb precisió
- Substitució d'ordres
- Àlies
- Shells de login, interactius i no interactius
- Personalitzar l'indicador
PS1 - Historial persistent i el seu risc de seguretat
- El
~/.bashrcrecomanat per aoperador
- Què és l'entorn d'un procés
Quan el nucli arrenca un procés, li lliura tres coses: els arguments de la línia d'ordres, els descriptors de fitxer oberts (que veuràs a 03-04) i un vector de cadenes CLAU=valor anomenat entorn. No és màgia de Bash: és una estructura del sistema operatiu, disponible per a qualsevol programa escrit en qualsevol llenguatge.
Com que a Linux tot és un fitxer, el pots veure directament:
operador@srv-tramontana:~$ tr '\0' '\n' < /proc/$$/environ | head -6
SHELL=/bin/bash
PWD=/home/operador
LOGNAME=operador
HOME=/home/operador
LANG=ca_ES.UTF-8
USER=operador$$ és el PID del shell actual. El fitxer environ guarda les variables separades per bytes nuls, per això cal tr per llegir-les. L'important: aquest contingut es va fixar quan el procés va arrencar. És una fotografia, no un enllaç viu.
- Variables de shell i variables d'entorn
Bash gestiona dos conjunts que s'assemblen i no són el mateix.
| Variable de shell | Variable d'entorn | |
|---|---|---|
| Es crea amb | VAR=valor |
export VAR=valor |
| La veu el shell actual | Sí | Sí |
| La veuen els processos fills | No | Sí |
| Es llista amb | set |
env o printenv |
| Ús típic | treball temporal a la sessió | configurar programes |
L'assignació té una regla que provoca errors el primer dia: no hi pot haver espais al voltant del =.
operador@srv-tramontana:~$ RELEASE=3.2.1
operador@srv-tramontana:~$ RELEASE = 3.2.1
RELEASE: command not foundAmb espais, Bash interpreta RELEASE com una ordre, i = i 3.2.1 com els seus arguments. Si el valor porta espais, cal posar-lo entre cometes: MISSATGE="desplegament ok".
Per promoure una variable ja existent a variable d'entorn n'hi ha prou amb export RELEASE. Per eliminar qualsevol de les dues, unset RELEASE.
Veure'n una en concret:
printenv VARIABLE imprimeix el seu valor i retorna 1 si la variable no és a l'entorn, encara que existeixi com a variable de shell. És la manera més ràpida de comprovar si et falta un export.
- L'herència cap als processos fills
Aquest és el concepte que cal deixar tancat, perquè explica una família sencera d'errors. L'herència és unidireccional i en el moment de l'arrencada: el fill rep una còpia de l'entorn del pare, i res del que faci el fill no torna al pare.
operador@srv-tramontana:~$ export ENTORN=produccio
operador@srv-tramontana:~$ bash -c 'echo "el fill veu: $ENTORN"; ENTORN=proves'
el fill veu: produccio
operador@srv-tramontana:~$ echo "el pare continua amb: $ENTORN"
el pare continua amb: produccioEl fill va canviar la seva còpia i va morir amb ella. Per això un script no pot canviar el directori de treball del teu terminal, ni definir-te una variable, tret que l'executis amb source (o el seu sinònim .), que no crea un procés fill: llegeix el fitxer al shell actual.
operador@srv-tramontana:~$ echo 'VERSIO_APP=3.2.1' > /tmp/vars.sh
operador@srv-tramontana:~$ bash /tmp/vars.sh; echo "[$VERSIO_APP]" # fill: es perd
[]
operador@srv-tramontana:~$ source /tmp/vars.sh; echo "[$VERSIO_APP]" # shell actual
[3.2.1]Els parèntesis creen un subshell, que és un fill més i es comporta igual: ( cd /opt/tramontana/app && pwd ) imprimeix /opt/tramontana/app i et deixa on eres. Aquest patró és útil de debò: et desplaces, fas alguna cosa i tornes sol, sense arriscar-te a oblidar un cd -.
PATH: com troba Bash un executable
PATH: com troba Bash un executableAl Mòdul 2 va quedar com a noció. Ara en detall. PATH és una llista de directoris separats per :, i Bash la recorre d'esquerra a dreta, aturant-se a la primera coincidència.
operador@srv-tramontana:~$ echo "$PATH"
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
operador@srv-tramontana:~$ type -a python3
python3 is /usr/bin/python3type -a mostra totes les coincidències en ordre; si hi hagués dues versions instal·lades, veuries quina guanya. A més, Bash guarda a la memòria cau les rutes resoltes: si instal·les un binari que n'emmascara un altre i continua executant-se l'antic, hash -r neteja aquesta memòria cau.
Per afegir /home/operador/scripts, la manera correcta és anteposar o afegir sense destruir el que ja hi havia:
Fixa't en dos detalls. Primer, es reutilitza $PATH dins del valor nou; escriure PATH=/home/operador/scripts a seques deixa el sistema sense ls ni sudo fins que tanquis la sessió. Segon, va entre cometes.
Posant-lo al davant, els teus scripts tenen prioritat sobre els del sistema, cosa que permet sobreescriure una ordre a propòsit; posant-lo al darrere (PATH="$PATH:$HOME/scripts") el sistema guanya sempre, que és més conservador. A Tramontana fem servir el segon ordre per als comptes administratius.
Per què mai no es posa . al PATH
Incloure el directori actual sembla còmode i és un forat de seguretat clàssic. Imagina que . és el primer i que en Luis, depurant, deixa a /srv/tramontana/backups/temporals/ un fitxer anomenat ls amb contingut maliciós. Hi entres a mirar, escrius ls, i en comptes de l'ordre del sistema executes el fitxer d'aquell directori amb els teus privilegis. Amb sudo pel mig, és una escalada de privilegis completa.
La regla és absoluta: . no va al PATH, ni al principi ni al final. Per executar alguna cosa del directori actual s'escriu ./programa, explícitament. Aquests dos caràcters són la diferència entre una decisió conscient i un accident.
- Les altres variables que importen
| Variable | Què conté | Nota pràctica |
|---|---|---|
HOME |
/home/operador |
És el que expandeix ~ i on va cd sense arguments |
USER / LOGNAME |
operador |
Informatives; per a la identitat real fes servir id -un |
SHELL |
/bin/bash |
És el teu shell de login, no necessàriament el que corre ara |
PWD / OLDPWD |
directori actual i anterior | cd - fa servir OLDPWD |
LANG / LC_ALL |
idioma i configuració regional | Afecta els missatges, l'ordre i el format de les dates |
EDITOR / VISUAL |
editor per defecte | El fan servir crontab -e, git, visudo |
TERM |
tipus de terminal | xterm-256color en local, vt100 en consoles antigues |
PS1 |
cadena de l'indicador | La personalitzem a l'apartat 10 |
La configuració regional mereix un paràgraf propi perquè produeix diferències silencioses entre màquines:
operador@srv-tramontana:~$ printf 'casa\nCasa\ncal-ferrer\nCan-Ventos\n' | sort | tr '\n' ' '
cal-ferrer Can-Ventos casa Casa
operador@srv-tramontana:~$ printf 'casa\nCasa\ncal-ferrer\nCan-Ventos\n' | LC_ALL=C sort | tr '\n' ' '
Can-Ventos Casa cal-ferrer casaAmb ca_ES.UTF-8, sort ignora majúscules i guionets i ordena «com un diccionari». Amb LC_ALL=C ordena per valor de byte, i totes les majúscules van abans que les minúscules. Quan l'ordre ha de ser reproduïble —comparar dos llistats, generar una suma de verificació— fixa LC_ALL=C. Fixa't també que l'assignació va davant de l'ordre, sense export: això defineix la variable només per a aquella execució, sense tocar la teva sessió. És la manera més neta de provar coses.
LC_ALL trepitja totes les altres LC_* i LANG; per això és la que es fa servir per forçar. El mateix efecte apareix a les dates: date et donarà «dl. 18 d'ago» o «Mon Aug 18» segons la configuració regional, i si un script retalla aquesta sortida per posició, es trenca en canviar de màquina.
- Expansió de variables i cometes, amb precisió
El Mòdul 2 va donar les cometes per sobre. Aquí va la regla exacta, que és de les tres o quatre coses més rendibles de tot el curs.
| Forma | S'expandeixen variables | Es fa globbing | Es parteix per espais |
|---|---|---|---|
$VAR (sense cometes) |
Sí | Sí, sobre el resultat | Sí |
"$VAR" |
Sí | No | No |
'$VAR' |
No | No | No |
La diferència entre les dues primeres files trenca scripts cada dia:
operador@srv-tramontana:~$ RUTA="/home/operador/dades/informe agost.txt"
operador@srv-tramontana:~$ touch "$RUTA"
operador@srv-tramontana:~$ ls -l $RUTA
ls: cannot access '/home/operador/dades/informe': No such file or directory
ls: cannot access 'agost.txt': No such file or directory
operador@srv-tramontana:~$ ls -l "$RUTA"
-rw-r----- 1 operador operador 0 Aug 18 10:12 '/home/operador/dades/informe agost.txt'Sense cometes, Bash parteix el valor per l'espai i ls rep dos arguments. La regla d'or: posa sempre "$VAR" entre cometes, tret que vulguis deliberadament que es parteixi en paraules.
Les claus ${VAR} delimiten el nom quan el que ve a continuació es podria confondre amb una part seva. Amb V=3.2.1, echo "release-$V_final" imprimeix release- —Bash busca una variable V_final, que no existeix— mentre que echo "release-${V}_final" imprimeix release-3.2.1_final.
Dues expansions amb valor per defecte que faràs servir constantment:
operador@srv-tramontana:~$ echo "Destí: ${BACKUP_DIR:-/srv/tramontana/backups/temporals}"
Destí: /srv/tramontana/backups/temporals
operador@srv-tramontana:~$ echo "Versió: ${VERSIO:?falta indicar la versió}"
bash: VERSIO: falta indicar la versió${VAR:-valor}fa servirvalorsiVARés buida o no està definida, sense assignar-la. Ideal per a valors per defecte.${VAR:?missatge}avorta amb aquest missatge si falta. És la forma curta d'exigir un paràmetre obligatori.
També existeix ${VAR:=valor}, que a més assigna, i ${VAR:+valor}, que fa servir valor només si la variable sí que està definida.
- Substitució d'ordres
$(ordre) executa l'ordre i substitueix l'expressió per la seva sortida, traient-ne els salts de línia finals.
operador@srv-tramontana:~$ ACTIU="$(readlink /opt/tramontana/app)"
operador@srv-tramontana:~$ echo "Release actiu: $ACTIU, revisat el $(date +%F)"
Release actiu: releases/3.2.1, revisat el 2026-08-18Ja el feies servir a la convenció de còpies de seguretat cp app.conf app.conf.bak-$(date +%F). Ara saps exactament què hi passa.
Existeix la forma antiga amb accents greus, `ordre`. Fes servir sempre $(...): es pot imbricar sense escapar res i no es confon visualment amb les cometes simples. I posa el resultat entre cometes, "$(...)", per la mateixa raó de l'apartat anterior.
- Àlies
Un àlies és una abreviatura que Bash substitueix al principi d'una ordre, abans d'executar-la.
operador@srv-tramontana:~$ alias ll='ls -lh --group-directories-first'
operador@srv-tramontana:~$ alias logs='cd /var/log/tramontana'
operador@srv-tramontana:~$ alias | head -3
alias ll='ls -lh --group-directories-first'
alias logs='cd /var/log/tramontana'
alias ls='ls --color=auto'S'eliminen amb unalias ll. Per executar l'ordre original saltant-te l'àlies, anteposa una barra invertida:
També serveixen command rm i la ruta absoluta /bin/rm. Això importa perquè els àlies són locals a la teva sessió interactiva: no existeixen en un script, ni a cron, ni quan un altre usuari executa el mateix. Un àlies rm='rm -i' et dona una falsa sensació de xarxa de seguretat que desapareix justament en el context on més mal faries.
Els àlies són per a la teva comoditat, no per automatitzar. Si necessites que alguna cosa es comporti igual sempre i a tot arreu, això és un script, i els scripts són el Mòdul 4. A l'apartat 12 veuràs el joc complet que fem servir a Tramontana.
- Shells de login, interactius i no interactius
Aquí hi ha l'embolic que cal desfer d'una vegada. Bash llegeix fitxers d'arrencada diferents segons com s'ha llançat.
| Tipus | Quan apareix | Què llegeix |
|---|---|---|
| Login interactiu | ssh operador@srv-tramontana, consola TTY, su - |
/etc/profile, després el primer que existeixi de ~/.bash_profile, ~/.bash_login, ~/.profile |
| No login interactiu | obrir una pestanya de terminal, escriure bash |
/etc/bash.bashrc i ~/.bashrc |
| No interactiu | bash script.sh, cron, ssh servidor 'ordre' |
Res de l'anterior (només $BASH_ENV si està definida) |
flowchart TD
S["Arrenca bash"] --> L{"És un shell<br/>de login?"}
L -->|Sí| P["/etc/profile"] --> U["~/.bash_profile<br/>o ~/.bash_login<br/>o ~/.profile<br/>(el primer que existeixi)"]
U --> R["~/.profile sol incloure:<br/>source ~/.bashrc"]
R --> B["~/.bashrc"]
L -->|No| I{"És<br/>interactiu?"}
I -->|Sí| G["/etc/bash.bashrc"] --> B
I -->|No| N["No llegeix cap fitxer<br/>d'arrencada"]
B --> W["Sessió a punt"]
N --> W
W --> X{"Surt un shell<br/>de login?"}
X -->|Sí| O["~/.bash_logout"]
D'aquest diagrama en surten tres conseqüències que resolen gairebé tots els dubtes:
- Les variables d'entorn van a
~/.profile; els àlies, les funcions iPS1van a~/.bashrc. El primer s'hereta per tots els processos de la sessió; el segon només té sentit quan hi ha algú teclejant. - A Ubuntu,
~/.profileacaba amb un bloc que fasource ~/.bashrc. Per això, en connectar-te per SSH, veus els teus àlies: arriben per aquesta cadena, no perquè el shell de login llegeixi.bashrcper si mateix. Si crees un~/.bash_profile,~/.profiledeixa de llegir-se i aquesta cadena es trenca. - Cron no llegeix res d'això, i aquesta és la causa arrel de la fallada clàssica que estudiaràs a 03-07.
Per saber en quin tipus de shell ets: shopt -q login_shell && echo login et diu si és de login, i echo "$-" mostra les opcions actives, on la i indica interactiu. I ~/.bash_logout s'executa en tancar un shell de login: serveix, per exemple, per netejar la pantalla d'un TTY físic amb clear.
- Personalitzar l'indicador
PS1
PS1PS1 és la cadena que Bash imprimeix abans de cada ordre. Admet seqüències d'escapada pròpies:
| Seqüència | Significat |
|---|---|
\u |
nom d'usuari |
\h / \H |
nom curt / complet de l'amfitrió |
\w / \W |
ruta completa (amb ~) / només l'últim directori |
\$ |
# si ets root, $ si no |
\t / \d |
hora HH:MM:SS / data |
\n |
salt de línia |
El color s'afegeix amb seqüències ANSI, i hi ha un detall imprescindible: tot el que no ocupa espai a la pantalla ha d'anar entre \\[ i \\]. Si te'l saltes, Bash calcula malament l'amplada de la línia i l'historial es pinta a sobre de l'indicador en recuperar ordres llargues.
En producció fem servir un altre color a propòsit:
operador@srv-tramontana:~$ PS1='\[\e[1;37;41m\] PROD \[\e[0m\] \u@\h:\w\$ '
PROD operador@srv-tramontana:~$Text blanc sobre fons vermell (41). A Tramontana, l'indicador de srv-tramontana va en vermell i el del portàtil en verd, per una raó molt poc estètica: gairebé tots els esborrats catastròfics comencen executant a la finestra equivocada una ordre pensada per a l'altra. Un avís visual permanent i impossible d'ignorar és més eficaç que qualsevol norma escrita. La mateixa lògica s'aplica quan treballes com a root, on el \$ passa a # tot sol.
- Historial persistent i el seu risc de seguretat
Bash guarda les ordres a la memòria durant la sessió i les aboca a ~/.bash_history en sortir. Aquest comportament per defecte té dos problemes: si obres diversos terminals, l'últim a tancar-se sobreescriu l'historial dels altres, i si la sessió mor de cop, es perd tot.
| Ajust | Què fa |
|---|---|
HISTSIZE=10000 |
ordres guardades a la memòria |
HISTFILESIZE=20000 |
línies conservades al fitxer |
HISTCONTROL=ignoreboth |
ignora duplicats consecutius i línies que comencen per espai |
HISTIGNORE='ls:ll:pwd:exit:history:clear' |
no guarda aquestes ordres trivials |
HISTTIMEFORMAT='%F %T ' |
afegeix data i hora a cada entrada |
shopt -s histappend |
afegeix al fitxer en comptes de sobreescriure'l |
ignoreboth inclou ignorespace, i això habilita un truc pràctic: si escrius una ordre precedida d'un espai, no es guarda. Amb HISTTIMEFORMAT posat, history 3 et mostra les tres últimes entrades amb la seva marca de temps, cosa que converteix l'historial en un registre de què vas fer i quan.
L'advertiment de seguretat
~/.bash_history és un fitxer de text pla. Tot el que escriguis a la línia d'ordres hi acaba, incloses les credencials:
Aquesta contrasenya queda escrita al teu historial, i a més és visible a la taula de processos per a qualsevol usuari del sistema mentre l'ordre corre (ho veuràs amb ps aux a 03-06). Dos problemes, no un.
Què fer en el seu lloc:
- Deixa que l'eina la demani de manera interactiva (
mysql -u tramontana -p, sense enganxar-la). - Guarda-la en un fitxer de credencials amb permisos
600i passa-li la ruta. - Si ja l'has escrita: esborra-la de l'historial en memòria i del fitxer.
operador@srv-tramontana:~$ history -d 512 # esborra l'entrada 512 en memòria
operador@srv-tramontana:~$ history -w # reescriu ~/.bash_historyI comprova els permisos, que han de ser 600. La gestió seriosa de secrets és la lliçó 06-05; aquí queda't amb la higiene mínima.
- El
~/.bashrc recomanat per a operador
~/.bashrc recomanat per a operadorReunint-ho tot, aquest és el bloc que afegim al final de ~/.bashrc als comptes administratius de Tramontana. Aplica la convenció del curs: còpia de seguretat abans d'editar i diff -u després.
operador@srv-tramontana:~$ cp ~/.bashrc ~/.bashrc.bak-$(date +%F)
operador@srv-tramontana:~$ nano ~/.bashrc# --- Ajustos Tramontana ---------------------------------------------
umask 027 # res per a "altres"
HISTSIZE=10000
HISTFILESIZE=20000
HISTCONTROL=ignoreboth
HISTIGNORE='ls:ll:pwd:exit:history:clear'
HISTTIMEFORMAT='%F %T '
shopt -s histappend # no sobreescriure entre terminals
shopt -s checkwinsize cdspell
export EDITOR=nano
export PATH="$PATH:$HOME/scripts" # els nostres scripts, al final
alias ll='ls -lh --group-directories-first'
alias la='ls -lha'
alias grep='grep --color=auto'
alias df='df -h'
alias logs='cd /var/log/tramontana'
alias rel='ls -l /opt/tramontana/releases/'
PS1='\[\e[1;37;41m\] PROD \[\e[0m\] \[\e[1;32m\]\u@\h\[\e[0m\]:\[\e[1;34m\]\w\[\e[0m\]\$ '
# --------------------------------------------------------------------S'activa sense tancar la sessió amb source ~/.bashrc, i es verifica el canvi amb diff -u ~/.bashrc.bak-2026-08-18 ~/.bashrc. Fixa't que umask 027 va aquí i no a ~/.profile perquè ens interessa per al treball interactiu; per als serveis es fixa en un altre lloc, i això és matèria de 05-05.
Errors Comuns i Consells
- Espais al voltant del
=.VAR = valorno és una assignació. És l'error número u. - Editar
~/.bashrci esperar que s'apliqui sol. Cal fersource ~/.bashrco obrir una sessió nova. - Trencar el
PATH. Abans de tocar-lo, guarda'n una còpia:PATH_ORIG="$PATH". Si et quedes sense ordres,export PATH="$PATH_ORIG"et salva sense reconnectar. - Posar variables d'entorn a
~/.bashrc. Funciona en interactiu i desapareix en contextos no interactius. El seu lloc és~/.profile. - Crear
~/.bash_profilesense saber que anul·la~/.profile. Si el crees, inclou-hi a dins[ -f ~/.profile ] && . ~/.profile. - Confiar en
alias rm='rm -i'. No existeix en scripts ni a cron. La xarxa de seguretat de debò és mirar amblsabans de l'rm. - Oblidar
\\[ \\]als colors delPS1. El símptoma és un indicador que es corromp en navegar per l'historial. - Consell:
env -i ordrearrenca un programa sense cap variable. És la millor manera de reproduir el que veu cron, i hi tornaràs a 03-07. I com quesetsense arguments llista variables i funcions, filtra sempre:set | grep '^HIST'.
Exercicis
Exercici 1. Demostra a la teva VM la diferència entre variable de shell i variable d'entorn. Defineix DESPLEGAMENT=3.3.0 sense exportar, comprova que un bash -c fill no la veu, exporta-la, comprova que ara sí, i explica per què printenv donava error abans.
Exercici 2. Afegeix /home/operador/scripts al PATH de manera que no tingui prioritat sobre les ordres del sistema i que el canvi sobrevisqui a reconnectar per SSH. Verifica que funciona sense tancar la sessió i explica en quin fitxer ho has posat i per què.
Exercici 3. Genera una llista ordenada i reproduïble de les cases de /home/operador/dades/cases.txt que sigui idèntica al teu portàtil i al servidor, encara que tinguin configuracions regionals diferents. Guarda el resultat a /home/operador/dades/cases-ordenades.txt i justifica la decisió.
Solucions
Solució 1.
operador@srv-tramontana:~$ DESPLEGAMENT=3.3.0
operador@srv-tramontana:~$ echo "$DESPLEGAMENT"
3.3.0
operador@srv-tramontana:~$ printenv DESPLEGAMENT; echo "codi: $?"
codi: 1
operador@srv-tramontana:~$ bash -c 'echo "el fill veu: [$DESPLEGAMENT]"'
el fill veu: []
operador@srv-tramontana:~$ export DESPLEGAMENT
operador@srv-tramontana:~$ bash -c 'echo "el fill veu: [$DESPLEGAMENT]"'
el fill veu: [3.3.0]La variable existia des del principi al shell actual —per això echo la mostrava—, però no era al vector d'entorn que es copia als fills. printenv consulta exactament aquest vector, així que no la va trobar i va retornar 1. export no crea la variable: la marca per a exportació, i a partir d'aquí tots els fills nous la reben. Els que ja estiguessin corrent, no: l'herència passa en el moment del fork.
Solució 2. Ha d'anar a ~/.profile, perquè és una variable d'entorn i perquè ~/.profile es llegeix als shells de login, que és el que obre SSH. Al final, i no al principi, perquè el sistema tingui prioritat.
operador@srv-tramontana:~$ cp ~/.profile ~/.profile.bak-$(date +%F)
operador@srv-tramontana:~$ printf '\n# scripts propis de Tramontana\nexport PATH="$PATH:$HOME/scripts"\n' >> ~/.profile
operador@srv-tramontana:~$ diff -u ~/.profile.bak-$(date +%F) ~/.profile
@@ -20,3 +20,6 @@
fi
fi
+
+# scripts propis de Tramontana
+export PATH="$PATH:$HOME/scripts"
operador@srv-tramontana:~$ source ~/.profile
operador@srv-tramontana:~$ echo "$PATH" | tr ':' '\n' | tail -2
/usr/games
/home/operador/scriptssource aplica el canvi a la sessió actual sense reconnectar. Si en comptes d'això haguéssim escrit PATH="$HOME/scripts:$PATH", un script nostre anomenat df o tar emmascararia el del sistema, i aquest tipus de sorpresa és difícil de diagnosticar. Posar-lo al final és l'opció conservadora. Fixa't també que les cometes simples del printf impedeixen que $PATH i $HOME s'expandeixin en escriure el fitxer: volem que l'expansió passi a cada login, no ara.
Solució 3.
operador@srv-tramontana:~$ LC_ALL=C sort /home/operador/dades/cases.txt \
> /home/operador/dades/cases-ordenades.txt
operador@srv-tramontana:~$ cat /home/operador/dades/cases-ordenades.txt
cal-ferrer
can-ventos
el-moli
la-solana
mas-figueresLa justificació és la clau de l'exercici: sense LC_ALL=C, el resultat depèn de la configuració regional de cada màquina. Amb ca_ES.UTF-8 el guionet s'ignora en la comparació i mas-figueres podria quedar en una altra posició respecte d'un hipotètic masfigueres; amb C es compara byte a byte i el resultat és idèntic a qualsevol sistema. Quan la sortida s'ha de comparar, versionar o alimentar un altre procés, la reproduïbilitat pesa més que la correcció ortogràfica de l'ordre. I es posa davant de l'ordre, sense export, per no alterar la resta de la sessió.
Conclusió
Has passat d'habitar l'entorn del shell a dissenyar-lo.
- L'entorn és un vector
CLAU=valorque el nucli lliura a cada procés; el llegeixes a/proc/<pid>/environ. - Distingeixes variable de shell de variable d'entorn:
exportmarca la diferència, i l'herència és unidireccional i en el moment de l'arrencada, per això un script no et pot canviar elcdtret que sigui ambsource. - Entens com busca Bash un executable recorrent el
PATHd'esquerra a dreta, com ampliar-lo sense destruir-lo, i per què.mai no va alPATH. - Coneixes l'efecte real de la configuració regional sobre
sorti les dates, i fas servirLC_ALL=Cquan necessites resultats reproduïbles. - Manegues amb precisió
"$VAR"enfront de$VARi'$VAR', les claus${VAR}, els valors per defecte${VAR:-...}i${VAR:?...}, i la substitució d'ordres$(...). - Tens desembolicat l'embolic dels fitxers d'arrencada: entorn a
~/.profile, àlies iPS1a~/.bashrc, i res d'això en un shell no interactiu. - Has posat l'indicador de producció en vermell per una raó operativa i has configurat un historial persistent amb
histappend, sabent que les contrasenyes escrites a la línia acaben en un fitxer de text pla.
La lliçó següent fa el pas natural. Ja saps descriure un fitxer amb la seva ruta; ara aprendràs a descriure conjunts de fitxers i patrons de text. A Ús de Comodins i Expressions Regulars veuràs la distinció que gairebé ningú explica bé —que el globbing el fa el shell abans d'executar l'ordre, mentre que les expressions regulars les interpreta el programa que les rep—, i aquesta distinció, que ara entendràs perquè ja saps com processa Bash una línia abans de llançar-la, és la que evita que grep *.log faci una cosa completament diferent del que esperaves.
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
