Pourquoi xargs fait-il avorter apt-get?


17

J'essaie de supprimer une liste de packages d'un fichier. J'utilise la commande suivante:

cat packages | xargs sudo apt-get remove

packagesest mon fichier contenant une liste de packages que je souhaite supprimer. Tout semble fonctionner, mais apt-getabandonne au lieu de me laisser choisir oui ou non.

Je sais que je peux contourner cela avec l' -yoption, mais je voudrais savoir pourquoi cela se produit et comment puis-je conserver le choix interactif.


Comment ça "marche bien" quand on dirait que ça ne marche pas du tout? À quoi ressemble une entrée dans votre fichier? As-tu essayé sudo xargs --arg-file packages apt-get remove?
pause jusqu'à nouvel ordre.

Eh bien, cela "fonctionne" car apt-get en arrive au point de supprimer les bons packages. Cela dit, --arg-file était ce que je cherchais. Vous pouvez mettre cela dans une réponse et je l'accepterai. Merci!
subb

Réponses:


13
xargs -a packages sudo apt-get remove

dirigera xargspour lire les arguments de packages, et ainsi il laissera stdin sans souci.


10

Une solution plus générale serait

 sudo apt-get remove `cat packages`

où vous aurez un problème si la liste des packages est vraiment longue .

La raison pour laquelle cela ne fonctionne pas est qu'apt-get essaie de lire votre confirmation à partir de l'entrée standard à laquelle - à cause du tuyau - est attachée cat. Au contraire, sudofait la bonne chose en demandant votre mot de passe en ouvrant / dev / tty directement. Apt devrait le faire, mais apparemment pas.


L'entrée standard de xargs est connectée au tube de cat, mais le processus démarré par xargs a son entrée standard provenant de / dev / null. C'est le comportement de xargs. Démonstration simple:echo "" | xargs ls -l /dev/self/fd
Juliano

1
@mws: Non, apt-getne devrait pas ouvrir /dev/tty. Sinon, vous ne pourriez pas faire des choses comme yes | apt-get. Les mots de passe sont à peu près le seul cas où la lecture /dev/ttyest la bonne chose, et même cela est discutable.
Gilles 'SO- arrête d'être méchant'

Merci pour les commentaires, les deux sont corrects et mieux pensés que ma réponse slap-dash, que je vais laisser non modifiée afin que les commentaires aient toujours du sens.
msw

Je vois. Y a-t-il une différence entre ceci et xargs -un nom de fichier, comme le suggère ephemient?
subb

Oui, l'utilisation éphémère de l' --arg-fileoption est encore meilleure pour le cas spécifique, c'est pourquoi je l'ai votée positivement. Pour les nombreuses commandes qui n'ont pas une telle option, la métaphore backtick-cat a toujours ses utilisations.
msw

2

Parce que apt-getsupprime plusieurs packages et doit donc confirmer l'action. Puisqu'il lit à STDINpartir d'un tuyau et n'est pas connecté au terminal, il suppose automatiquement No.

Une autre façon de se déplacer est d'ajouter APT::Get::Assume-Yesà apt.conf.


2

Apparemment, xargs redirige STDIN, ce qui confond apt-get à supposer qu'il fonctionne en mode non interactif.

J'utiliserais probablement quelque chose comme

sudo apt-get remove $(cat packages)

pour éviter d'utiliser xargs du tout.

("--arg-file" n'est ni dans apt-get (8) man ni dans mon vocabulaire actif).


1

Pour contourner.

Avec GNU xargs et ksh / zsh / bash:

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

(bien sûr, si la commande est juste cat, vous pouvez la remplacer <(cat packages)par packages.

Ou:

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

Selon le format du fichier "packages" (xargs attend une liste d'arguments séparés par des blancs et traite les guillemets ( ", 'et \), alors $(...)qu'il ne traite pas les guillemets et développe les modèles de globalisation), vous pouvez également faire:

sudo apt-get remove $(cat packages)

Mais veuillez noter que de nombreux systèmes d'exploitation ont une limite sur la longueur d'une ligne de commande, de sorte que cela peut ne pas fonctionner si la liste est grande (tandis que xargscontournera le problème en exécutant plusieurs apt-getcommandes).


0

Je peux me tromper, mais vous pouvez essayer cela et voir si cela fonctionne:

yes | sudo apt-get remove $(cat packages)
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.