Un prompt rojo en producción
La mayoría de los errores de servidor equivocado ocurren porque dos terminales se ven iguales. El prompt es lo que lees justo antes de pulsar Intro, así que cámbialo ahí. Añade esto al final de ~/.bashrc en el servidor. Tiene que ir al final, porque el .bashrc de la distribución define PS1 antes y lo sobrescribiría:
PS1='\[\e[1;37;41m\] PRODUCTION \[\e[0m\] \u@\h:\w\$ '
Esto muestra PRODUCTION en blanco sobre rojo y después el usuario, el host y la carpeta habituales. Los \[ y \] indican a bash que los códigos de color no ocupan ancho, de modo que los comandos largos siguen ajustándose bien.
Añade la misma línea a /root/.bashrc: en nuestra prueba sudo -i mostró la etiqueta roja solo porque ese archivo también la tenía. Para staging, usa amarillo con \e[1;30;43m. Solo funciona en bash interactivo, así que otros shells necesitan su propio ajuste.


Colorea la barra de tmux y la terminal
Si usas tmux en el servidor, colorea su barra de estado, en el ~/.tmux.conf de allí:
set -g status-style bg=red,fg=white,bold
set -g status-left " PRODUCTION "
Comprueba que se cargó con tmux show -g status-style.
En tu propia máquina, la mayoría de las aplicaciones de terminal pueden abrir un host con un perfil aparte. Dale a producción una ventana con fondo rojo oscuro. También puedes dejar que tu configuración de SSH ponga el color, en terminales que admiten la secuencia OSC 11:
Host prod-*
PermitLocalCommand yes
LocalCommand printf '\033]11;#400000\007'
El color no vuelve solo al original al cerrar sesión, y la compatibilidad varía, así que pruébalo primero en tu terminal.
Con muchos servidores, nombres claros y grupos ayudan tanto como los colores: consulta cómo gestionar muchos servidores SSH.
Borrar archivos con seguridad
rm de GNU ya rechaza el peor caso:
$ rm -rf /
rm: it is dangerous to operate recursively on '/'
rm: use --no-preserve-root to override this failsafe
Esto protege solo la / literal. En rm -rf /* el shell expande primero el asterisco, así que rm recibe /bin, /etc y el resto, y la comprobación no se aplica. Un espacio suelto en rm -rf /var/app /* lo provoca por accidente. Estos hábitos ayudan más:
- Mira antes de borrar. Pon
echodelante para ver en qué se expande un glob:echo rm -rf /tmp/app/*. Después quita elecho. - Une con
&&, no con;. Concd /var/app/tmp && rm -rf ./*, si elcdfalla, todo se detiene ahí. Con;el borrado se ejecuta en la carpeta en la que estés. - Protege las variables en los scripts.
rm -rf "${DIR:?}/"se detiene con un error cuandoDIRestá vacía, mientras que un simple"$DIR/"se convertiría en/.set -ual principio de un script también se detiene ante variables sin definir. - Mueve primero, borra después. Un
mva una carpeta de espera se puede deshacer. Unrmno. - Usa
rm -I. Pregunta una vez antes de borrar más de tres archivos o de borrar de forma recursiva. Si no respondes nada, no se borra nada, como en nuestra prueba. - Usa
--preserve-root=all. También rechaza una carpeta que esté en un sistema de archivos distinto del de su padre, así que rechazaría un disco montado:rm: skipping '/dev/shm', since it's on a different device.
Los dos últimos pueden ir en un alias en el servidor, alias rm='rm -I --preserve-root=all'. Los alias se aplican solo a shells interactivos, no a scripts ni a sudo rm, y estas opciones son exclusivas de GNU.
Simulacro primero
| Comando | Vista previa |
|---|---|
| rsync | rsync -an --delete --itemize-changes src/ dst/ |
| find | find . -name '*.tmp' -print primero, y luego cambia -print por -delete |
| git clean | git clean -n |
| apt-get | apt-get -s remove package |
Con SQL, ejecuta primero BEGIN;, luego la sentencia, comprueba el número de filas y termina con COMMIT; o ROLLBACK;. Esto no cubre las sentencias que tu base de datos confirma por sí misma. MySQL lo hace con los cambios de tablas, por ejemplo.
Pegar varias líneas
En una terminal, un salto de línea en el texto pegado actúa como Intro, así que un pegado puede ejecutar comandos antes de que los leas. El bracketed paste lo soluciona. La terminal marca el texto pegado y el shell lo inserta sin ejecutar nada. Pegamos dos líneas echo en bash a través de tmux:
- Con él activado, las dos líneas quedaron en el prompt y no se ejecutó nada hasta pulsar Intro.
- Con él desactivado, la primera línea se ejecutó en cuanto se pegó.
Viene activado por defecto en el bash actual. Compruébalo con este comando en un shell interactivo:
bind -v | grep bracketed-paste
Si dice off, añade set enable-bracketed-paste on a ~/.inputrc. Solo ayuda donde el programa lo solicita. Si pegas en un programa que no lo hace, o en un shell antiguo, se ejecuta línea por línea.
Lo que esto no puede hacer
El color del prompt solo ayuda si lo miras. No protege un script, una tarea de cron ni un comando ejecutado con ssh server 'command', que nunca muestra un prompt. Los alias se pueden esquivar, y nada de esto detiene un error en los argumentos de un comando que querías ejecutar.
Así que mantén las protecciones mayores: copias de seguridad probadas, cuentas y claves separadas para producción, y el mínimo de sudo que necesite cada persona. Consulta sudo por SSH para reglas estrechas.
Preguntas
¿Cómo pongo en rojo el prompt de bash en un servidor de producción?
Define PS1 con un código de color de fondo rojo al final de ~/.bashrc en ese servidor, y en /root/.bashrc para sudo -i. Al final, para que el PS1 de la distribución no lo sobrescriba.
¿Sigue funcionando rm -rf / en Linux?
El rm de GNU rechaza la / literal salvo que añadas --no-preserve-root. No protege rm -rf /*, porque la shell expande antes el asterisco en todas las carpetas de primer nivel.
¿Cómo veo qué borrará un comando antes de ejecutarlo?
Pon echo delante para ver en qué se expande un patrón, o usa la opción de prueba: rsync -n, git clean -n, o find con -print antes de -delete.
Fuentes
- Manual de GNU coreutils: rm y el tratamiento especial de /
- Manual de Bash: sintaxis del archivo de inicio de Readline
- tmux(1), manual de OpenBSD
- ssh_config(5), manual de OpenBSD