Nano no guarda: error de permisos y cómo resolverlo
Si nano muestra Permission denied al guardar, comprueba propietario, directorio padre, sistema de archivos de solo lectura o lleno y tu uid en el contenedor.
Por qué nano no guarda el archivo
nano no guarda el archivo por uno de estos cuatro motivos: no es propietario del archivo, el directorio padre no permite la operación que nano intenta realizar, el sistema de archivos es de solo lectura o no tiene espacio, o está dentro de un contenedor que se ejecuta con otro ID de usuario. Los dos primeros son problemas de permisos y los dos últimos no lo son. Compruébelos en ese orden porque el primer motivo cubre la mayoría de los casos, se confirma con un solo comando y su solución es sudoedit en lugar de sudo nano.
No se pierde nada mientras el editor siga abierto. El texto permanece en memoria, por lo que puede dejar el archivo abierto, escribir el búfer en una ruta de la que sea propietario y colocarlo después en su ubicación. Esta alternativa se explica cerca del final de esta guía.
Ejecute estas comprobaciones antes de cambiar permisos
Apunte cada comando a la ruta real que está editando. Cada uno responde a una pregunta diferente, por lo que debe ejecutarlos todos antes de modificar nada. Cambiar los permisos sin saber qué comprobación falla suele crear un segundo problema además del primero.
id
ls -l /etc/nginx/nginx.conf
ls -ld /etc/nginx
namei -l /etc/nginx/nginx.conf
findmnt -no SOURCE,FSTYPE,OPTIONS -T /etc/nginx/nginx.conf
df -h /etc/nginx
df -i /etc/nginxid muestra el ID de usuario y los ID de grupo que tiene en este momento. ls -l muestra el propietario, el grupo y los bits de permisos del propio archivo. ls -ld muestra lo mismo para el directorio que lo contiene, que es una pregunta independiente con una respuesta independiente. namei -l recorre cada parte de la ruta y muestra el propietario y los permisos de cada una, por lo que responde a ambas preguntas en una sola salida. findmnt indica el sistema de archivos situado bajo esa ruta y las opciones con las que se montó. df -h informa del espacio libre y df -i informa de los inodos libres, que se agotan por separado del espacio. Si esas cadenas de permisos aún no le resultan familiares, empiece por cómo leer la cadena de permisos que muestra ls -l.
Causa 1: el archivo pertenece a root y usted no
Los permisos de lectura y escritura son independientes, y la mayoría de los archivos de /etc pueden ser leídos por cualquier usuario. Por eso nano abre el archivo, muestra su contenido y permite escribir en él: ninguna de esas acciones modifica el disco. El rechazo se produce al guardar, cuando el kernel compara su ID de usuario y sus ID de grupo con el propietario, el grupo y los permisos para otros usuarios del archivo. nano sólo muestra la respuesta del kernel, por lo que ninguna opción de nano cambia el resultado.
id y ls -l lo confirman. El archivo pertenece a root, usted no es root y los permisos para otros usuarios no conceden escritura. Pulsar Ctrl-O de nuevo no solucionará el problema.
Por qué sudoedit es la forma correcta de editar un archivo propiedad de root
SUDO_EDITOR=nano sudoedit /etc/nginx/nginx.confsudo crea una copia temporal del archivo cuyo propietario eres tú, ejecuta nano sobre esa copia como tu propio usuario y, cuando el editor termina, copia el resultado a su ubicación original con privilegios de root. El editor nunca se ejecuta como root. sudo -e es el mismo comando con otro nombre. El editor se selecciona primero desde SUDO_EDITOR, después desde VISUAL y, por último, desde EDITOR, por lo que export EDITOR=nano en el perfil de tu shell establece el editor predeterminado en todos los casos. Si en sudoers la opción env_editor está desactivada, esas variables se ignoran y el editor se obtiene de la configuración editor de sudoers.
sudo nano también guarda el archivo, y ese es el problema. Concede al editor interactivo completo privilegios de root sobre todo el sistema de archivos mientras dura la sesión. Por tanto, una ruta escrita por error en el indicador de guardado puede sobrescribir otro archivo del sistema con permisos de root. Trabajar como un usuario normal que usa sudo sólo para los pasos que lo necesitan es el hábito que conviene adoptar. sudoedit es la forma de aplicar ese hábito al editar un archivo de configuración.
Dos reglas de sudoedit sorprenden a muchos usuarios. Rechaza editar un enlace simbólico y rechaza editar un archivo dentro de un directorio en el que tienes permisos de escritura, salvo que seas root. La segunda regla existe porque cualquiera que pueda escribir en el directorio puede reemplazar el archivo mientras el editor está abierto. Ambos comportamientos son los valores predeterminados de sudoers (sudoedit_follow desactivada, sudoedit_checkdir activada). Si el archivo todavía no existe, se crea.
Causa 2: qué controla realmente el directorio padre
Las recomendaciones escritas para otros editores indican que guardar un archivo requiere permiso de escritura en el directorio, porque muchos editores guardan escribiendo un archivo nuevo y cambiándole el nombre para reemplazar el anterior. nano no funciona así. Abre el archivo indicado y escribe en ese mismo archivo. Por tanto, si el archivo ya existe, nunca se consulta el bit de escritura del directorio.
El directorio sigue controlando otros aspectos. Por eso ls -ld aparece en la lista de comprobaciones:
- Crear un archivo que todavía no existe requiere permisos de escritura y ejecución en el directorio, porque es necesario añadirle un nombre nuevo. umask determina los permisos iniciales de ese archivo nuevo.
- Para llegar al archivo se necesita permiso de ejecución, también llamado permiso de búsqueda, en todos los directorios de la ruta. Si falta en uno de ellos, se bloquea todo lo que hay debajo, y
namei -lmuestra cuál es. - Guardar con copias de seguridad o con el bloqueo de archivos activado escribe un segundo archivo junto al original. Por tanto, estas funciones sí requieren un directorio con permiso de escritura. Las copias de seguridad se controlan con la opción
-Bo conset backupen un nanorc, y el bloqueo con-Goset locking. Ambas funciones están desactivadas, salvo que usted o su distribución las hayan activado.
Los permisos de los directorios tienen la misma importancia en otras partes del sistema. El servidor SSH rechaza una clave si otros usuarios pueden escribir en su directorio personal o en su directorio .ssh. Esta es una causa habitual de que SSH rechace su clave durante el inicio de sesión.
Como nano escribe en el archivo que ya existe, el archivo conserva su inode, que es la identidad del archivo en el disco asociada a su nombre. Cualquier proceso que mantenga abierto el archivo sigue trabajando con él, y un archivo individual montado mediante bind en un contenedor continúa funcionando. Los editores que guardan reemplazando el archivo rompen ese montaje, porque el montaje sigue el inode y no el nombre.
Causa 3: el sistema de archivos es de solo lectura o no le queda espacio
findmnt indica ro en las opciones significa que la escritura no podía completarse. El sistema de archivos se montó así, mediante /etc/fstab o mediante un montaje bind de solo lectura, o el kernel lo volvió a montar como de solo lectura después de un error de disco. El segundo caso es el grave. sudo dmesg -T | tail -50 muestra los errores de entrada/salida y del sistema de archivos que provocaron el remontaje. La reparación consiste en comprobar el sistema de archivos mientras está desmontado. En un VPS, esto significa arrancar la consola de rescate del proveedor.
Un sistema de archivos lleno impide la misma escritura por otro motivo. df -h cubre el caso habitual. df -i cubre el caso que suele pasarse por alto: los inodos proceden de un grupo fijo creado al crear el sistema de archivos, y un árbol con archivos pequeños puede agotarlos aunque df -h siga mostrando gigabytes libres. Cuando no queda espacio y no hay nada evidente que lo esté ocupando, cuando df y du no coinciden sobre un disco lleno explica el caso de un archivo eliminado que todavía está abierto y provoca el problema.
Un detalle explica un síntoma confuso en este caso. ext4 reserva una parte de sus bloques para root al crear el sistema de archivos, por lo que root puede seguir escribiendo después de que se deniegue la escritura a los usuarios normales. sudo parece entonces la solución, el disco se llena por completo y el problema vuelve en una forma más grave.
Como nano trunca el archivo antes de escribir el contenido nuevo, una escritura que se queda sin espacio a mitad del proceso puede dejar el archivo más corto que antes. Copie los archivos de configuración importantes antes de editarlos en un sistema de archivos casi lleno. sudo cp -a /etc/nginx/nginx.conf /root/nginx.conf.bak conserva el propietario, el grupo y los permisos de la copia.
Causa 4: está en un contenedor y edita un bind mount
La propiedad de los archivos se almacena como valores numéricos. El kernel guarda un ID de usuario, y el nombre que se muestra procede de la búsqueda que realiza /etc/passwd. Por eso, un mismo archivo puede mostrar un nombre en el host y otro nombre, o sólo un número, dentro del contenedor. Compare los números, no los nombres: ejecute id -u dentro del contenedor y ls -ln sobre el archivo.
Un archivo montado mediante bind mount conserva la propiedad que tiene en el host. Cuando el archivo del host pertenece a su usuario y el proceso del contenedor se ejecuta con otro usuario, la escritura se rechaza dentro del contenedor. Además, sudo dentro del contenedor no cambia la propiedad del archivo en el host. Corríjalo desde el host asignando el propietario al ID con el que se ejecuta el contenedor, o ejecute el contenedor con el ID que ya es propietario de los archivos. Las imágenes de linuxserver.io y de proyectos similares exponen las variables PUID y PGID que establecen con qué usuario se ejecuta el proceso.
Conviene conocer otros dos casos relacionados con contenedores. Un montaje creado como de sólo lectura con :ro, o un contenedor iniciado con --read-only, rechaza las escrituras independientemente de la propiedad. cat /proc/mounts dentro del contenedor muestra este indicador. Con rootless Podman, un espacio de nombres de usuario asigna los ID de usuario del contenedor a un rango de ID del host. Por eso, un archivo que parece pertenecer a root dentro del contenedor pertenece a su cuenta sin privilegios fuera de él.
También existe el caso de una edición que se aplica y después desaparece. Un archivo que modifica dentro de un contenedor, en una ruta que no es un montaje, reside en la capa escribible del contenedor. Esa capa se descarta cuando se vuelve a crear el contenedor. Modifique el archivo en el lado del host del montaje, o durante la construcción de la imagen, si el cambio debe conservarse.
La salida de emergencia: guárdelo en una ruta de su propiedad
No intente obtener privilegios desde el editor. Pulse Ctrl-O, borre la ruta del indicador, escriba una ruta dentro de su directorio personal, como /home/you/nginx.conf.new, y pulse Enter. Después, pulse Ctrl-X para salir. El archivo ya está guardado en el disco, es de su propiedad y el resto es una copia de archivo normal.
sudo cp /home/you/nginx.conf.new /etc/nginx/nginx.conf
sudo nginx -tUse cp aquí en lugar de mv. cp escribe a través del archivo que ya existe, por lo que ese archivo conserva su propietario, grupo y permisos. mv, en el mismo sistema de archivos, lo reemplaza por su archivo. Esto deja un archivo de configuración en /etc cuyo propietario es su cuenta de usuario, y ese se convierte en el siguiente problema de permisos que debe resolver.
Compruebe el resultado con la herramienta responsable del archivo antes de volver a cargar nada. sudo nginx -t analiza la configuración de nginx y sudo sshd -t analiza la configuración del servidor SSH. Dos archivos tienen editores específicos que realizan todo este procedimiento: sudo visudo para /etc/sudoers y crontab -e para sus propias tareas de cron. Cada uno edita una copia temporal, comprueba la sintaxis e instala el archivo sólo si el análisis es correcto.
FAQ
¿Debo usar sudo nano o sudoedit para editar un archivo del sistema?
Use sudoedit. Copia el archivo en una copia temporal de su propiedad, ejecuta el editor con su usuario y escribe el resultado como root cuando el editor termina. Así, el editor nunca tiene privilegios de root. Establezca SUDO_EDITOR, VISUAL o EDITOR en nano para seleccionar nano. sudo nano también funciona, pero concede a un editor interactivo acceso de root a todas las rutas del sistema durante la sesión. Esto convierte un nombre de archivo escrito incorrectamente en el indicador de guardado en un archivo del sistema dañado.
¿Necesito permiso de escritura en el directorio para guardar un archivo con nano?
No si el archivo ya existe. nano escribe directamente en el archivo. Por eso, el kernel comprueba el bit de escritura del archivo y el bit de ejecución de cada directorio de la ruta. El bit de escritura del directorio es necesario cuando el archivo todavía no existe, porque hay que crear un nombre nuevo. También es necesario cuando las copias de seguridad o el bloqueo de archivos están activados, porque ambas funciones escriben un segundo archivo junto al original.
El propietario es correcto y el disco no está lleno. ¿Qué más puede impedir la escritura?
Hay cuatro posibilidades. El sistema de archivos puede estar montado como de solo lectura, como muestra findmnt -no OPTIONS -T /etc/nginx/nginx.conf. El archivo puede tener el atributo immutable, que muestra lsattr y elimina sudo chattr -i. Ni siquiera root puede escribir en el archivo mientras ese atributo esté establecido. El conjunto de inodos puede estar agotado aunque quede espacio libre, como muestra df -i. SELinux o AppArmor pueden denegar la escritura aunque los bits de permisos la permitan. El registro de auditoría registra la denegación para la ruta que intentó utilizar.
¿Dónde guardo los cambios si el archivo no se puede guardar de ninguna forma?
Pulse Ctrl-O e indique una ruta de su propiedad, dentro de su directorio personal o en cualquier otra ubicación donde su usuario pueda escribir. El búfer sigue en memoria, por lo que no se pierde nada de lo que escribió. Copie después el archivo guardado a su ubicación con sudo cp. Este comando conserva el propietario y los permisos del archivo original. Luego compruébelo con el comando de prueba propio del servicio antes de volver a cargarlo.
¿Por qué desaparecen mis cambios dentro de un contenedor Docker?
Si la ruta no es un montaje, el cambio se guarda en la capa de escritura de ese contenedor. Esa capa se elimina cuando el contenedor se reemplaza. Edite el archivo en el lado del host de un bind mount o un volumen, o inclúyalo en la imagen. Si la ruta es un bind mount y la escritura se rechaza, compare id -u dentro del contenedor con el propietario numérico obtenido mediante ls -ln. El archivo conserva el propietario del host y el proceso del contenedor debe coincidir con él.