¿Cómo probar de forma no invasiva el acceso de escritura a un archivo?


20

En una secuencia de comandos de shell, ¿cómo puedo probar de forma fácil y no invasiva el acceso de escritura a un archivo sin intentar modificarlo?

Podría analizar la salida de stat, pero eso parece realmente complejo, y quizás frágil, aunque no estoy seguro de cuánto difiere la salida de estadísticas entre implementaciones y tiempo.

Podría agregar al final del archivo y ver si eso tiene éxito, pero eso es potencialmente peligroso, por dos razones que puedo pensar:

  1. Ahora tengo que eliminar la adición, y en caso de que algún otro proceso escriba en el archivo, esto inmediatamente no será trivial ya que mi línea ya no es la última.
  2. Cualquier proceso de lectura del archivo puede tener requisitos arbitrarios sobre el contenido de ese archivo, y es posible que haya roto esa aplicación.

Respuestas:


29

Solo use la wbandera - de la testutilidad:

[ -w /path/to/file ] && echo "writeable" || echo "write permission denied"

Tenga en cuenta que si va a escribir en el archivo más tarde, aún es posible que no pueda escribir en él. El archivo puede haberse movido, los permisos pueden haber cambiado, etc. También puede suceder que -wdetecte permisos de escritura, pero interviene algún otro factor para que el archivo no se pueda escribir .


1
¡Por supuesto! Debería haber pensado revisar la página del manual de prueba. Gracias.
user50849

1
@qweilun es un shell incorporado, pero puede mostrar la página de manual a través de man testoman [
chaos

55
@chaos Es tanto un shell integrado como un ejecutable externo - pruebatype -a
Volker Siegel

1
Por lostest usos de origen euidaccessque simplemente comprueba los bits de permiso . ¿No hay otros factores (por ejemplo, SELinux) que podrían prohibir el acceso de escritura?
zamnuts

2
@BroSlow, &&y ||tienen la misma precedencia. Se evalúan de izquierda a derecha.
Comodín el

11

Otro enfoque:

if >> /path/to/file
then
    echo "writeable"
else
    echo "write permission denied"
fi

Esto intentará abrir el archivo para agregarlo y, si tiene éxito, no ejecutará ningún comando (es decir, ejecutará un comando nulo ) con salida al archivo. 

Tenga en cuenta que esto crea un archivo vacío si no existiera.

El -woperador del testcomando podría simplemente hacer un stat y luego tratar de averiguar si parece que debería tener acceso. Mi alternativa (arriba) es más confiable que el testenfoque en algunas condiciones especiales, porque obliga a que el kernel realice la verificación de acceso en lugar del shell. Por ejemplo,

  • si el archivo está en un sistema de archivos que no es Unix, especialmente si está montado de forma remota desde un servidor de archivos que no es Unix, porque statpodría devolver un valor de modo que es engañoso.
  • si el archivo está en un sistema de archivos que está montado de solo lectura.
  • si el archivo tiene una ACL, y el modo hace que parezca que debería tener acceso, pero la ACL lo niega, o viceversa.
  • si algún marco de seguridad (AppArmor, SELinux, ...) niega el acceso al archivo.

3
Acabo de probar esto (en Debian). No se modificó el tiempo, y esa es la forma en que debería funcionar en cualquier Unix. El tiempo de acceso debe actualizarse solo si lee del archivo, el tiempo de modificación debe actualizarse solo si escribe en el archivo. Este código tampoco. @Schwern: ¿tiene una referencia para su estado de cuenta? ¿Alguno de ustedes lo ha intentado?
G-Man dice 'reinstalar a Monica' el

2
PD @muru: acabo de probar touchun archivo que poseía pero al que no tenía acceso de escritura, y lo logré. Supongo que chmodes el archivo y chmodlo devuelve. Entonces touchparece ser absolutamente inútil como respuesta a la pregunta.
G-Man dice 'Restablecer a Monica' el

2
@ G-Man ah, eso es interesante. IIRC vimtiene el comportamiento de cambiar rápidamente los permisos cuando se ve obligado a escribir en archivos de solo lectura. Verifiqué con strace, touch's openfalla con EACCES, pero la llamada posterior al utimensatéxito tiene éxito, por lo que creo que touchen general todo sale con éxito.
Muru

2
@muru: Gracias por comprobar eso. utimensat(2)dice: " Requisitos de permisos: 1. acceso de escritura (o) 2. la identificación de usuario efectiva de la persona que llama debe coincidir con el propietario del archivo, ...".
G-hombre dice 'Restablecer Mónica'

3
Otros problemas como el de Champignac: >> fileno es portátil (por ejemplo, ejecuta el NULLCMD en zsh), utilícelo true >> fileen su lugar. Y si el archivo es una tubería con nombre, tiene efectos secundarios desagradables.
Stéphane Chazelas

3

G-man tiene razón: [ -w ]no siempre dirá la verdad. Aquí para hacer frente a un archivo no existente y al mensaje de permiso denegado del shell:

( [ -e /path/to/file ] && >> /path/to/file ) 2> /dev/null && 
  echo writable || 
  echo not writable

Actualización : Parece aterrador, ¿no? Bueno, lo es. Hmm ... cómo expresarlo ... NO UTILICE ESTO, a menos que sepa perfectamente que se encuentra en las condiciones en que solicita que funcione como se espera. Ver el comentario de Stephane.

¿Qué concluir, entonces? Incluso si[ -w ] no dice la verdad, es el único comando que está destinado a hacer el trabajo. Si no es así, bueno, lo culparemos, escribiremos informes de errores y funcionará en el futuro. Mejor verifique las condiciones bajo las cuales funciona y usa [ -w ]; escribir código especial para casos especiales. Las soluciones tienen sus propias condiciones.

[ -w /path/to/file ]

es la mejor a priori .


3
Si el archivo es una tubería con nombre, se bloqueará si no hay lectura, e incluso si hay un lector tendrá efectos secundarios desagradables. test -wen la mayoría de las implementaciones, los usos access(2)deberían ser suficientes para probar los permisos.
Stéphane Chazelas
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.