¿Por qué xargs hace que apt-get aborte?

17

Estoy tratando de eliminar una lista de paquetes de un archivo. Estoy usando el siguiente comando:

cat packages | xargs sudo apt-get remove

packageses mi archivo que contiene una lista de paquetes que quiero eliminar. Todo parece funcionar, pero apt-getaborta en lugar de dejarme elegir sí o no.

Sé que puedo solucionar esto con la -yopción, pero me gustaría saber por qué sucede esto y cómo puedo mantener la opción interactiva.

subb
fuente
¿Cómo "funciona bien" cuando parece que no funciona en absoluto? ¿Cómo se ve una entrada en su archivo? ¿Lo has intentado sudo xargs --arg-file packages apt-get remove?
Pausado hasta nuevo aviso.
Bueno, de alguna manera "funciona" porque apt-get llega al punto de eliminar los paquetes correctos. Dicho eso, --arg-file era lo que estaba buscando. Puedes poner eso en una respuesta y lo aceptaré. ¡Gracias!
subb

Respuestas:

13
xargs -a packages sudo apt-get remove

dirigirá la xargslectura de argumentos packages, por lo que dejará stdin sin molestar.

efímero
fuente
10

Una solución más general sería

 sudo apt-get remove `cat packages`

donde tendrá un problema si la lista de paquetes es realmente larga .

La razón por la que no funciona es que apt-get está tratando de leer su confirmación de la entrada estándar a la que, debido a la tubería, está conectada cat. Por el contrario, sudohace lo correcto al pedir su contraseña abriendo / dev / tty directamente. Apt debería hacer esto, pero aparentemente no lo hace.

msw
fuente
La entrada estándar de xargs está conectada a la tubería desde cat, pero el proceso iniciado por xargs tiene su entrada estándar proveniente de / dev / null. Este es el comportamiento de xargs. Demostración simple:echo "" | xargs ls -l /dev/self/fd
Juliano
1
@mws: No, apt-getno debería abrirse /dev/tty. De lo contrario no podrías hacer cosas como yes | apt-get. Las contraseñas son prácticamente el único caso en el que leer /dev/ttyes lo correcto, e incluso eso es discutible.
Gilles 'SO- deja de ser malvado'
Gracias por los comentarios, ambos son correctos y están mejor pensados ​​que mi respuesta slap-dash, que voy a dejar sin editar para que los comentarios sigan teniendo sentido.
msw
Veo. ¿Hay alguna diferencia entre esto y xargs -un nombre de archivo, como sugiere ephemient?
subb
Sí, el uso de ephimemient de la --arg-fileopción es aún mejor para el caso específico, por eso lo voté. Para los muchos comandos que no tienen esa opción, la metáfora backtick-cat todavía tiene sus usos.
msw
2

Porque apt-getestá eliminando más de un paquete, y por lo tanto debe confirmar la acción. Como está leyendo STDINdesde una tubería y no está conectado al terminal, asume automáticamente No.

Otra forma de evitar esto es agregar APT::Get::Assume-Yesa apt.conf.

bahamat
fuente
2

Aparentemente, xargs redirige STDIN, lo que confunde a apt-get para suponer que se está ejecutando en modo no interactivo.

Probablemente usaría algo como

sudo apt-get remove $(cat packages)

para evitar usar xargs en absoluto.

("--arg-file" no está en apt-get (8) man ni en mi vocabulario activo).

Solo trabajo
fuente
1

Para trabajar alrededor.

Con GNU xargs y ksh / zsh / bash:

sudo xargs -r --arg-file <(cat packages) apt-get remove

(por supuesto, si el comando es justo cat, puede reemplazarlo <(cat packages)con packages.

O:

< packages sudo xargs sh -c 'exec apt-get remove "$@" < /dev/tty' sh

Dependiendo del formato del archivo de "paquetes" (xargs espera una lista separada por espacios en blanco de argumentos y comillas de procesos ( ", 'y \), mientras $(...)que no procesa comillas y expande patrones globales), también podría hacer:

sudo apt-get remove $(cat packages)

Pero tenga en cuenta que muchos sistemas operativos tienen un límite en la longitud de una línea de comando, por lo que puede no funcionar si la lista es grande (mientras xargsque solucionará el problema ejecutando varios apt-getcomandos).

Stéphane Chazelas
fuente
0

Puedo estar equivocado, pero puedes probar esto y ver si funciona:

yes | sudo apt-get remove $(cat packages)
fromnaboo
fuente