Un prompt rosso in produzione
La maggior parte degli errori di server sbagliato nasce dal fatto che due terminali sembrano uguali. Il prompt è ciò che leggi un attimo prima di premere Invio, quindi cambialo lì. Aggiungi questo in fondo a ~/.bashrc sul server. Deve andare in fondo, perché il .bashrc della distribuzione imposta PS1 prima e lo sovrascriverebbe:
PS1='\[\e[1;37;41m\] PRODUCTION \[\e[0m\] \u@\h:\w\$ '
Mostra PRODUCTION bianco su rosso, poi il solito utente, host e cartella. \[ e \] dicono a bash che i codici colore non occupano spazio, così i comandi lunghi vanno a capo correttamente.
Aggiungi la stessa riga a /root/.bashrc: nella nostra prova sudo -i mostrava l'etichetta rossa solo perché c'era anche in quel file. Per lo staging usa il giallo con \e[1;30;43m. Funziona solo con bash interattivo, quindi le altre shell richiedono una loro impostazione.


Colora la barra di tmux e il terminale
Se usi tmux sul server, colora la sua barra di stato, in ~/.tmux.conf lì:
set -g status-style bg=red,fg=white,bold
set -g status-left " PRODUCTION "
Controlla che sia stato caricato con tmux show -g status-style.
Sul tuo computer, la maggior parte delle app di terminale può aprire un host in un profilo separato. Dai alla produzione una finestra con lo sfondo rosso scuro. Puoi anche far impostare il colore alla tua configurazione SSH, nei terminali che supportano la sequenza OSC 11:
Host prod-*
PermitLocalCommand yes
LocalCommand printf '\033]11;#400000\007'
Il colore non torna da solo com'era quando esci, e il supporto varia, quindi provalo prima nel tuo terminale.
Con molti server, nomi chiari e gruppi aiutano quanto i colori: vedi come gestire molti server SSH.
Cancellare i file in sicurezza
rm di GNU rifiuta già il caso peggiore:
$ rm -rf /
rm: it is dangerous to operate recursively on '/'
rm: use --no-preserve-root to override this failsafe
Protegge solo il / letterale. In rm -rf /* la shell espande prima l'asterisco, quindi rm riceve /bin, /etc e il resto, e il controllo non si applica. Uno spazio di troppo in rm -rf /var/app /* lo fa per sbaglio. Queste abitudini aiutano di più:
- Guarda prima di cancellare. Metti
echodavanti per vedere in cosa si espande un glob:echo rm -rf /tmp/app/*. Poi togli l'echo. - Unisci con
&&, non con;. Concd /var/app/tmp && rm -rf ./*, uncdfallito si ferma lì. Con;la cancellazione parte in qualunque cartella ti trovi. - Proteggi le variabili negli script.
rm -rf "${DIR:?}/"si ferma con un errore quandoDIRè vuota, mentre un semplice"$DIR/"diventerebbe/. Ancheset -uall'inizio di uno script si ferma sulle variabili non impostate. - Prima sposta, poi cancella.
mvin una cartella di parcheggio si può annullare.rmno. - Usa
rm -I. Chiede una volta prima di rimuovere più di tre file o di rimuovere in modo ricorsivo. Non rispondere nulla non rimuove nulla, come nella nostra prova. - Usa
--preserve-root=all. Rifiuta anche una cartella su un filesystem diverso da quello del genitore, quindi rifiuterebbe un disco montato:rm: skipping '/dev/shm', since it's on a different device.
Gli ultimi due possono andare in un alias sul server, alias rm='rm -I --preserve-root=all'. Gli alias valgono solo per le shell interattive, non per gli script né per sudo rm, e questi flag esistono solo in GNU.
Prima un dry run
| Comando | Anteprima |
|---|---|
| rsync | rsync -an --delete --itemize-changes src/ dst/ |
| find | find . -name '*.tmp' -print prima, poi sostituisci -print con -delete |
| git clean | git clean -n |
| apt-get | apt-get -s remove package |
Con SQL, esegui prima BEGIN;, poi l'istruzione, controlla il numero di righe e chiudi con COMMIT; o ROLLBACK;. Questo non copre le istruzioni che il database conferma da solo. MySQL lo fa con le modifiche alle tabelle, per esempio.
Incollare più righe
In un terminale un'interruzione di riga nel testo incollato agisce come Invio, quindi un incolla può eseguire comandi prima che tu li legga. Il bracketed paste risolve il problema. Il terminale marca il testo incollato e la shell lo inserisce senza eseguire nulla. Abbiamo incollato due righe echo in bash tramite tmux:
- Con l'opzione attiva, entrambe le righe sono rimaste al prompt e non è stato eseguito nulla fino a Invio.
- Con l'opzione disattivata, la prima riga è stata eseguita appena incollata.
Nelle versioni attuali di bash è attivo per impostazione predefinita. Controlla con questo comando in una shell interattiva:
bind -v | grep bracketed-paste
Se dice off, aggiungi set enable-bracketed-paste on a ~/.inputrc. Aiuta solo dove il programma lo richiede. Incollare in un programma che non lo fa, o in una vecchia shell, esegue comunque riga per riga.
Cosa non possono fare
Il colore del prompt aiuta solo se lo guardi. Non protegge uno script, un job cron o un comando eseguito con ssh server 'command', che non mostra mai un prompt. Gli alias si possono aggirare e niente di tutto questo ferma un errore negli argomenti di un comando che volevi davvero eseguire.
Quindi mantieni le protezioni più grandi: backup collaudati, account e chiavi separati per la produzione e il minimo sudo che serve a ciascuno. Vedi sudo via SSH per regole mirate.
Domande
Come rendo rosso il prompt di bash su un server di produzione?
Imposta PS1 con un codice colore a sfondo rosso in fondo a ~/.bashrc su quel server, e in /root/.bashrc per sudo -i. Va in fondo, così il PS1 della distribuzione non lo sovrascrive.
rm -rf / funziona ancora su Linux?
rm di GNU rifiuta la / letterale, a meno di aggiungere --no-preserve-root. Non protegge rm -rf /*, perché la shell espande prima l'asterisco in tutte le cartelle principali.
Come vedo cosa cancellerà un comando prima di eseguirlo?
Metti echo davanti per vedere in cosa si espande un glob, oppure usa l'opzione di prova: rsync -n, git clean -n, o find con -print prima di -delete.
Fonti
- Manuale GNU coreutils: rm e il trattamento speciale di /
- Manuale di Bash: sintassi del file di init di Readline
- tmux(1), manuale OpenBSD
- ssh_config(5), manuale OpenBSD