Was ist der Grund, warum "rm -rf a / b" sagt "a / b ist nicht leer"?

7

Das folgende Skript gibt mir manchmal Dinge wiecan't remove a/b as it's not empty

ssh -T user@host <<EOF
  cd somewhere
  rm -rf a/b    
EOF

Aber ich melde mich beim Server an und führe aus, rm -rf a/bdann hatte ich nie das Problem.

Es gibt andere Prozesse, für die Dateien generiert werden. Ist a/bdas verwandt?

Wie kann man ein Skript erstellen, das sicherstellt, dass "a / b" gelöscht wird?

Cheng
quelle
1
Das ist lustig, rm -rfsollte immer gelingen, ohne Erlaubnisprobleme. Bitten Sie das Skript, die Debugging-Ausgabe zu drucken, wenn das Entfernen fehlschlägt. ls -laR a/bsollte ausreichen.
Faheem Mitha

Antworten:

7

rmdir(2)schlägt fehl, wenn das Verzeichnis nicht leer ist. Wenn ein anderer Prozess Dateien erstellt, während rm(1)er sie entfernt, weiß er nicht, ob er sie löschen soll. Wenn es daher an der Zeit ist, rm(1)zu versuchen, das zu löschen, was seiner Meinung nach ein leeres Verzeichnis sein sollte, schlägt dies mit dem von Ihnen veröffentlichten Fehler fehl.

Eine Möglichkeit, das Verzeichnis angesichts gleichzeitiger Dateierstellungen im Verzeichnis zu löschen, besteht darin, es umzubenennen:

mv a a~
rm -rf a~

Es ist möglich, dass dies nicht funktioniert, wenn die Prozesse, in denen die Dateien erstellt a/bwerden, dies nicht nach Pfad ( open(2)vs. openat(2)) tun .

Ich gehe davon aus, dass die Prozesse, in denen Dateien erstellt a/bwerden, dieses Verzeichnis neu erstellen, wenn es nicht vorhanden ist, oder Fehler ordnungsgemäß behandeln, wenn es nicht vorhanden ist. Da Sie bereits versuchen, das Verzeichnis unter anderen Prozessen zu löschen, scheint dies eine sichere Annahme zu sein.

camh
quelle
danke, glusterfs heilt das Verzeichnis und kann es nicht normal durch einen Fehler in glusterfs heilen, also mv ein Verzeichnis mit einem anderen Namen und rm repariert es.
Waza123
15

Es gibt andere Prozesse, die Dateien für a / b generieren. Ist das verwandt?

Sehr wahrscheinlich. Möglicherweise werden rm -rfzuerst alle Dateien und dann alle Verzeichnisse entfernt. Unter der Haube schlägt der rmdirSystemaufruf zum Entfernen eines Verzeichnisses fehl, wenn das Verzeichnis nicht leer ist. Möglicherweise läuft eine Race-Bedingung, bei der rm -rfüberprüft wird, ob das Verzeichnis leer ist und ob es leer ist. Ein anderer Prozess erstellt dann eine neue Datei. rm -rfruft schließlich auf rmdir, aber ein anderer Prozess erstellt vorher eine Datei.

Faheems Rat ist gut: Setzen Sie einen lsin Ihren Fehlerzustand

ssh -T user@host <<EOF
  cd somewhere
  rm -rf a/b || ( ls -a a/b && exit 1 )
EOF
jmtd
quelle
Sehr interessant.
Boehj
Der Fehler &&sollte ;oder lswird das Beenden des Skripts verhindern.
R .. GitHub STOP HELPING ICE
Ja. lszeigt an, dass sich in diesem Verzeichnis neue Dateien befinden. Ich werde die mvLösung ausprobieren.
Cheng
@R, das stimmt nicht. Wenn dies lsfehlschlägt, gibt die Subshell den Fehlercode zurück ls. Das ' && exit 1' ist erforderlich, um sicherzustellen, dass die Sub-Shell bei ls Erfolg weiterhin einen Fehlercode zurückgibt. Wenn Sie '||' ersetzen, maskieren Sie den wahren Fehlercode für ls.
Jmtd
0

Bei sehr hohen Race-Bedingungen: Der nächste Befehl entfernt veraltete Dateien und dann leere Verzeichnisse:

find /somedir -type f -atime +3 -print0 | xargs -0 --no-run-if-empty rm -f; find /somedir -mindepth 1 -type d -empty -not -name "*.empty" -print0 | xargs -0 --no-run-if-empty -I{} mv {} {}.empty; sleep 30; find /somedir -type d -name '*.empty' -print0 | xargs -0 --no-run-if-empty rm -rf

Oder Schritt für Schritt:

find /somedir -type f -atime +3 -print0 | xargs -0 --no-run-if-empty rm -f;
find /somedir -mindepth 1 -type d -empty -not -name "*.empty" -print0 | xargs -0 --no-run-if-empty -I{} mv {} {}.empty;
sleep 30;
find /somedir -type d -name '*.empty' -print0 | xargs -0 --no-run-if-empty rm -rf;

Schlaf 30 ist für alle Prozesse erforderlich, um das Schreiben in das Entfernungsverzeichnis zu beenden.

WARNUNG: Sie können Ihre neuen Daten verlieren (in meinem Fall handelt es sich um einen Cache, es ist mir also egal).

MingalevME
quelle