He estado tratando de encontrar la respuesta a esta pregunta por un tiempo. Estoy escribiendo un script rápido para ejecutar un comando basado en la salida de awk.
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
Los problemas son que el -c
argumento toma un comando entre comillas simples y no puedo encontrar la manera de escapar de eso y eso $1
no se expande al nombre de usuario.
Esencialmente solo estoy tratando de que salga:
xfs_quota -x -c 'limit bsoft=5g bhard=6g userone' /home
xfs_quota -x -c 'limit bsoft=5g bhard=6g usertwo' /home
etc ...
awk
Respuestas:
Para ejecutar el comando
xfs_quota -x -c 'limit bsoft=5g bhard=6g USER' /home
para cada unoUSER
cuyo UID es al menos$ID_minimum
, considere analizar primero a esos usuarios y luego realmente ejecutar el comando, en lugar de intentar crear una cadena que represente el comando que desea ejecutar.Si crea la cadena de comando, debería
eval
hacerlo. Esto es complicado y fácil de equivocarse. Es mejor obtener una lista de nombres de usuario y luego ejecutar el comando.Tenga en cuenta que no hay necesidad real de comillas simples alrededor del argumento posterior
-c
. Aquí uso comillas dobles porque quiero que el shell expanda el$user
variable que contiene los valores extraídos porawk
.Lo uso
${ID_minimum:-1000}
cuando le doy el valor a lamin
variable en elawk
comando. Esto se expandirá al valor de$ID_minimum
, o a1000
si esa variable está vacía o no está establecida.Si realmente quisiera, podría hacer que el bucle anterior imprima los comandos en lugar de ejecutarlos:
Tenga en cuenta nuevamente que el uso de comillas dobles en la cadena de comando que se genera (en lugar de comillas simples) no confundiría a un shell de ninguna manera si tuviera que ejecutar los comandos generados utilizando
eval
o por algún otro medio. Si te molesta, solo cambia las comillas simples y dobles en el primer argumentoprintf
anterior.fuente
getent
(en el escritorio, de todos modos), y la pregunta no está etiquetada como "Linux"./home
no se usa realmente en macOS (está allí, pero generalmente está vacío).Esto es un poco tonto ya que realmente no hay bucle con un solo valor.
Pero el problema parece estar imprimiendo comillas simples de awk. Podrías escapar de ellos en el caparazón, pero también podrías usar la barra invertida dentro de awk para imprimirlos. es el carácter con valor numérico OOO (en octal ), también lo es . Entonces esta sería una forma de hacerlo:
\OOO
\047
'
Podría usar el escape similar en hexadecimal,
\x27
pero puede malinterpretarse en algunas implementaciones si el siguiente carácter es un dígito hexadecimal válido. (Y, por supuesto, asumí ASCII o un conjunto de caracteres compatible con ASCII, por ejemplo, UTF-8).fuente
l
que no es un dígito hexadecimal, pero se"\x27df\n"
trataría como"\x27" "df"
en busybox awk o mawk, pero como"\xdf"
( conversión0x27df
a char de 8 bits) en el awk y gawk original (esa es la razón por la cual POSIX no especifica\xHH
). Los Octals (\047
) no tienen el mismo problema y son POSIX. En cualquier caso, eso supone un sistema ASCII (una suposición razonable en estos días).Use la
-f -
opción awk para tomar el script de stdin y un documento aquí:fuente
Esto lo hizo.
fuente
'\''
o no'"'"'
. Ambos funcionan, ambos parecen molestos.Es un cuerpo horrible, pero es rápido y fácil ...
fuente
Esto me parece una oportunidad ideal para emplear algunos
xargs
(o GNU Paralelo ):La ventaja de usar
xargs
oparallel
es que simplemente puede eliminar elecho
cuando esté listo para ejecutar el comando de verdad (posiblemente reemplazándolo consudo
, si es necesario).También puede usar las opciones de estas utilidades
-p
/--interactive
(esta última es solo GNU) o--dry-run
(parallel
solo), para obtener confirmación antes de ejecutar cada una, o simplemente para ver qué se ejecutaría, antes de ejecutarla.El método general utilizado anteriormente debería funcionar en la mayoría de los Unix, y no requiere
xargs
opciones específicas de GNU . Las comillas dobles hacen necesidad de ser "escaparon" de modo que aparezcan literalmente en la salida. Tenga en cuenta que la "cadena de reemplazo"{}
, enxargs -I{}
puede ser cualquier cosa que prefiera, y-I
implica-L1
(ejecutar un comando por línea de entrada en lugar de procesamiento por lotes para arriba).Paralelo GNU no requiere la
-I
opción ({}
es la cadena de sustitución por defecto), y le da el bono instantáneo de funcionamiento de muchos puestos de trabajo en paralelo, incluso si usted no quiere molestarse en aprender acerca de cualquier de sus otras características .Como nota al margen, ni siquiera estoy seguro de si
xfs_quota
's-c
se supone posibilidad de ser usada como este, aunque no tengo ni sistemas de archivos XFS útil para la prueba. Es posible que ni siquiera haya necesitado lidiar con una cadena entre comillas en primer lugar (a menos que espere nombres de usuario con espacios en blanco, lo que supongo que es posible), ya que parece que puede dar múltiples-c
opciones en la misma línea de comando, de acuerdo con a la página de manual incluida conxfsprogs
4.5.algo.fuente
Con GNU Parallel puedes hacer:
Explicación:
--colsep :
Dividir en:-q
no divida el comando en espacios (mantenga el '...' como una sola cadena){=1 ... =}
Evalúe esta expresión perl en el primer argumento de la línea$_ eq "nfsnobody" and skip();
Si el valor == nfsnobody: omita$arg[3] <= 1000 and skip();
If argumento3 <= 1000: omitafuente