Wie werden bestimmte Dateiberechtigungen beim Umleiten der Ausgabe festgelegt?

12

Dies ist wahrscheinlich ein Duplikat, aber alle meine Suchanfragen stellen Fragen zu Fehlern, denen die Berechtigung verweigert wurde.

Ich führe einen Befehl in einer Bash-Shell aus. Ich möchte die Ausgabe umleiten, um sie an eine Datei anzuhängen, die beim ersten Durchlauf wahrscheinlich nicht vorhanden ist. Ich möchte einen bestimmten Dateiberechtigungsmodus festlegen, wenn die Ausgabeumleitung diese Datei erstellen muss. Gibt es eine Möglichkeit, dies mit einem Befehl zu tun?

Zum Beispiel könnte ich es versuchen

foo >> /tmp/foo.log 0644

Wo 0644sind die Berechtigungen, mit denen ich foo.logenden möchte ? Die meisten Befehle, mit denen ich in Bash experimentiert habe, werden 0644als zusätzliches Argument interpretiert foo.

Ich habe das Gefühl, dass dies einen zweiten Befehl für chmoddie Berechtigungen vor oder nach dem Schreiben erfordert.

Ich verwende GNU bash 4.2.25 und Ubuntu 12.04, wenn das einen Unterschied macht - allgemeine Antworten werden bevorzugt.

Patrick M.
quelle

Antworten:

5

Soweit ich weiß, gibt es keine Möglichkeit, dies beim Piping zu tun. Ein einfaches Skript ist möglicherweise die beste Lösung.

if [ -e /tmp/foo.log ]; then
    foo >> /tmp/foo.log
else
    foo >> /tmp/foo.log
    chmod 0644 /tmp/foo.log
fi
Terdon
quelle
Danke Slowki, das war auch meine Vermutung. Ich werde es für ein paar Tage offen lassen, in der Hoffnung, einen Guru anzuziehen, der uns erleuchtet.
Patrick M
3
Das Problem bei diesem Ansatz besteht darin, dass ein kurzes Zeitfenster erstellt wird, wenn die Berechtigungen für die Datei falsch sind. Ich würde es nicht verwenden, wenn das Ziel darin besteht, sensible Daten zu schützen.
Proski
1
Diese Antwort funktioniert soweit es geht, aber @proski ist richtig: Die umaskAntworten sind besser und eine davon sollte akzeptiert werden.
Scott
15

Ich weiß, dass es eine alte Frage ist, aber ich wollte meine zwei Cent hinzufügen.

Ich hatte die gleiche Idee und kam auf eine ähnliche Lösung wie BowlesCR . Das Problem mit seiner Lösung war, dass mein Befehl ( foo) nicht funktionieren würde, wenn ich die Umask vor dem Ausführen ändern würde. Dies ist also meine Einstellung zum Problem:

foo | ( umask 0033; cat >> /tmp/foo.log; )

Hier umaskwirkt sich nur die Umleitung auf foo.login der Subshell aus. Alles andere bleibt unberührt.

Ein bisschen verworren, aber es funktioniert.

xynomorf
quelle
Sehr schön und effektiv :) Kann einfach nicht mit stderr-Umleitung über stdout-Umleitung verwendet werden.
Orsiris de Jong
5

Ohne echtes Scripting können Sie ein bisschen verketten:

touch /tmp/foo.log; chmod 0644 /tmp/foo.log; foo >> /tmp/foo.log

Effektiv ähnlich wie Slowkis Antwort , jedoch zu einem Einzeiler zusammengefasst .

Das einzige andere, woran ich denken kann, ist an der Umask zu basteln. Am besten in einer Subshell, damit die aktuelle Umgebung nicht verschmutzt wird:

(umask 0033 && foo >> /tmp/foo.log)

Zwei Probleme damit.

  1. Umask kann die Berechtigungen nicht über die im creat()Systemaufruf angegebene Stufe erhöhen (0666 scheint das zu sein, was Bash verwendet).
  2. Dadurch werden die Berechtigungen nicht auf einer Datei ändern (weil umasknur Datei gilt Schöpfung ).
