[Tutorial] Linux avanzado: Piping (Tuberías)

Moderadores: Kravenbcn, largeroliker, fidelcastro, cerealkiller, pspCaracas, dark_sasuke, m0skit0, LnD, ka69, zacky06

Responder
Avatar de Usuario
m0skit0
Administrador
Administrador
Mensajes: 5585
Registrado: 03 Sep 2009, 09:35
Ubicación: 0xdeadbeef

[Tutorial] Linux avanzado: Piping (Tuberías)

Mensaje por m0skit0 »

En Linux y casi todos los sistemas operativos (incluido Windows), saber manejar bien la consola es fundamental. Ningún usuario puede considerarse avanzado si no conoce las posibilidades que brinda la consola y sobre todo cómo usarlas y combinarlas. Hay veces (muchas) en que la consola brinda una potencia y una automatización de tareas que la interfaz gráfica sólo puede soñar. Queda mucho para que la interfaz gráfica tenga la potencia de la consola.

La filosofía UNIX trata de presentar herramientas con una funcionalidad específica y reducida. Esto permite múltiples combinaciones de dichas herramientas para realizar asuntos complicados. Una forma de combinar las herramientas que nos proporciona UNIX es usando pipes (tuberías). El concepto es el mismo que las tuberías en programación POSIX para comunicar procesos (para los que ya conozcan este tema).

Una tubería normalmente se representa con el carácter | (AltGr-1 en teclado español, código ASCII 124). La tubería permite pasar la salida de un proceso a otro proceso que la toma como entrada. Veamos algún ejemplo.

La herramienta grep es un pilar de cualquier sistema *IX. Permite filtrar los resultados. Para ilustrar su utilidad, creemos un fichero de texto con el siguiente contenido:

Código: Seleccionar todo

Alfonso
Raquel
Pepe
Epifanio
Fidedigno
Obsoleto

y lo guardamos como prueba. Ahora supongamos que sólo queremos listar los nombres que contengan la letra 'o'.

m0skit0@sodiet:~/Temp$ cat prueba
Alfonso
Raquel
Pepe
Epifanio
Fidedigno
Obsoleto
m0skit0@sodiet:~/Temp$ cat prueba | grep o
Alfonso
Epifanio
Fidedigno
Obsoleto

Ahora podría volver a filtar para obtener sólo los nombre que contengan 'o' y 'n':

m0skit0@sodiet:~/Temp$ cat prueba | grep o | grep n
Alfonso
Epifanio
Fidedigno

Con otro ejemplo más útil: listar procesos en ejecución:

m0skit0@sodiet:~/Temp$ ps -A
PID TTY TIME CMD
1 ? 00:00:01 init
2 ? 00:00:00 kthreadd
3 ? 00:00:00 migration/0
4 ? 00:00:00 ksoftirqd/0
5 ? 00:00:00 watchdog/0
6 ? 00:00:00 events/0
[...]
2042 ? 00:00:00 gvfsd-trash
2045 ? 00:00:00 e-calendar-fact
2055 ? 00:00:00 e-addressbook-f
2064 ? 00:00:00 gvfsd-burn
2088 tty1 00:07:30 firefox-bin
2957 tty1 00:00:00 gnome-terminal
2958 tty1 00:00:00 gnome-pty-helpe
2959 pts/0 00:00:00 bash
3407 ? 00:00:00 flush-8:16
3466 pts/0 00:00:00 ps

Este comando lista todos los procesos en ejecución. La salida es muy engorrosa para buscar un proceso en concreto. Pero si usamos grep:

m0skit0@sodiet:~/Temp$ ps -A | grep gnome-terminal
2957 tty1 00:00:00 gnome-terminal

Ahora podríamos terminar este proceso con kill:

m0skit0@sodiet:~$ kill -TERM 2957

Pero esto se puede mejorar. ¿Podríamos conseguir mandar a kill el número de proceso directamente usando una sola línea de comando? Sencillo, esto es Linux chavales :oki:

Primero tendremos que extraer el número de proceso de la salida que nos brinda ps -A | grep gnome-terminal. Para ello tenemos a la maravillosa utilidad cut. cut corta, como su nombre bien indica, una línea (o varias) según un cierto formato. Para demostrar su funcionamiento, nos vamos a sustituir el anterior fichero prueba con este nuevo contenido:

Código: Seleccionar todo

1 García, Alfonso 
2 Pérez, Raquel
3 Gómez, Pepe
4 Segundo, Epifanio
5 Negro, Fidedigno
6 Cuevas, Obsoleto

Ahora veamos qué pasa si delimitamos por el carácter espacio ' '. Con -d le indicamos el carácter que queremos usar como delimitador (tabulación por defecto) y con -f qué parte del corte queremos.

m0skit0@sodiet:~/Temp$ cat prueba | cut -d ' ' -f 1
1
2
3
4
5
6

Como véis, hemos cortado todo lo previo al primer espacio. Veamos que pasa si cogemos entre el primer y el segundo espacio:

m0skit0@sodiet:~/Temp$ cat prueba | cut -d ' ' -f 2
García,
Pérez,
Gómez,
Segundo,
Negro,
Cuevas,

Hemos cogido los apellidos. Si queremos suprimir la coma, podríamos usar otra vez cut usando la coma como delimitador. Por ejemplo:

m0skit0@sodiet:~/Temp$ cat prueba | cut -d ' ' -f 2 | cut -d ',' -f 1
García
Pérez
Gómez
Segundo
Negro
Cuevas

Volviendo entonces a nuestro asunto, queremos sacar únicamente el número de proceso de la siguiente salida:

m0skit0@sodiet:~/Temp$ ps -A | grep gnome-terminal
3517 tty1 00:00:00 gnome-terminal

Como ya hemos visto, podemos cortar por espacios y coger el segundo campo (lo que hay entre el primer y el segundo espacio):

m0skit0@sodiet:~/Temp$ ps -A | grep gnome-terminal | cut -d ' ' -f 2
3517

Ahora bien, kill no soporta leer por la entrada estándar, le da dolor de cabeza:

m0skit0@sodiet:~/Temp$ ps -A | grep gnome-terminal | cut -d ' ' -f 2 | kill -TERM
kill: usage: kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]
m0skit0@sodiet:~/Temp$ ps -A | grep gnome-terminal | cut -d ' ' -f 2 | kill -TERM -
bash: kill: -: arguments must be process or job IDs

Por tanto no podemos usar tuberías (si alguien sabe cómo hacerlo por tuberías, que nos enseñe :D ). En este caso usaré backticks -> ` (no es suciedad en la pantalla, es una tilde al revés :mrgreen: ). Esto hace que bash sustituya todo lo que vaya entre este símbolo por el resultado de su ejecución. Esto sí se lo podemos pasar a kill (y a cualquier comando):

m0skit0@sodiet:~$ kill -TERM `ps -A | grep gnome-terminal | cut -d ' ' -f 2`

Espero que os haya resultado útil el ver las posibilidades y las limitaciones de las tuberías. Los comentarios son los bienvenidos :D
Imagen

Avatar de Usuario
~Rdavid~
Experto
Experto
Mensajes: 965
Registrado: 12 Nov 2009, 17:29
Ubicación: Costa Rica

Re: [Tutorial] Linux avanzado: Piping (Tuberías)

Mensaje por ~Rdavid~ »

Muy útil, gracias m0skit0 :D
Imagen

Responder