Wie prüfe ich nicht-invasiv den Schreibzugriff auf eine Datei?

20

Wie kann ich in einem Shell-Skript einfach und nicht-invasiv den Schreibzugriff auf eine Datei testen, ohne tatsächlich zu versuchen, die Datei zu ändern?

Ich könnte die Ausgabe von analysieren stat, aber das scheint wirklich komplex und vielleicht spröde zu sein, obwohl ich nicht sicher bin, wie viel stat-Ausgabe sich über Implementierungen und Zeit unterscheidet.

Ich könnte an das Ende der Datei anhängen und sehen, ob das gelingt, aber das ist möglicherweise gefährlich, und zwar aus zwei Gründen, die ich mir vorstellen kann:

  1. Ich muss jetzt den Zusatz entfernen, und falls ein anderer Prozess in die Datei schreibt, ist dies sofort nicht mehr trivial, da meine Zeile nicht mehr die letzte ist.
  2. Jeder Prozess, der die Datei liest, kann willkürliche Anforderungen an den Inhalt dieser Datei stellen, und ich habe diese Anwendung möglicherweise nur beschädigt.
user50849
quelle

Antworten:

29

Verwenden Sie einfach die - wFlagge des testDienstprogramms:

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

Wenn Sie später in die Datei schreiben, ist es dennoch möglich, dass Sie nicht in die Datei schreiben können. Die Datei wurde möglicherweise verschoben, die Berechtigungen haben sich möglicherweise geändert usw. Es kann auch vorkommen, dass -wSchreibberechtigungen erkannt werden , jedoch aufgrund eines anderen Faktors, dass die Datei nicht schreibbar ist .

Chaos
quelle
1
Na sicher! Ich hätte darüber nachdenken sollen, die Manpage von test zu überprüfen. Vielen Dank.
user50849
1
@qweilun es ein Shell - builtin ist, aber Sie können über die man - Seite angezeigt werden man testoderman [
Chaos
5
@chaos Es ist sowohl eine eingebaute Shell als auch eine externe ausführbare Datei - versuchen Sie estype -a
Volker Siegel
1
Pro Quelletest wird euidaccessdas einfach überprüft, Berechtigungsbits . Gibt es keine anderen Faktoren (zB SELinux), die den Schreibzugriff verhindern könnten?
Zamnuts
2
@BroSlow &&und ||haben die gleiche Priorität. Sie werden von links nach rechts ausgewertet.
Wildcard
11

Ein anderer Ansatz:

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

Dadurch wird versucht, die Datei zum Anhängen zu öffnen. Wenn dies erfolgreich ist, führen Sie keinen Befehl aus (dh führen Sie einen Null-Befehl aus ), und geben Sie die Datei aus. 

Beachten Sie, dass dadurch eine leere Datei erstellt wird, wenn sie nicht vorhanden ist.

Der -wOperator des testBefehls könnte einfach a stat ausführen und dann versuchen, herauszufinden, ob Sie Zugriff haben sollten. Meine Alternative (oben) ist unter bestimmten testUmständen zuverlässiger als der Ansatz, da die Zugriffskontrolle eher vom Kernel als von der Shell durchgeführt werden muss. Beispielsweise,

  • Wenn sich die Datei in einem Nicht-Unix-Dateisystem befindet, insbesondere, wenn sie von einem Nicht-Unix-Dateiserver remote eingehängt statwird, wird möglicherweise ein irreführender Moduswert zurückgegeben.
  • Wenn sich die Datei in einem Dateisystem befindet, das schreibgeschützt bereitgestellt ist.
  • Wenn die Datei über eine Zugriffssteuerungsliste verfügt und der Modus den Eindruck erweckt, dass Sie Zugriff haben sollten, verweigert die Zugriffssteuerungsliste dies jedoch oder umgekehrt.
  • Wenn ein Sicherheitsframework (AppArmor, SELinux,…) den Zugriff auf die Datei verweigert.
G-Man sagt, "Monica wiedereinsetzen"
quelle
3
Ich habe das gerade getestet (auf Debian). Weder Zeit wurde geändert, und so sollte es auf jedem Unix funktionieren. Die Zugriffszeit sollte nur aktualisiert werden, wenn Sie aus der Datei lesen. Die Änderungszeit sollte nur aktualisiert werden, wenn Sie in die Datei schreiben. Dieser Code funktioniert auch nicht. @Schwern: hast du eine referenz für deine aussage? Hat jemand von euch es versucht?
G-Man sagt, dass Monica
2
PS @muru: Ich habe gerade versucht, auf toucheine Datei zuzugreifen, deren Eigentümer ich war, auf die ich jedoch keinen Schreibzugriff hatte, und es war erfolgreich. Ich denke, es ist chmoddie Datei und chmodes ist zurück. So touchscheint auf die Frage absolut nutzlos als eine Antwort zu sein.
G-Man sagt, dass Monica
2
@ G-Man ah, das ist interessant. IIRC vimhat das Verhalten, die Berechtigungen schnell zu ändern, wenn das Schreiben in schreibgeschützten Dateien erzwungen wird. Ich habe mit strace, touch‚s opennicht mit EACCES, aber die nachfolgenden Aufruf utimensaterfolgreich ist , weshalb ich denke , touchüber die ganze Exits erfolgreich.
muru
2
@muru: Danke, dass du das überprüft hast. utimensat(2)sagt : „ Berechtigungen Anforderungen: 1. Schreibzugriff (oder) , 2. die effektive Benutzer - ID des Anrufers muss der Besitzer der Datei übereinstimmen, ....“
G-Man ‚wieder einzusetzen Monica‘ sagt
3
Andere Probleme wie bei Champignacs: >> fileIst nicht portabel (zB läuft das NULLCMD in zsh), benutze true >> filestattdessen. Und wenn es sich bei der Datei um eine Named Pipes handelt, hat dies unangenehme Nebenwirkungen.
Stéphane Chazelas
3

G-man hat recht: sagt [ -w ]nicht immer die Wahrheit. Hier, um mit nicht existierenden Datei- und Berechtigungsverweigerungsnachrichten von der Shell umzugehen:

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

Update : Sieht furchterregend aus, oder? Nun, es ist. Hmm ... wie man es ausdrückt ... BENUTZEN SIE DIESES NICHT, es sei denn, Sie wissen genau, dass Sie sich in den Bedingungen befinden, die es erfordert, um wie erwartet zu arbeiten. Siehe Stephanes Kommentar.

Was ist dann zu schließen? Auch wenn [ -w ]es nicht die Wahrheit sagt, ist es der einzige Befehl, der die Arbeit erledigen soll . Wenn nicht, werden wir es beschuldigen, Fehlerberichte schreiben und es wird in Zukunft funktionieren. Überprüfen Sie besser die Bedingungen, unter denen es funktioniert und verwendet wird [ -w ]. Schreiben Sie speziellen Code für spezielle Fälle. Problemumgehungen haben ihre eigenen Bedingungen.

[ -w /path/to/file ]

ist das beste a priori .

Champignac
quelle
3
Wenn es sich bei der Datei um eine Named Pipe handelt, bleibt diese hängen, wenn sie nicht gelesen wird, und selbst wenn ein Reader vorhanden ist, treten unangenehme Nebenwirkungen auf. test -wIn den meisten Implementierungen access(2)sollte dies ausreichen, um Berechtigungen zu testen.
Stéphane Chazelas