Me pregunto qué deberíamos usar para canalizar y cuándo no.
Digamos, por ejemplo, que para matar ciertos procesos que manejan archivos pdf, lo siguiente no funcionará usando pipeline:
ps aux | grep pdf | awk '{print $2}'|kill
En cambio, solo podemos hacerlo de las siguientes maneras:
kill $(ps aux| grep pdf| awk '{print $2}')
o
ps aux | grep pdf | awk '{print $2}'| xargs kill
Según man bash
(versión 4.1.2
):
The standard output of command is connected via a pipe to the standard input of command2.
Para el escenario anterior:
- el stdin de
grep
es el stdout deps
. Eso funciona. - el stdin de
awk
es el stdout degrep
. Eso funciona. - el stdin de
kill
es el stdout deawk
. Eso no funciona
El stdin del siguiente comando siempre recibe información del stdout del comando anterior.
- ¿Por qué no funciona con
kill
orm
? - ¿Cuál es la diferencia entre
kill
,rm
de entrada, congrep
,awk
de entrada? - ¿Hay alguna regla?
pgrep
,pkill
y loskillall
comandos.pgrep
y el resto puede lograr esto perfectamente :)Respuestas:
Hay dos formas comunes de proporcionar aportes a los programas:
kill
usa solo argumentos de línea de comando. No lee de STDIN. Los programas tienen gustogrep
yawk
leen de STDIN (si no se dan nombres de archivo como argumentos de línea de comando) y procesan los datos de acuerdo con sus argumentos de línea de comando (patrón, declaraciones, banderas, ...).Solo puede canalizar a STDIN de otros procesos, no a argumentos de línea de comando.
La regla común es que los programas usan STDIN para procesar una cantidad arbitraria de datos. Todos los parámetros de entrada adicionales o, si generalmente hay solo unos pocos, se pasan por argumentos de línea de comando. Si la línea de comando puede ser muy larga, por ejemplo, para
awk
textos de programa largos , a menudo existe la posibilidad de leerlos desde archivos de programa adicionales (-f
opción deawk
).Para usar el STDOUT de programas como argumentos de línea de comando, use
$(...)
o en caso de muchos datosxargs
.find
También puede esto directamente con-exec ... {} +
.Para completar: Para escribir argumentos de línea de comando en STDOUT, use
echo
.fuente
gzip
en la SINOPSIS, no dijo que debe tomar un FILENAME como entrada. Estoy buscando hay una manera más sistemática para determinar eso.xargs
permitirá precisamente "canalizar los argumentos de la línea de comando"?xargs
. Llama al comando si es necesario más de una vez (el tamaño de la línea de comando es limitado) y tiene muchas otras opciones.Esta es una pregunta interesante, y trata con una parte de la filosofía de Unix / Linux.
Así que, ¿cuál es la diferencia entre programas como
grep
,sed
,sort
por un lado, ykill
,rm
,ls
en el otro lado? Veo dos aspectos.El aspecto del filtro
El primer tipo de programas también se llama filtros . Toman una entrada, ya sea de un archivo o de STDIN, la modifican y generan alguna salida, principalmente a STDOUT. Están destinados a ser utilizados en una tubería con otros programas como fuentes y destinos.
El segundo tipo de programas actúa sobre una entrada, pero la salida que dan a menudo no está relacionada con la entrada.
kill
no tiene salida cuando funciona regularmente, tampoco lo hacels
. Solo tienen un valor de retorno para mostrar el éxito. Normalmente no reciben información de STDIN, pero en su mayoría dan salida a STDOUT.Para programas como
ls
, el aspecto del filtro no funciona tan bien. Ciertamente puede tener una entrada (pero no la necesita), y la salida está estrechamente relacionada con esa entrada, pero no funciona como filtro. Sin embargo, para ese tipo de programas, el otro aspecto aún funciona:El aspecto semántico.
Para los filtros, su entrada no tiene significado semántico . Simplemente leen datos, modifican datos, generan datos. No importa si se trata de una lista de valores numéricos, algunos nombres de archivo o código fuente HTML. El significado de estos datos solo viene dado por el código que usted proporciona al filtro: la expresión regular para
grep
, las reglas paraawk
o el programa Perl.Para otros programas, como
kill
ols
, su entrada tiene un significado , una denotación .kill
espera números de proceso,ls
espera nombres de archivo o ruta. No pueden manejar datos arbitrarios y no están destinados a hacerlo. Muchos de ellos ni siquiera necesitan ninguna entrada o parámetro, comops
. Normalmente no leen de STDIN.Probablemente se podrían combinar estos dos aspectos: un filtro es un programa cuya entrada no tiene un significado semántico para el programa.
Estoy seguro de que he leído sobre esta filosofía en alguna parte, pero no recuerdo ninguna fuente en este momento, lo siento. Si alguien tiene algunas fuentes presentes, no dude en editar.
fuente
No hay "reglas" como tales. Algunos programas reciben información de STDIN y otros no. Si un programa puede recibir información de STDIN, se puede canalizar a, si no, no puede.
Normalmente puede saber si un programa tomará información o no al pensar en lo que hace. Si el trabajo del programa es manipular de alguna forma los contenidos de un archivo (por ejemplo
grep
,sed
,awk
etc.), que normalmente toma de entrada de STDIN. Si su trabajo consiste en manipular el archivo en sí (por ejemplomv
,rm
,cp
) o un proceso (por ejemplokill
,lsof
) o a la información de retorno sobre algo (por ejemplotop
,find
,ps
), entonces no lo hace.Otra forma de pensarlo es la diferencia entre argumentos y aportes. Por ejemplo:
En el comando anterior,
mv
no tiene entrada como tal. Lo que se le ha dado son dos argumentos. No sabe ni le importa lo que hay en ninguno de los archivos, solo sabe que esos son sus argumentos y debe manipularlos.Por otra parte
Aquí,
sed
se ha dado información y un argumento. Como toma entrada, puede leerlo desde STDIN y puede canalizarlo.Se vuelve más complicado cuando un argumento puede ser la entrada. Por ejemplo
Aquí
file
está el argumento que se le diocat
. Para ser precisos, el nombre del archivofile
es el argumento. Sin embargo, dado quecat
es un programa que manipula el contenido de los archivos, su entrada es lo que esté dentrofile
.Esto puede ilustrarse con
strace
un programa que rastrea las llamadas al sistema realizadas por los procesos. Si corremos acat foo
través destrace
, podemos ver que el archivofoo
está abierto:La primera línea de arriba muestra que el programa
/bin/cat
fue llamado y sus argumentos fueroncat
yfoo
(el primer argumento es siempre el programa en sí). Más tarde, el argumentofoo
se abrió en modo de solo lectura. Ahora, compara esto conAquí también, se
ls
tomó yfoo
como argumentos. Sin embargo, no hayopen
llamada, el argumento no se trata como entrada. En cambio,ls
llama a lastat
biblioteca del sistema (que no es lo mismo que elstat
comando) para obtener información sobre el archivofoo
.En resumen, si el comando que está ejecutando leerá su entrada, puede canalizarlo, si no lo hace, no puede.
fuente
kill
yrm
no necesita STDIN.Para
kill
yrm
, los usuarios proporcionan su información personalizada como argumento, y$(cmd)
ayuda a tomar el STDOUT decmd
y convertir su argumento de información.Para
grep
yawk
, los usuarios proporcionan argumentos y, además, tambiénSTDIN
o un archivo normal que será procesado por el comando.STDIN
se puede pasar con tubería|
o ingresando manualmente.Lea el manual o los códigos fuente. Y si no encuentra nada de lo que necesita, puede hacer una prueba simple pero quizás peligrosa:
Simplemente ingrese el comando que le interesa, con argumentos que ya ha entendido, y vea si el comando se detiene (no pasa nada). Si pausa, en realidad está a la espera de STDIN (puedes probar
cat
yecho
ver el diferente). Escribe manualmenteCtrl-D
y el comando continúa (muestra resultados o errores) y regresa. Tal comando necesita STDIN en esa situación (con argumentos que proporcione).El mismo comando puede no necesitar STDIN en diferentes situaciones (por ejemplo,
cat
espera STDIN perocat file.txt
no).fuente