Почему xargs вызывает apt-get для прерывания?

17

Я пытаюсь удалить список пакетов из файла. Я использую следующую команду:

cat packages | xargs sudo apt-get remove

packagesмой файл, содержащий список пакетов, которые я хочу удалить. Кажется, все работает, но apt-getпрерывается, вместо того, чтобы позволить мне выбрать да или нет.

Я знаю, что могу обойти это с -yопцией, но я хотел бы знать, почему это происходит и как я могу сохранить интерактивный выбор.

SUBB
источник
Как это «хорошо работает», когда звучит так, будто не работает вообще? Как выглядит запись в вашем файле? Ты пробовал sudo xargs --arg-file packages apt-get remove?
Приостановлено до дальнейшего уведомления.
Ну, это вроде «работает», потому что apt-get доходит до удаления нужных пакетов. Тем не менее, --arg-file был тем, что я искал. Вы можете поместить это в ответ, и я приму это. Благодарность!
2010 г.

Ответы:

13
xargs -a packages sudo apt-get remove

будет направлен xargsна чтение аргументов packages, поэтому он не будет подвергаться насилию.

ephemient
источник
10

Более общее решение будет

 sudo apt-get remove `cat packages`

где у вас будет проблема, если список пакетов очень длинный .

Причина, по которой он не работает, состоит в том, что apt-get пытается прочитать ваше подтверждение из стандартного ввода, к которому - из-за канала - прикреплено cat. Наоборот, sudoпоступает правильно, спрашивая свой пароль, открывая / dev / tty напрямую. Апт должен сделать это, но, очевидно, нет.

MSW
источник
Стандартный ввод xargs подключен к каналу from cat, но процесс, запущенный xargs, имеет стандартный ввод из / dev / null. Это поведение xargs. Простая демонстрация:echo "" | xargs ls -l /dev/self/fd
Джулиано
1
@mws: нет, apt-getне должен открываться /dev/tty. В противном случае вы не можете делать такие вещи, как yes | apt-get. Пароли в значительной степени единственный случай , когда чтение из /dev/ttyявляется правильным, и даже , что многое спорно.
Жиль "ТАК - перестань быть злым"
Спасибо за комментарии, оба являются правильными и лучше продуманными, чем мой ответ пощечины, который я собираюсь оставить без редактирования, чтобы комментарии все еще имели смысл.
2010 г.
Понимаю. Есть ли разница между этим и xargs -a именем файла, как предлагает ephemient?
2010 года
Да, использование этой --arg-fileопции ephimemient еще лучше для конкретного случая, поэтому я проголосовал за него. Для многих команд, у которых нет такой опции, метафора backtick-cat все еще имеет свое применение.
2010 года
2

Потому apt-getчто удаляет более одного пакета, и, следовательно, должны подтвердить действие. Так как он читает STDINиз канала и не подключен к терминалу, он принимает автоматически No.

Другой способ обойти это , чтобы добавить APT::Get::Assume-Yesк apt.conf.

bahamat
источник
2

По-видимому, xargs перенаправляет STDIN, что сбивает с толку apt-get, предполагая, что он работает в неинтерактивном режиме.

Я бы, наверное, использовал что-то вроде

sudo apt-get remove $(cat packages)

чтобы вообще не использовать xargs.

(«--arg-file» отсутствует ни в apt-get (8) man, ни в моем активном словаре).

Onlyjob
источник
1

Чтобы обойти.

С GNU xargs и ksh / zsh / bash:

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

(конечно, если команда просто cat, то вы можете заменить <(cat packages)на packages.

Или:

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

В зависимости от формата файла «packages» (xargs ожидает разделенный пробелами список аргументов и обрабатывает кавычки ( ", 'и \), в то время $(...)как не обрабатывает кавычки и расширяет шаблоны глобирования), вы также можете сделать:

sudo apt-get remove $(cat packages)

Но обратите внимание, что многие операционные системы имеют ограничение на длину командной строки, поэтому оно может не работать, если список большой (хотя можно xargsобойти проблему, выполнив несколько apt-getкоманд).

Стефан Шазелас
источник
0

Я могу ошибаться, но вы можете попробовать это и посмотреть, работает ли это:

yes | sudo apt-get remove $(cat packages)
fromnaboo
источник