BowlesCR
quelle
Ich bin noch neu genug, um zu wissen, dass die Umask für mich immer noch ein bisschen magisch ist. Vielen Dank für den Tipp, ich werde es sicher nachlesen.
Patrick M
Hmm… Erlaubt einem nicht privilegierten Prozess weiterhin, die Datei zu öffnen und später ihren Inhalt zu lesen.
Feuermurmel
(1) Herzlichen Glückwunsch zum Finden einer interessanten, nützlichen Verwendung von cat. (Obwohl dies nicht dem Standardmuster nutzloser Verwendungen von folgt  cat.) (2) Ich nehme an, Sie wollten damit sagen, dass bash beim Erstellen von Dateien standardmäßig den Modus  0666 verwendet, und deshalb habe ich Ihre Antwort bearbeitet, um dies zu sagen. (Siehe das ,  das   … (Fortsetzung)
Scott
(Fortsetzung)… und  dies .) In der Frage wird speziell der Modus 0644 erwähnt. umaskIn diesem Zusammenhang würde also auch ein Wert von 22, 23 oder 32 funktionieren (Sie müssen keine führenden Nullen verwenden ; wann) Modi und  umaskWerte werden numerisch angegeben, sie werden immer als oktal interpretiert.  22 wird üblicherweise herkömmlich verwendet.
Scott
@Feuermurmel: Na und? Die Frage fordert ausdrücklich den Modus 644. Wir müssen davon ausgehen, dass das OP weiß, dass 644 weltlesbar bedeutet und seine Informationen veröffentlichen soll.
Scott
1

Wenn die Umleitung die falschen Berechtigungen festlegt, z.

$ rm capture.*
$ perl -e 'print STDERR "$$ STDERR\n"; print STDOUT "$$ STDOUT\n"' \
                            >> capture.STDOUT 2>> capture.STDERR
$ perl -e 'print STDERR "$$ STDERR\n"; print STDOUT "$$ STDOUT\n"' \
                            >> capture.STDOUT 2>> capture.STDERR
$ ls -l capture.*
-rw-rw-rw- 1 jcookinf jcookinf 22 Jun 12 10:38 capture.STDERR
-rw-rw-rw- 1 jcookinf jcookinf 22 Jun 12 10:38 capture.STDOUT
$ cat capture.*
215 STDERR
216 STDERR
215 STDOUT
216 STDOUT

Ich glaube, Sie können etwas verwenden, wie es xynomorf gegeben hat, und die Bedenken von Orsiris de Jong mit einer geringfügigen Änderung ansprechen, um die Bash-Prozess-Substitution zu verwenden .

$ rm capture.*
$ perl -e 'print STDERR "$$ STDERR text\n"; print STDOUT "$$ STDOUT text\n"' \
            > >(umask 0033; cat >> capture.STDOUT) 2> >(umask 0033; cat >> capture.STDERR)
$ perl -e 'print STDERR "$$ STDERR text\n"; print STDOUT "$$ STDOUT text\n"' \
            > >(umask 0033; cat >> capture.STDOUT) 2> >(umask 0033; cat >> capture.STDERR)
$ ls -l capture.*
-rw-r--r-- 1 jcookinf jcookinf 32 Jun 12 10:43 capture.STDERR
-rw-r--r-- 1 jcookinf jcookinf 32 Jun 12 10:43 capture.STDOUT
$ cat capture.*
233 STDERR text
238 STDERR text
233 STDOUT text
238 STDOUT text

Verwenden Sie diese Option, umask 0077um den Modus abzurufen 600 und anderen Benutzern das Anzeigen des Inhalts zu untersagen.

piCookie
quelle
0

Wenn Sie im Gegensatz umaskzur Prozessersetzung zu einem Skript umleiten möchten, installkönnen Sie auch das Ausführungsbit setzen:

install -m 755 <(echo commands go here) newscript

<()Platziert die Ausgabe in einer temporären Datei, siehe Prozessersetzung

Laktak
quelle