Ich habe eine Weile versucht, die Antwort auf diese Frage zu finden. Ich schreibe ein schnelles Skript, um einen Befehl auszuführen, der auf der Ausgabe von awk basiert.
ID_minimum=1000
for f in /etc/passwd;
do
awk -F: -vID=$ID_minimum '$3>=1000 && $1!="nfsnobody" { print "xfs_quota -x -c 'limit bsoft=5g bhard=6g $1' /home "}' $f;
done
Die Probleme sind, dass das -c
Argument einen Befehl in einfachen Anführungszeichen akzeptiert und ich nicht herausfinden kann, wie ich dem richtig entkommen kann und dass $1
dies auch nicht in den Benutzernamen erweitert wird.
Im Wesentlichen versuche ich nur, es zur Ausgabe zu bringen:
xfs_quota -x -c 'limit bsoft=5g bhard=6g userone' /home
xfs_quota -x -c 'limit bsoft=5g bhard=6g usertwo' /home
usw...
awk
Antworten:
Um den Befehl
xfs_quota -x -c 'limit bsoft=5g bhard=6g USER' /home
für jeden Benutzer auszuführen,USER
dessen UID mindestens lautet$ID_minimum
, sollten Sie zuerst diese Benutzer analysieren und dann den Befehl tatsächlich ausführen , anstatt zu versuchen, eine Zeichenfolge zu erstellen, die den Befehl darstellt, den Sie ausführen möchten.Wenn Sie die Befehlszeichenfolge erstellen, müssten Sie sie erstellen
eval
. Das ist fummelig und leicht falsch zu verstehen. Es ist besser, nur eine Liste der Benutzernamen abzurufen und dann den Befehl auszuführen.Beachten Sie, dass für das nachfolgende Argument keine einfachen Anführungszeichen erforderlich sind
-c
. Hier verwende ich doppelte Anführungszeichen, weil ich möchte, dass die Shell die$user
Variable erweitert , die Werte enthält, die von extrahiert wurdenawk
.Ich benutze,
${ID_minimum:-1000}
wenn ich dermin
Variablen imawk
Befehl den Wert gebe . Dies wird auf den Wert von erweitert$ID_minimum
oder darauf,1000
ob diese Variable leer oder nicht festgelegt ist.Wenn Sie wirklich wollten, können Sie die Befehle in der obigen Schleife ausdrucken lassen, anstatt sie auszuführen:
Beachten Sie erneut, dass die Verwendung von doppelten Anführungszeichen in der ausgegebenen Befehlszeichenfolge (anstelle von einfachen Anführungszeichen) eine Shell in keiner Weise verwirren würde, wenn Sie die generierten Befehle mit
eval
oder auf andere Weise ausführen würden . Wenn es Sie stört, tauschen Sie einfach die einfachen und doppelten Anführungszeichen im ersten Argument nachprintf
oben aus.quelle
getent
(auf dem Desktop jedenfalls), und die Frage ist nicht mit "Linux" gekennzeichnet./home
macOS auch nicht wirklich verwendet (es ist da, aber normalerweise leer).Das ist ein bisschen albern, da es wirklich keine Schleife mit nur einem Wert gibt.
Aber das Problem scheint darin zu bestehen, einfache Anführungszeichen von awk zu drucken. Sie können sie in der Shell maskieren, aber Sie können auch Backslash-Escapezeichen innerhalb von awk verwenden, um sie zu drucken. das Zeichen mit Zahlenwert ist OOO (in oktal ), so ist . Das wäre also eine Möglichkeit:
\OOO
\047
'
Sie können das ähnliche Escape-
\x27
Zeichen in hexadezimaler Form verwenden, es kann jedoch in einigen Implementierungen falsch interpretiert werden, wenn das folgende Zeichen eine gültige hexadezimale Ziffer ist. (Und natürlich habe ich ASCII oder einen ASCII-kompatiblen Zeichensatz angenommen, z. B. UTF-8.)quelle
l
es sich nicht um eine hexadezimale Ziffer handelt, sondern"\x27df\n"
wie"\x27" "df"
in der Busybox awk oder mawk behandelt wird, sondern als"\xdf"
(0x27df
in 8-Bit- Zeichen umgewandelt ) in der ursprünglichen awk und gawk (dies ist der Grund, warum POSIX dies nicht angibt\xHH
). Octals (\047
) haben nicht das gleiche Problem und sind POSIX. Dies setzt in jedem Fall ein ASCII-System voraus (heutzutage eine vernünftige Annahme).Verwenden Sie die
-f -
Option to awk, um das Skript von stdin und einem Here-Dokument zu übernehmen:quelle
Das hat es geschafft.
quelle
'\''
oder'"'"'
. Beide arbeiten, beide sehen nervig aus.Es ist ein schrecklicher Trottel, aber es ist schnell und einfach ...
quelle
Dies scheint mir eine ideale Gelegenheit zu sein, Sie zu beschäftigen
xargs
(oder GNU Parallel ):Der Vorteil der Verwendung von
xargs
oderparallel
besteht darin, dass Sie den Befehl einfach entfernenecho
können , wenn Sie bereit sind, den Befehl tatsächlich auszuführen (ggf. durch ihn zu ersetzensudo
, falls erforderlich).Sie können auch diese Dienstprogramme verwenden
-p
/--interactive
(letzteres ist GNU-only) oder--dry-run
(parallel
nur) Optionen, die Bestätigung zu erhalten , bevor jedes laufen, oder einfach nur , um zu sehen , was würde laufen, bevor Sie es ausführen.Die oben verwendete allgemeine Methode sollte unter den meisten Unixen funktionieren und erfordert keine GNU-spezifischen
xargs
Optionen. Die doppelten Anführungszeichen tun Notwendigkeit, „entkommen“ , so dass sie buchstäblich in der Ausgabe erscheinen. Beachten Sie, dass die "Ersatzzeichenfolge"{}
inxargs -I{}
beliebig sein kann und-I
impliziert-L1
(führen Sie einen Befehl pro Eingabezeile aus, anstatt sie zu stapeln).GNU Parallel nicht die benötigen
-I
Option ({}
ist der Standardersatzzeichenfolge), und gibt Ihnen den sofortigen Bonus viele Jobs parallel laufen, auch wenn Sie wollen über nicht die Mühe zu lernen jeder von seinen anderen Funktionen .Nebenbei bemerkt, ich bin mir nicht einmal sicher, ob
xfs_quota
die-c
Option so verwendet werden soll, obwohl ich keine XFS-Dateisysteme zum Testen zur Hand habe. Sie haben nicht einmal nötig mit einer Zeichenfolge in Anführungszeichen in erster Linie zu tun (es sei denn , Sie Benutzernamen mit Leerzeichen in ihnen erwarten, was ich kann erraten), da es so aussieht , mehrere geben kann-c
Optionen auf der gleichen Befehlszeile nach auf die Manpage mitxfsprogs
4.5.something.quelle
Mit GNU Parallel können Sie Folgendes tun:
Erläuterung:
--colsep :
Split auf:-q
Sie spalten den Befehl nicht auf Räume (halten die ‚...‘ als einzelne Zeichenfolge){=1 ... =}
werten diese Perl - Ausdruck auf dem ersten Argument der Linie$_ eq "nfsnobody" and skip();
Wenn der Wert == nfsnobody: überspringen$arg[3] <= 1000 and skip();
Wenn Argument3 <= 1000: überspringenquelle