Uso de xargs junto con bash -c para crear comandos complejos

Shutterstock / ksb

xargs son fuegos artificiales para comandos de shell. Cualquier salida, generada por cualquier comando de shell, puede enviarse a xargs para su posterior procesamiento en otra línea de comando. ¡Aprenda a aprovechar este gran poder de los xargs hoy mismo!

Índice de contenidos
  1. Introducción a xargs
  2. Tubos y xarg
  3. Bienvenido a xargs con bash -c
  4. Terminando

Introducción a xargs

Mi colega Dave McKay escribió un artículo interesante Cómo usar el comando xargs en Linux, que es posible que desee leer primero para obtener una introducción detallada y una exploración de los xargs en general.

Este artículo se centrará en un problema específico: qué hacer cuando encuentre limitaciones del apilamiento normal o basado en tuberías tradicionales (; delimitado) apilamiento de comandos de Linux, e incluso cuando se usa xargs no parece dar una respuesta de inmediato?

Esto sucede con regularidad, si no con frecuencia, al escribir scripts de una línea en la línea de comando y / o al procesar datos complejos o estructuras de datos. La información que se presenta aquí se basa en investigaciones y muchos años de experiencia utilizando este método y enfoque en particular.

Tubos y xarg

Cualquiera que aprenda Bash crecerá en sus habilidades de scripting de línea de comandos con el tiempo. Lo mejor de Bash es que todas las habilidades aprendidas desde la línea de comandos se traducen fácilmente en scripts de Bash (que generalmente están marcados con un .sh sufijo). La sintaxis es tan buena como idéntica.

Y, a medida que mejoran las habilidades, los nuevos ingenieros suelen descubrir primero el lenguaje Pipe. Usar una manguera es fácil y sencillo: la salida del comando anterior se 'canaliza' a la entrada para el siguiente comando Piense en ello como una tubería de agua que lleva agua desde una fuente de salida a una fuente de entrada en otro lugar, como ejemplo el agua de una presa conectada a una turbina de agua.

Echemos un vistazo a un ejemplo sencillo:

echo 'a' | sed 's/a/b/'

Un ejemplo simple de una tubería Bash con reemplazo de texto regex sed

Aquí simplemente repetimos "a" y luego cambiamos lo mismo usando el editor de flujo de texto es. La salida es, por supuesto, "b": el sed reemplazó (comando s) "a" con "b".

Algún tiempo después, el ingeniero se dará cuenta de que los tubos todavía tienen capacidades limitadas, especialmente cuando desea preprocesar los datos en un formato listo para el siguiente instrumento. Por ejemplo, considere esta situación:

Enfréntate a los desafíos usando una tubería en combinación con kill

Aquí comenzamos un sueño de fondo. A continuación usamos pidof para recuperar el PID del comando de suspensión en ejecución e intentar eliminarlo con kill -9 (Piense en -9 como una forma destructiva de matar un proceso). Falla. Así que intentamos usar el PID proporcionado por el shell cuando iniciamos el proceso en segundo plano, pero de manera similar falla.

El problema es ese kill no acepta la entrada directamente, independientemente de si proviene de ps o incluso de un simple echo. Para resolver este problema, podemos usar xargs para obtener la salida de ambos archivos ps o el echo comando) y proporcionarlos como entrada kill, convirtiéndolos en argumentos para el comando kill. Por tanto, es como si hubiéramos ejecutado kill -9 some_pid directamente. Vamos a ver cómo funciona:

sleep 300 &
pidof sleep | xargs kill -9

xargs resuelve el problema con el comando pipe kill visto arriba

Funciona perfectamente y consigue lo que nos propusimos: acabar con el proceso de sueño. Un pequeño cambio en el código (es decir, simplemente agregue xargs delante del comando), ¡pero un gran cambio en la utilidad Bash para el ingeniero desarrollador!

También podemos utilizar el -I opción (que define el argumento de cadena sustituto) a kill para aclarar un poco la forma en que pasamos los argumentos para matar: i12b Aquí definimos {} como nuestra cadena de reemplazo. En otras palabras, siempre que xargs vea {}, reemplazará {} a cualquier entrada recibida por el último comando.

Sin embargo, esto también tiene sus limitaciones. ¿Qué pasaría si quisiéramos proporcionar información de depuración agradable impresa en línea y desde la instrucción? Hasta ahora parece imposible.

Sí, podríamos procesar posteriormente la salida con un archivo sed regex o inserte una subcapa ($()) en algún lugar, pero todos estos todavía parecen tener limitaciones, especialmente cuando llega el momento de crear flujos de datos complejos, sin usar un nuevo comando y sin usar archivos temporales intermedios.

¿Y si pudiéramos, de una vez por todas, dejar atrás estos límites y ser 100% libres de crear lo que sea ¿Nos gusta la línea de comandos de Bash, usando solo tuberías, xargs y el shell Bash, sin archivos temporales intermedios y sin iniciar un nuevo comando? Es posible.

Y no es nada complejo si alguien te lo muestra, pero la primera vez tomó algo de tiempo y discusión para resolverlo. En particular, me gustaría agradecer y agradecer a mi mentor y colega anterior de Linux, Andrew Dalgleish: juntos descubrimos cómo hacerlo mejor hace poco menos de 10 años.

