chmod 755 vs u+x: modos numérico y simbólico
Aprende chmod con ejemplos: qué significan los dígitos octales y u/g/o, por qué chmod -R 755 rompe directorios y cómo X evita añadir ejecución a archivos.
Qué cambia chmod
chmod cambia los bits de permisos de un archivo o directorio y acepta esos bits con una de dos notaciones. La forma numérica es un número octal que reemplaza todos los bits de permisos a la vez. La forma simbólica indica una clase de usuario y un operador, y modifica sólo los bits que se especifican. Ambas terminan en la misma llamada al sistema. La diferencia está en lo que ocurre con los bits que no se indican.
Leer un modo y cambiar un modo son tareas distintas. Si las letras de un listado largo todavía no resultan evidentes, lea primero qué significa drwxr-xr-x campo por campo. Esta guía sólo los cambia.
Ejecute todo lo indicado aquí con su usuario de inicio de sesión normal. La cuenta root omite estas comprobaciones, por lo que una demostración de permisos ejecutada como root no demuestra nada. Si todavía está trabajando como root en un servidor nuevo, cree un usuario normal con privilegios mínimos y vuelva aquí.
Configura un entorno aislado que puedas eliminar
cd "$(mktemp -d)"
touch notes.txtmktemp -d crea un directorio vacío dentro de /tmp e imprime la ruta que ha creado, y sustitución de comandos pasa esa ruta directamente a cd. Nada de lo que aparece a continuación modifica archivos que necesites conservar.
Un comando muestra el resultado de cada cambio:
stat -c '%a %A %n' notes.txt%a muestra el modo como un número octal, %A muestra el mismo modo con letras, como en un listado largo, y %n muestra el nombre. En los bloques siguientes, una línea que empieza por $ es lo que debes escribir y la línea siguiente es lo que ha mostrado el comando. Ejecútalos tú mismo. El resultado de tu máquina debería coincidir línea por línea, porque un modo numérico no depende de nada de tu entorno.
La forma numérica: un dígito octal por clase
El primer dígito corresponde al propietario del archivo. El segundo corresponde al grupo del archivo. El tercero corresponde a todos los demás. Cada dígito es una suma, con un valor por bit. Establezca un bit cada vez y lea lo que informa stat.
$ chmod 400 notes.txt
$ stat -c '%a %A %n' notes.txt
400 -r-------- notes.txt
$ chmod 200 notes.txt
$ stat -c '%a %A %n' notes.txt
200 --w------- notes.txt
$ chmod 100 notes.txt
$ stat -c '%a %A %n' notes.txt
100 ---x------ notes.txtLas letras se corresponden con los dígitos. Después del carácter inicial que indica el tipo de archivo, el primer grupo de tres letras corresponde al propietario, el siguiente grupo de tres al grupo y los últimos tres caracteres a todos los demás. Sume los valores para combinar bits dentro de una clase.
$ chmod 600 notes.txt
$ stat -c '%a %A %n' notes.txt
600 -rw------- notes.txt
$ chmod 700 notes.txt
$ stat -c '%a %A %n' notes.txt
700 -rwx------ notes.txt
$ chmod 750 notes.txt
$ stat -c '%a %A %n' notes.txt
750 -rwxr-x--- notes.txtUn modo numérico es absoluto. Escribe los nueve bits en cada ejecución, por lo que también escribe una clase en la que nunca pensó.
$ chmod 755 notes.txt
$ stat -c '%a %A %n' notes.txt
755 -rwxr-xr-x notes.txt
$ chmod 600 notes.txt
$ stat -c '%a %A %n' notes.txt
600 -rw------- notes.txtEl segundo comando no indicó nada sobre el grupo ni sobre todos los demás, pero sus bits también cambiaron. Esa es la característica de la forma numérica y por eso es la herramienta incorrecta para una modificación pequeña. (chmod también gestiona los bits setuid, setgid y sticky, que se encuentran en un cuarto dígito delante de estos. Es un tema aparte y esta guía se centra en los tres.)
La forma simbólica: una clase, un operador y, después, los bits
Escriba primero la clase. u es el propietario, g es el grupo, o representa a todos los demás y a representa las tres clases a la vez. Después, escriba el operador: + añade bits, - elimina bits y = establece esa clase exactamente con los bits indicados y elimina el resto de sus bits. Por último, escriba los bits como r, w o x.
$ chmod 640 notes.txt
$ stat -c '%a %A %n' notes.txt
640 -rw-r----- notes.txt
$ chmod u+x notes.txt
$ stat -c '%a %A %n' notes.txt
740 -rwxr----- notes.txt
$ chmod g-r notes.txt
$ stat -c '%a %A %n' notes.txt
700 -rwx------ notes.txt
$ chmod o=r notes.txt
$ stat -c '%a %A %n' notes.txt
704 -rwx---r-- notes.txtCada comando modificó una sola clase y mantuvo las demás sin cambios. Combine las cláusulas con comas y sin espacios. chmod las aplica de izquierda a derecha.
$ chmod u=rw,go=r notes.txt
$ stat -c '%a %A %n' notes.txt
644 -rw-r--r-- notes.txt
$ chmod go= notes.txt
$ stat -c '%a %A %n' notes.txt
600 -rw------- notes.txtgo= sin nada después del signo igual elimina todos los bits del grupo y de todos los demás usuarios. Este es el formato que necesita para un archivo que sólo su propietario puede leer, como la parte privada de un par de claves SSH.
chmod también puede informar sobre sus propias acciones. Esto es útil dentro de un script cuando nadie supervisa la pantalla.
chmod -v u+x notes.txt
chmod -v u+x notes.txt-v imprime una línea por cada archivo que recibe. Ejecute ambos comandos y compare las dos líneas en pantalla: la primera identifica el archivo e indica el modo anterior y el modo nuevo, y la segunda indica que el modo se mantuvo porque el bit que debía añadir ya estaba establecido. -c imprime una línea sólo cuando un archivo cambia realmente, por lo que es la opción más adecuada para conservar en un registro.
chmod 755 frente a u+x: qué notación usar
Empiece dos veces con el mismo archivo y compare qué deja cada notación.
$ chmod 640 notes.txt
$ chmod 755 notes.txt
$ stat -c '%a %A %n' notes.txt
755 -rwxr-xr-x notes.txt
$ chmod 640 notes.txt
$ chmod u+x notes.txt
$ stat -c '%a %A %n' notes.txt
740 -rwxr----- notes.txtAmbos comandos hicieron que el propietario pudiera ejecutar el archivo. Sólo uno dejó sin cambios las otras dos clases. Use un modo numérico cuando conozca el estado final exacto que desea y quiera imponerlo. Este es el caso adecuado en un script de despliegue que debe producir el mismo resultado en una máquina que no conoce. Use un modo simbólico cuando la frase que tiene en mente contiene add o remove, porque la forma numérica no permite indicar que se deje esa parte sin cambios.
El modo con el que empieza un archivo nuevo no procede de chmod. Procede de la umask del proceso que creó el archivo. Ejecute umask y umask -S en su propia shell para ver el valor activo allí. Espere que difiera entre distribuciones, entre su shell de inicio de sesión y un servicio de systemd, y entre una cuenta y otra. La umask establece el modo de todos los archivos nuevos, por lo que determina el estado inicial antes de que se ejecute chmod.
Qué hace el bit de ejecución en un directorio
Este es el malentendido que más tiempo hace perder. En un archivo normal, el bit de ejecución indica que el kernel puede ejecutar el archivo. Un directorio no contiene instrucciones, por lo que no hay nada que ejecutar en él. En un directorio, el bit de ejecución significa recorrido: permiso para resolver un nombre dentro de él. Para acceder a dir/file necesita ese permiso en dir. El bit de lectura es un permiso independiente y permite listar los nombres que contiene el directorio. Puede tener uno sin el otro, algo que resulta más fácil de entender después de observarlo en la práctica.
$ mkdir vault
$ printf 'hello\n' > vault/secret.txt
$ chmod 600 vault/secret.txt
$ chmod 100 vault
$ echo vault/*
vault/*
$ cat vault/secret.txt
helloEl shell devolvió el patrón sin cambios porque expandir vault/* implica leer el directorio, y un patrón glob que no coincide con nada se pasa como texto literal en lugar de generar un error. cat siguió funcionando porque proporcionó el nombre manualmente y el recorrido estaba permitido. Ahora intercambie los dos bits.
$ chmod 400 vault
$ echo vault/*
vault/secret.txt
$ cat vault/secret.txt
cat: vault/secret.txt: Permission deniedLos nombres son visibles, pero no el contenido. La lectura proporciona la lista. La ejecución proporciona el acceso. Casi todos los directorios que utiliza necesitan ambos permisos.
$ chmod 500 vault
$ cat vault/secret.txt
helloPor qué chmod -R con un modo numérico daña un árbol
-R recorre todo el árbol y aplica el modo indicado a cada elemento que encuentra. Un directorio y un archivo de datos necesitan bits distintos, por lo que un único número absoluto no puede ser correcto para ambos. Cree un árbol pequeño y observe cómo se produce el problema.
$ mkdir -p site/css
$ touch site/index.html site/css/main.css
$ printf '#!/bin/bash\necho hi\n' > site/deploy.sh
$ chmod 755 site site/css site/deploy.sh
$ chmod 644 site/index.html site/css/main.css
$ stat -c '%a %A %n' site site/css site/index.html site/css/main.css site/deploy.sh
755 drwxr-xr-x site
755 drwxr-xr-x site/css
644 -rw-r--r-- site/index.html
644 -rw-r--r-- site/css/main.css
755 -rwxr-xr-x site/deploy.shEsa es la estructura que necesita un directorio de archivos estáticos. Este es el primer error recursivo.
$ chmod -R 755 site
$ stat -c '%a %A %n' site/index.html site/css/main.css
755 -rwxr-xr-x site/index.html
755 -rwxr-xr-x site/css/main.cssNo se rompe nada, y ese es el problema. El error es silencioso, por lo que permanece durante años en instrucciones copiadas. Ahora dos archivos de datos indican que son programas. Git almacena el bit de ejecución, por lo que el siguiente commit propagará el cambio a todos los que clonen el repositorio, y rsync y tar lo propagarán a todos los equipos donde copie el árbol.
El segundo error recursivo es visible de inmediato. Aplique a un directorio un modo sin bit de ejecución y el directorio quedará cerrado.
$ chmod 644 site
$ stat -c '%a %A %n' site
644 drw-r--r-- site
$ echo site/*
site/css site/deploy.sh site/index.html
$ cd site
bash: cd: site: Permission denied
$ cat site/index.html
cat: site/index.html: Permission deniedLos nombres siguen apareciendo porque el bit de lectura se conservó, pero todas las rutas que atraviesan el directorio quedan cerradas porque falta el bit de ejecución. chmod -R 644 site hace eso con todos los directorios del árbol en un solo comando. El resultado tampoco siempre es uniforme, porque chmod debe recorrer los mismos directorios cuyo acceso está eliminando. Por eso, compruebe qué se aplicó realmente con find site -type d -exec stat -c '%a %n' {} + en lugar de darlo por supuesto. Restablezca este cambio antes de continuar.
$ chmod 755 site
$ chmod 644 site/index.html site/css/main.css
$ stat -c '%a %A %n' site site/index.html
755 drwxr-xr-x site
644 -rw-r--r-- site/index.htmlUn chmod recursivo no tiene deshacer. chmod no registra lo que reemplazó, por lo que la reparación consiste en reconstruir los modos a partir de lo que cree que tenían antes. Es el mismo trabajo lento e incierto que reconstruir archivos después de un rm -rf accidental, y la lección es la misma: compruebe el destino de un comando recursivo antes de pulsar Enter.
La X mayúscula: ejecutar en directorios, no en todos los archivos
Los modos simbólicos aceptan X y también x. X establece el bit de ejecución sólo cuando corresponde: en un directorio o en un archivo normal que ya tiene un bit de ejecución para alguna clase. Esa regla coincide exactamente con la que querías que siguiera -R.
$ chmod -R u=rwX,go=rX site
$ stat -c '%a %A %n' site site/css site/index.html site/css/main.css site/deploy.sh
755 drwxr-xr-x site
755 drwxr-xr-x site/css
644 -rw-r--r-- site/index.html
644 -rw-r--r-- site/css/main.css
755 -rwxr-xr-x site/deploy.shUn solo comando, y los directorios siguieron siendo transitables mientras los archivos de datos no se modificaron. El script conservó su bit de ejecución porque ya tenía uno, que es la segunda parte de la regla X. X lee el modo actual de un archivo, por lo que un archivo que ya perdió todos los bits de ejecución no puede recuperarlos mediante este comando.
$ chmod 644 site/deploy.sh
$ chmod -R u=rwX,go=rX site
$ stat -c '%a %A %n' site/deploy.sh
644 -rw-r--r-- site/deploy.sh
$ site/deploy.sh
bash: site/deploy.sh: Permission denied
$ chmod u+x site/deploy.sh
$ stat -c '%a %A %n' site/deploy.sh
744 -rwxr--r-- site/deploy.sh
$ site/deploy.sh
hiLa misma regla funciona en el sentido contrario. X extiende a otra clase un bit de ejecución que el archivo ya tiene:
$ chmod go+X site/deploy.sh
$ stat -c '%a %A %n' site/deploy.sh
755 -rwxr-xr-x site/deploy.shPor tanto, la x minúscula sirve para hacer ejecutable un archivo concreto, y X sirve para recorrer un árbol completo. Si necesitas establecer un modo exacto para cada tipo de elemento, en lugar de aplicar una regla basada en el modo actual, divide el recorrido con find.
find site -type d -exec chmod 755 {} +
find site -type f -exec chmod 644 {} +
chmod u+x site/deploy.sh-type d selecciona los directorios y -type f selecciona los archivos normales, de modo que cada tipo recibe el modo correspondiente. -exec ... + agrupa muchas rutas en una sola llamada a chmod en lugar de iniciar un proceso por archivo, lo que resulta importante en un árbol con miles de entradas. El script recupera su bit en una línea independiente, de forma deliberada.
Compruebe el resultado antes de terminar
Dos comandos detectan los errores importantes después de cualquier cambio recursivo. El primero muestra los directorios en los que ya no puede entrar.
find . -type d ! -perm -u+xEl segundo muestra los archivos que cualquier cuenta del equipo puede modificar.
find . -type f -perm -o+wEn -perm -o+w, el - inicial significa como mínimo estos bits, por lo que coincide con un archivo cuya clase o contiene el bit de escritura, independientemente de los demás permisos definidos. Lo que busca es que ninguno de los dos comandos muestre resultados. Ejecute ambos desde la raíz de cualquier árbol que acabe de modificar con -R y ejecute stat -c '%a %A %n' en el pequeño conjunto de rutas que pretendía cambiar, para comprobar que el modo que cree haber establecido coincide con el que realmente mantiene el kernel.
FAQ
¿Cuál es la diferencia entre chmod 755 y chmod u+x?
Un modo numérico es absoluto. Escribe todos los bits de permisos del archivo, por lo que también reescribe las clases que no tenía previsto modificar. Un modo simbólico es una edición. u+x añade un bit para el propietario y deja sin cambios todos los demás bits. Use la forma numérica cuando conozca el estado final exacto que quiere aplicar a un archivo. Use la forma simbólica cuando quiera añadir o quitar un elemento. Ejecute stat -c '%a %A %n' <file> antes y después de cualquiera de los dos comandos para ver la diferencia en la salida.
¿Por qué es una mala idea usar chmod -R 755 en un directorio con archivos web?
Porque -R aplica el mismo modo absoluto a los directorios y a los archivos normales, pero ambos necesitan bits distintos. Un directorio necesita el bit de ejecución para poder atravesarse. Los archivos de datos, como HTML y CSS, no lo necesitan; marcarlos como ejecutables es un cambio que git registra en la siguiente confirmación y que rsync copia al siguiente equipo. Use chmod -R u=rwX,go=rX <dir> para que el bit de ejecución se aplique sólo a los directorios, o use find con -type d y -type f para asignar un modo propio a cada tipo.
¿Qué hace el bit de ejecución en un directorio?
Concede permiso de recorrido, no de ejecución. No hay nada dentro de un directorio que se pueda ejecutar. El bit de ejecución permite resolver un nombre dentro del directorio, por lo que debe estar presente en todos los directorios de una ruta antes de poder abrir el archivo situado al final de esa ruta. El bit de lectura es independiente y permite listar los nombres. Puede tener uno sin el otro: con sólo el bit de ejecución puede abrir un archivo cuyo nombre ya conoce, mientras el shell no puede expandir un comodín en ese directorio; con sólo el bit de lectura puede ver los nombres, pero todos los intentos de abrir uno fallan.
¿Cuándo debo usar la X mayúscula en lugar de la x minúscula?
Use X siempre que el comando sea recursivo. X establece el bit de ejecución en los directorios y, en los archivos normales, sólo cuando ya hay establecido algún bit de ejecución. Así, una sola pasada permite recorrer un árbol sin convertir los archivos de datos en programas. Use la x minúscula cuando apunte a un solo archivo y se refiera específicamente a ese archivo. Conviene recordar un límite: X no puede restaurar un bit de ejecución que ya se haya eliminado de todas las clases de un archivo, porque ya no tiene ningún bit con el que compararlo. Restaure ese bit con chmod u+x <file>.
¿chmod cambia quién es el propietario de un archivo?
No. chmod sólo cambia los bits de permisos. La propiedad corresponde a chown para el usuario y a chgrp para el grupo; asignar un archivo a otro usuario requiere root. Esto importa porque los bits se interpretan según el usuario y el grupo registrados en el archivo, no según quién lo haya escrito por última vez. Ejecute stat -c '%U %G %a %n' <file> para ver juntos el propietario, el grupo y el modo antes de decidir cuál de los tres comandos necesita realmente.