Ayer estuve ayudando a una compañera a desarrollar un pequeño script que hiciera algo útil para administración de sistemas Linux. Las condiciones que se ponían era que tenía que usar awk con getline y system. Puesto que nunca hasta ese momento usé tales cosas, me pareció interesante. Hoy voy a comentar aquí, para todos aquellos a los que le haga falta lo que se hizo.
El script que nos propusimos hacer
Pepe (Doval) y yo era algo muy simple:
Contar la cantidad de ficheros que cada usuario del sistema tenía en una carpeta. Dicha carpeta era introducida como parámetro al script. A priori algo muy sencillo que se podría escribir en
bash de manera muy simple.
for i in `awk 'BEGIN{FS=":"} {print $1}' /etc/passwd`
do
echo -n -e "user: $i.\tFicheros: "
find $1 -type f -user $i | wc -l
done
El detalle es que así no cumplíamos los requisitos propuestos, que no eran otros que usar las funciones getline y system. Comenzamos por lo tanto a intentar crear un script que lo hiciese. La primera aproximación fue la siguiente:
#/bin/bash
awk -v raiz=$1 'BEGIN { FS=":"
if(system("test -d "raiz)!=0)
print ("No existe el directorio");
else
{
while (getline < "/etc/passwd" != 0)
{
system( "find "raiz" -user "$1" | wc -l" | getline aa
print "El usuario " $1 " tiene "aa" ficheros en " raiz;
}
}
}'
Puesto que el comando find sí se podía usar, lo aprovechamos (flag -user) y con ello hacemos lo que se nos pide de forma muy sencilla. El problema de esta solución es que la línea del segundo system, la que realiza el find, no funciona, puesto que el paso de parámetros así en awk no es válido.
La solución final por que se se optó no fue otra que hacer el script directamente en
awk. Así evitaríamos el paso intermedio de enlace entre
bash y awk. Desde luego, una solución más limpia.
El resultado final, tendría por ejemplo el siguiente aspecto:
BEGIN { FS=":"
print "Introduce el directorio a evaluar"
getline dir < "-"
if(system("test -d "dir) != 0)
print ("No existe el directorio");
else
{
while ((getline < "/etc/passwd") != 0)
{
cmd = sprintf("find %s -type f -user %s | wc -l",dir,$1);
cmd | getline line
if(line != 0)
print "El usuario "$1" tiene "line" ficheros en "dir"."
}
}
}
Acepto que no es eficiente ni queda bonito el código, pero hace lo que tiene que hacer. Un ejemplo de salida:
shell> awk -f prueba.awk
Introduce el directorio a evaluar
/home
El usuario javier tiene 8297 ficheros en /home.
El usuario user tiene 7949 ficheros en /home.
El usuario root tiene 3 ficheros en /home.
El usuario www-data tiene 4 ficheros en /home.
Leer más