Come test non invasivo per l'accesso in scrittura a un file?


20

In uno script di shell, come posso testare in modo semplice e non invasivo l' accesso in scrittura a un file senza tentare effettivamente di modificare il file?

Potrei analizzare l'output di stat, ma sembra davvero complesso, e forse fragile, anche se non sono sicuro di quanto output stat differisca tra implementazioni e tempo.

Potrei aggiungere alla fine del file e vedere se ciò ha esito positivo, ma è potenzialmente pericoloso, per due motivi a cui posso pensare:

  1. Ora devo rimuovere l'aggiunta e, nel caso in cui qualche altro processo scriva nel file, questo diventa immediatamente non banale poiché la mia linea non è più l'ultima.
  2. Qualsiasi processo di lettura del file può avere requisiti arbitrari sul contenuto di quel file e potrei aver rotto l'applicazione.

Risposte:


29

Basta usare la - wbandiera testdell'utilità:

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

Nota che se hai intenzione di scrivere sul file in un secondo momento, è ancora possibile che non sarai in grado di scrivere su di esso. Il file potrebbe essere stato spostato, le autorizzazioni potrebbero essere state modificate, ecc. Può anche accadere che -wrilevi le autorizzazioni di scrittura ma alcuni altri fattori intervengono per rendere il file non scrivibile .


1
Ovviamente! Avrei dovuto pensare di controllare la pagina man del test. Grazie.
user50849

1
@qweilun è una shell integrata, ma puoi visualizzare la pagina man tramite man testoman [
caos

5
@chaos È sia un shell incorporato che un eseguibile esterno - provatype -a
Volker Siegel,

1
Per glitest usi sorgente euidaccessche controlla semplicemente i bit di autorizzazione . Non ci sono altri fattori (ad esempio SELinux) che potrebbero vietare l'accesso in scrittura?
Zamnuts,

2
@BroSlow &&e ||hanno la stessa precedenza. Sono valutati da sinistra a destra.
Wildcard

11

Un altro approccio:

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

Ciò tenterà di aprire il file per l'aggiunta e, se ciò ha esito positivo, non esegue alcun comando (ovvero, esegue un comando null ) con l'output nel file. 

Attenzione che questo crea un file vuoto se non esistesse.

L' -woperatore del testcomando potrebbe semplicemente fare una stat e quindi provare a capire se sembra che tu debba avere accesso. La mia alternativa (sopra) è più affidabile testdell'approccio in alcune condizioni speciali, perché forza il controllo di accesso che deve essere eseguito dal kernel piuttosto che dalla shell. Per esempio,

  • se il file si trova su un file system non Unix, specialmente se è montato in remoto da un file server non Unix, perché statpotrebbe restituire un valore di modalità fuorviante.
  • se il file si trova su un file system montato di sola lettura.
  • se il file ha un ACL e la modalità fa sembrare che dovresti avere accesso, ma l'ACL lo nega, o viceversa.
  • se qualche framework di sicurezza (AppArmor, SELinux, ...) nega l'accesso al file.

3
Ho appena provato questo (su Debian). Né il tempo è stato modificato, ed è così che dovrebbe funzionare su qualsiasi Unix. Il tempo di accesso deve essere aggiornato solo se si legge dal file, il tempo di modifica deve essere aggiornato solo se si scrive nel file. Questo codice non fa nessuno dei due. @Schwern: hai un riferimento per la tua affermazione? Qualcuno di voi l'ha provato?
G-Man dice "Reinstate Monica" il

2
PS @muru: ho appena provato a touchun file di mia proprietà ma non avevo accesso in scrittura e ci è riuscito. Immagino sia chmodil file ed chmodè tornato indietro. Quindi touchsembra assolutamente inutile come risposta alla domanda.
G-Man dice "Reinstate Monica" il

2
@ G-Man ah, è interessante. IIRC vimha quel comportamento di cambiare rapidamente le autorizzazioni quando è costretto a scrivere su file di sola lettura. Ho controllato con strace, touchs' openfallisce con EACCES, ma la chiamata successiva al utimensatsuccesso, che è il motivo per cui penso che touchnel complesso uscite con successo.
muru,

2
@muru: grazie per averlo verificato. utimensat(2)dice: “ Permessi requisiti: l'accesso in scrittura 1. (o) 2. ID utente effettivo del chiamante deve corrispondere al proprietario del file, ....”
G-uomo dice 'Ripristinare Monica'

3
Altri problemi come per Champignac: >> filenon è portatile (ad esempio, esegue NULLCMD in zsh), utilizzare true >> fileinvece. E se il file è una pipe denominata, ha effetti collaterali cattivi.
Stéphane Chazelas,

3

G-man ha ragione: [ -w ]non dirà sempre la verità. Qui per far fronte a file inesistenti e messaggio di autorizzazione negata dalla shell:

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

Aggiornamento : sembra spaventoso, no? Beh, lo è. Hmm ... come esprimerlo ... NON USARLO, a meno che tu non sappia perfettamente di essere nelle condizioni in cui richiede di funzionare come previsto. Vedi il commento di Stephane.

Cosa concludere, allora? Anche se [ -w ]non dice la verità, è l'unico comando che è destinato a fare il lavoro. In caso contrario, biasimeremo, scriveremo segnalazioni di bug e funzionerà in futuro. Verificare meglio le condizioni in cui funziona e utilizzare [ -w ]; scrivere un codice speciale per casi speciali. Le soluzioni alternative hanno le loro condizioni.

[ -w /path/to/file ]

è il migliore a priori .


3
Se il file è una pipe denominata, si bloccherà se non c'è lettura e anche se c'è un lettore avrà effetti collaterali cattivi. test -wnella maggior parte delle implementazioni, access(2)quindi dovrebbe essere sufficiente per testare le autorizzazioni.
Stéphane Chazelas,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.