Durch die Inplace-Bearbeitung wird der Gruppenbesitz der Datei geändert

8

Ich habe ein shell ( php) Skript, das auf folgende Weise mit der Zieldatei in Kontakt kommt:

  • prüft, ob Datei und Verzeichnis mit php's beschreibbar sind is_writable()(ich glaube nicht, dass dies ein Problem ist)
  • Bearbeitet die Datei vor Ort mit dem folgenden sedBefehl:

grep -q "$search" "$passwd_file" && { sed -i "s|$search|$replace|" "$passwd_file"; printf "Password changed!\n"; } || printf "Password not changed!\n"

Als Ergebnis bekomme ich (alles andere richtig als) Datei, die sein myuser:www-datasollte myuser:myuser.

Ändert sedsich der Besitz einer Dateigruppe wie es scheint und wie vermeide ich ihn, wenn möglich?

Miloš Đakonović
quelle

Antworten:

16

Es gibt ein kleines Problem mit seddem Inplace-Bearbeitungsmodus -i. sedErstellt eine temporäre Datei im selben Verzeichnis namens sedy08qMA, wobei y08qMAes sich um eine zufällig generierte Zeichenfolge handelt. Diese Datei wird mit dem geänderten Inhalt der Originaldatei gefüllt. sedEntfernt nach dem Vorgang die Originaldatei und benennt die temporäre Datei mit dem Originaldateinamen um. Es ist also keine echte Inplace-Bearbeitung . Es wird eine neue Datei mit Berechtigungen des anrufenden Benutzers und einer neuen Inode-Nummer erstellt. Dieses Verhalten ist meistens nicht schlecht, aber zum Beispiel werden harte Links unterbrochen.

Wenn Sie jedoch eine echte Inplace-Bearbeitung wünschen, sollten Sie diese verwenden ed. Es liest Befehle aus dem Standard und bearbeitet die Datei direkt ohne temporäre Datei (dies erfolgt über edden Speicherpuffer). Es ist üblich printf, die Befehlsliste zu erstellen:

printf "%s\n" '1,$s/search/replace/g' wq | ed -s file

Der printfBefehl erzeugt die folgende Ausgabe:

1,$s/search/replace/g
wq

Diese beiden Zeilen sind edBefehle. Der erste sucht nach der Zeichenfolge searchund ersetzt sie durch replace. Der zweite schreibt ( w) die Änderungen an der Datei und beendet ( q). -sunterdrückt die Diagnoseausgabe.

Chaos
quelle
8

Der -iParameter von sedfunktioniert, indem während des Betriebs eine temporäre Datei erstellt und am Ende die eigentliche Datei mit der temporären Datei überschrieben wird. Dies ist höchstwahrscheinlich die Ursache des Problems, da beim Erstellen der temporären Datei standardmäßig der Besitz der Datei verwendet wirdmyuser:myuser

Sie können das setgidBit im übergeordneten Verzeichnis festlegen (nur wenn das übergeordnete Verzeichnis der Gruppe gehört www-data), sodass Dateien, die unter diesem Verzeichnis erstellt wurden, dieselbe Gruppe erben.
das zu tun:

chmod g+s parent-dir-of-your-file  

Ich denke, dies ist eine sehr typische Verwendung des setgidBits.

David Dai
quelle
@cuonglm Ich habe gerade eine Strace gemacht sed -i, habe die folgende Zeile in der Ablaufverfolgung gefunden. Bedeutet das , dass die temporäre Datei im aktuellen Verzeichnis erstellt wurde? open("./sedKyG9Ei", O_RDWR|O_CREAT|O_EXCL, 0600) = 4
David Dai
@ DavidDai: Ja, mein falsches Gedächtnis.
Cuonglm
2

Die Verwendung von edstatt sederscheint hierfür eher überflüssig, da Sie eine zusätzliche Eingabe eingeben müssen. Die Distribution, an der ich gerade arbeite (CentOS 5.10), hat die -cOption, seddass die temporäre Datei "kopiert" wird, anstatt sie einfach umzubenennen, wenn sie mit der -iOption verwendet wird. Ich habe es getestet und es hat perfekt funktioniert, wobei der ursprüngliche Besitzer und die ursprüngliche Gruppe bei einer Inline-Bearbeitung erhalten blieben. Die Änderungszeit bleibt NICHT erhalten.

z.B, sed -ci -e '3,5d' file.txt

  • -c verwendet Kopie anstelle von Umbenennen (dh behält das Eigentum / die Gruppe bei)
  • -i Inline-Bearbeitung
  • -e Skript / Ausdruck ausgeführt werden

Ich sedbin mir nicht sicher, wie weit verbreitet diese Option in anderen Distributionen ist. Solaris 10 hatte es nicht, aber Solaris hat nicht viele Dinge, die ich will.

d3vnulldroid
quelle
Klingt ziemlich praktisch. Nicht in Ubuntu 14.04, FWIW. :-(
John Rix