Dlaczego xargs powoduje, że apt-get przerywa?

17

Próbuję usunąć listę pakietów z pliku. Używam następującego polecenia:

cat packages | xargs sudo apt-get remove

packagesto mój plik zawierający listę pakietów, które chcę usunąć. Wszystko wydaje się działać, ale apt-getprzerywa zamiast pozwolić mi wybrać tak lub nie.

Wiem, że mogę to obejść dzięki tej -yopcji, ale chciałbym wiedzieć, dlaczego tak się dzieje i jak mogę zachować interaktywny wybór.

podpunkt
źródło
Jak to działa „dobrze”, kiedy wydaje się, że wcale nie działa? Jak wygląda wpis w twoim pliku? Próbowałeś sudo xargs --arg-file packages apt-get remove?
Wstrzymano do odwołania.
Cóż, to trochę „działa”, ponieważ apt-get dochodzi do momentu usunięcia odpowiednich pakietów. To powiedziawszy: - plik -arg był tym, czego szukałem. Możesz podać to w odpowiedzi, a ja ją zaakceptuję. Dzięki!
podpunkt

Odpowiedzi:

13
xargs -a packages sudo apt-get remove

przekieruje xargsdo odczytu argumentów packages, a więc pozostawi stdin niezaprzeczalny.

efemeryczny
źródło
10

Bardziej ogólnym rozwiązaniem byłoby

 sudo apt-get remove `cat packages`

gdzie będziesz mieć problem, jeśli lista pakietów jest naprawdę długa .

Powodem, dla którego nie działa, jest to, że apt-get próbuje odczytać twoje potwierdzenie ze standardowego wejścia, do którego - z powodu potoku - jest przyłączony cat. W przeciwieństwie do tego, sudorobi właściwą rzecz, pytając o hasło, otwierając / dev / tty bezpośrednio. Apt powinien to zrobić, ale najwyraźniej nie.

msw
źródło
Standardowe wejście xargs jest podłączone do potoku z cat, ale proces rozpoczęty przez xargs ma standardowe wejście pochodzące z / dev / null. To jest zachowanie xargs. Prosta demonstracja:echo "" | xargs ls -l /dev/self/fd
Juliano,
1
@mws: Nie, apt-getnie powinien się otwierać /dev/tty. W przeciwnym razie nie można robić takich rzeczy yes | apt-get. Hasła to /dev/ttywłaściwie jedyny przypadek, w którym czytanie z jest właściwą rzeczą, a nawet tyle jest dyskusyjna.
Gilles „SO- przestań być zły”
Dzięki za komentarze, oba są poprawne i lepiej się nad tym zastanowić niż moja odpowiedź klapsa, którą zostawię bez edycji, aby komentarze nadal miały sens.
msw
Widzę. Czy jest jakaś różnica między tym a xargs-nazwa pliku, jak sugeruje ephemient?
podpunkt
Tak, korzystanie z tej --arg-fileopcji przez ephimemient jest jeszcze lepsze w konkretnym przypadku i dlatego głosowałem za nią. W przypadku wielu poleceń, które nie mają takiej opcji, metafora backtick-cat nadal ma swoje zastosowanie.
msw
2

Ponieważ apt-getusuwa więcej niż jedną paczkę i dlatego musi potwierdzić akcję. Ponieważ odczytuje STDINz potoku i nie jest podłączony do terminala, automatycznie zakłada No.

Innym sposobem obejścia tego jest dodanie APT::Get::Assume-Yesdo apt.conf.

bahamat
źródło
2

Najwyraźniej xargs przekierowuje STDIN, co dezorientuje apt-get, zakładając, że działa w trybie nieinteraktywnym.

Prawdopodobnie użyłbym czegoś takiego

sudo apt-get remove $(cat packages)

aby w ogóle unikać używania xargs.

(„--arg-file” nie jest ani w apt-get (8) man, ani w moim aktywnym słowniku).

Onlyjob
źródło
1

Do obejścia.

Z GNU xargs i ksh / zsh / bash:

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

(oczywiście, jeśli polecenie jest tylko cat, po czym można zastąpić <(cat packages)zpackages .

Lub:

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

W zależności od formatu pliku „pakietów” (xargs oczekuje pustej listy argumentów i przetwarza cudzysłowy ( ", 'i \), chociaż $(...)nie przetwarza cudzysłowów i rozwija wzorce globowania), możesz również:

sudo apt-get remove $(cat packages)

Należy jednak pamiętać, że wiele systemów operacyjnych ma ograniczenie długości wiersza polecenia, więc może nie działać, jeśli lista jest duża (podczas gdy xargsobejdzie ten problem, uruchamiając kilka apt-getpoleceń).

Stéphane Chazelas
źródło
0

Mogę się mylić, ale możesz spróbować i sprawdzić, czy to działa:

yes | sudo apt-get remove $(cat packages)
fromnaboo
źródło