
Ich habe ein Problem auf einem Linux-Betriebssystem, auf dem eine Version von SMB ausgeführt wird. Wenn der absolute Pfad zu einem Verzeichnis in einem freigegebenen Ordner lautetgrößer als 1024 Bytes und die Dateinamenkomponente größer als 256 Bytesder SMB-Dienst stürzt ab und sperrt alle anderen Dienste für den Netzwerkzugriff wie SSH und FTP, wodurch die Maschine stummgeschaltet wird.
Um Systemabstürze zu verhindern, habe ich eine Gruppe von Ordnern, bei denen ich vermute, dass der Problempfad außerhalb des freigegebenen Ordners liegt, vorübergehend verschoben. Ich muss die Datei und den Dateipfad finden, die diese Beschränkung überschritten haben, und sie umbenennen oder entfernen, damit ich einen Großteil der Dateien in den freigegebenen Ordner zurückversetzen kann.
Ich habe versucht,findenUndgrepBefehle ohne Erfolg. Gibt es eine Befehlskette oder ein Skript, mit dem ich die fehlerhaften Dateien und Verzeichnisse aufspüren kann?
Bitte beraten.
Antwort1
Dies ist in Bash geschrieben und verwendet spezifische Funktionen (aber ähnliche Funktionen sind in anderen Shells verfügbar). Es ist so konzipiert, dass es von einem übergeordneten Verzeichnis aus ausgeführt werden kann, das für alle Dateien und Verzeichnisse, an denen Sie interessiert sind, gemeinsam ist. Es berücksichtigt die Länge des Pfads von /
dort und addiert sie zur Länge jedes ausgewerteten Pfads. Wenn Sie das nicht tun möchten, verwenden Sie einfach lenpwd=0
anstelle von lenpwd=${#PWD}
. Es funktioniert, wenn es Dateien mit Leerzeichen in ihren Namen gibt, aber nicht solche mit Zeilenumbrüchen (die sowieso verbannt werden sollten). Es druckt die Längen und Dateispezifikationen aller gefundenen Dateien, die die Kriterien erfüllen.
lenpwd=${#PWD}; find | while read -r path; do file=${path##*/}; if (( ${#path} + lenpwd > 1024 || ${#file} > 256 )); then echo "$((${#path} + lenpwd)) ${#file} $path"; fi; done
Antwort2
Weiß nicht, ob ich dich richtig verstehe, aber erster Versuch:
for f in $( find /srv/smb -type f )
do
fname=$( basename "$f" )
pname=$( dirname "$f" )
l_fname=$( echo "$fname" | wc -c )
l_pname=$( echo "$pname" | wc -c )
if [ $l_fname -gt 256 ] ; then
# do somthing with $f when filename > 256b
rm -- "$f"
continue
fi
if [ $l_pname -gt 1024 ] ; then
# do something if path > 1024
echo "$f much too long!"
fi
done
Dies ist nur ein „Ich habe es nicht getestet, aber es sollte in Bash und einem Equlas-Shell-Skript funktionieren“. Fügen Sie gerne Fehlerprüfungen und andere nützliche Dinge hinzu ...
Antwort3
Hier ist ein Einzeiler, der die Länge des Verzeichnisnamens, dann die Länge des Basisnamens, dann den Verzeichnisnamen und zuletzt den Basisnamen (für die Nachwelt) ausgibt. Ich habe gerade das aktuelle Arbeitsverzeichnis verwendet, aber das kann geändert werden. Dies kann auch erweitert werden, um die Werte herauszuziehen, die größer sind als Ihre Angaben.
find `pwd` -exec dirname '{}' \; -exec basename '{}' \;
| awk '( NR%2 != 0){printf("%s ",$0);next}1 '
| awk '{print length($1)" "length($2)" "$1$2}'
Aktualisieren:
Um nach der Verzeichnisnamenlänge zu sortieren, fügen Sie am Ende Folgendes hinzu:
| sort -nr
Um nach der Länge des Basisnamens zu sortieren, fügen Sie Folgendes am Ende hinzu:
| sort -nr -k2
Aktualisierung 2:
Gemäß dem Kommentar des Autors werden dadurch Leerzeichen in +-Zeichen geändert, wodurch die Zählungen anschließend funktionieren.
find `pwd` -exec dirname '{}' \; -exec basename '{}' \;
| tr '[:blank:]' '+'
| awk '( NR%2 != 0){printf("%s ",$0);next}1 '
| awk '{print length($1)" "length($2)" "$1$2}'