Bienvenido a xargs con bash -c

Como hemos visto, incluso cuando se utilizan tuberías junto con xargs, todavía existen limitaciones para la creación de scripts en el nivel de ingeniero senior. Tomemos nuestro ejemplo anterior y agreguemos información de depuración sin procesar el resultado. Normalmente esto sería difícil de lograr, pero no así con xargs combinado con bash -c:

sleep 300 &
pidof sleep | xargs -I{} echo "echo 'The PID of your sleep process was: {}'; kill -9 {}; echo 'PID {} has now been terminated'" | xargs -I{} bash -c "{}"

Una secuencia de compilación compleja de comandos xargs y el uso de bash -c

Aquí hemos usado dos xargs comandos. El primero crea una línea de comando personalizada, utilizando la salida del comando anterior en la tubería como entrada (siendo pidof sleep) y el segundo comando xargs ejecuta ese comando generado, personalizado para la entrada (¡importante!).

¿Por qué personalizar por entrada? La razón es que xargs, por defecto, procesará línea por línea a través de su entrada (la salida del comando anterior en la tubería) y hará lo que se le ordene para cada una de esas líneas de entrada.

Aquí hay mucho poder. Esto significa que puede crear y compilar cualquier comando personalizado y luego ejecutarlo, completamente libre del formato en el que se encuentran sus datos de entrada y completamente libre de preocuparse por cómo ejecutarlo. La única sintaxis que debe recordar es esta:

some_command | xargs -I{} echo "echo '...{}...'; more_commands; more_commands_with_or_without{}" | xargs -I{} bash -c "{}"

Tenga en cuenta que el archivo anidado echo (el segundo eco) solo es realmente necesario si desea reproducir el texto real. De lo contrario, si el último echo el primero no estaba echo comenzaría a producir "El PID ...", etc. y el archivo bash -c el subshell no podría analizarlo como un comando (IOW, 'El PID ...' no es un comando y no se puede ejecutar como tal, de ahí el eco secundario / anidado).

Una vez que recuerdes el bash -c, la -I{} y la forma de hacer eco desde dentro de otro eco (y alternativamente podría usar secuencias de escape si es necesario), se encontrará usando esta sintaxis una y otra vez.

Digamos que necesita hacer tres cosas por archivo en el directorio: 1) ver el contenido del archivo, 2) moverlo a un subdirectorio, 3) eliminarlo. Normalmente, esto requeriría una serie de pasos con varios comandos escalonados, y si se vuelve más complejo, es posible que también necesite archivos temporales. Pero es muy facil de usar bash -c es xargs:

echo '1' > a
echo '2' > b
echo '3' > c
mkdir subdir
ls --color=never | grep -v subdir | xargs -I{} echo "cat {}; mv {} subdir; rm subdir/{}" | xargs -I{} bash -c "{}"

Un mini script completamente funcional basado en xargs y bash -c en un comando de una línea

Primero, notar rápidamente que siempre es una buena idea usar --color=never para ls, para evitar problemas en el sistema usando codificación de colores para las salidas de la lista de directorios (habilitado de manera predeterminada en Ubuntu), ya que esto a menudo causa graves problemas de análisis debido a los códigos de color que realmente se envían al terminal y se prefieren a las entradas lista de directorios.

Primero creamos tres archivos, a, byc y un subdirectorio llamado subdir. Excluimos este subdirectorio de la lista de directorios con grep -v después de notar que se ejecuta una prueba rápida (sin ejecutar los comandos, o en otras palabras, sin el segundo xarg), el subdirectorio aún se muestra.

Siempre es importante probar los comandos complejos primero mirando la salida antes de pasarlos a una subcapa de bash con bash -c para la ejecución.

Finalmente, usamos exactamente el mismo método visto arriba para compilar o ordenar; cat (mostrar) el archivo, mover el archivo (indicado por {}) en el subdirectorio y finalmente elimine el archivo dentro del subdirectorio. Vemos que el contenido de los 3 archivos (1, 2, 3) se muestra en la pantalla y si revisamos el directorio actual nuestros archivos se han ido. También podemos ver cómo no hay más archivos en el subdirectorio. Todo funcionó bien.

Terminando

Utilizando xargs ser un gran poder para un usuario avanzado de Linux (y en este caso) Bash. Utilizando xargs en combinación con bash -c todavía trae un poder mucho mayor; la capacidad única de crear líneas de comando 100% complejas y personalizadas, sin la necesidad de archivos intermedios o construcciones, y sin la necesidad de comandos apilados / secuenciados.

¡Disfrutar!

Descubre más contenido

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Información básica sobre protección de datos Ver más

  • Responsable: Nelida Haydee Saldivia.
  • Finalidad:  Moderar los comentarios.
  • Legitimación:  Por consentimiento del interesado.
  • Destinatarios y encargados de tratamiento:  No se ceden o comunican datos a terceros para prestar este servicio. El Titular ha contratado los servicios de alojamiento web a KnownHost que actúa como encargado de tratamiento.
  • Derechos: Acceder, rectificar y suprimir los datos.
  • Información Adicional: Puede consultar la información detallada en la Política de Privacidad.

Subir