Por que xargs faz com que o apt-get seja interrompido?

17

Estou tentando remover uma lista de pacotes de um arquivo. Estou usando o seguinte comando:

cat packages | xargs sudo apt-get remove

packagesé o meu arquivo que contém uma lista de pacotes que desejo remover. Tudo parece funcionar, mas apt-getaborta em vez de me deixar escolher sim ou não.

Sei que posso contornar isso com a -yopção, mas gostaria de saber por que isso está acontecendo e como posso manter a escolha interativa.

subb
fonte
Como "funciona bem" quando parece que não funciona? Como é uma entrada no seu arquivo? Você já tentou sudo xargs --arg-file packages apt-get remove?
Pausado até novo aviso.
Bem, meio que "funciona" porque o apt-get chega ao ponto de remover os pacotes corretos. Dito isto, --arg-file era o que eu estava procurando. Você pode colocar isso em uma resposta e eu aceito. Obrigado!
Subb

Respostas:

13
xargs -a packages sudo apt-get remove

irá direcionar xargsa leitura dos argumentos packagese, portanto, deixará o stdin sem ser molestado.

efémero
fonte
10

Uma solução mais geral seria

 sudo apt-get remove `cat packages`

onde você terá um problema se a lista de pacotes for realmente longa .

A razão pela qual não está funcionando é que o apt-get está tentando ler sua confirmação na entrada padrão à qual - por causa do pipe - está conectado cat. Por outro lado, sudofaz a coisa certa pedindo sua senha, abrindo / dev / tty diretamente. O Apt deve fazer isso, mas aparentemente não.

msw
fonte
A entrada padrão do xargs é conectada ao canal a partir de cat, mas o processo iniciado pelo xargs tem sua entrada padrão vinda de / dev / null. Este é o comportamento de xargs. Demonstração simples:echo "" | xargs ls -l /dev/self/fd
Juliano
1
@mws: Não, apt-getnão deve abrir /dev/tty. Caso contrário, você não poderia fazer coisas como yes | apt-get. As senhas são praticamente o único caso em que a leitura /dev/ttyé a coisa certa, e até isso é discutível.
Gilles 'SO- stop be evil'
Obrigado pelos comentários, ambos estão corretos e melhor pensados ​​do que minha resposta slap-dash, que deixarei sem edição para que os comentários ainda façam sentido.
msw
Entendo. Existe alguma diferença entre este e xargs -a nome do arquivo, como ephemient está sugerindo?
Subb
Sim, o uso da --arg-fileopção pelo ephimemient é ainda melhor para o caso específico, e foi por isso que eu a votei. Para os muitos comandos que não têm essa opção, a metáfora backtick-cat ainda tem seus usos.
msw
2

Porque apt-getestá removendo mais de um pacote e, portanto, deve confirmar a ação. Como está lendo STDINde um tubo e não está conectado ao terminal, ele assume automaticamente No.

Outra maneira de contornar isso é adicionar APT::Get::Assume-Yesa apt.conf.

bahamat
fonte
2

Aparentemente, o xargs redireciona o STDIN, o que confunde o apt-get ao assumir que ele está sendo executado no modo não interativo.

Eu provavelmente usaria algo como

sudo apt-get remove $(cat packages)

para evitar o uso de xargs.

("--arg-file" não está no apt-get (8) man nem no meu vocabulário ativo).

Onlyjob
fonte
1

Para contornar.

Com GNU xargs e ksh / zsh / bash:

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

(é claro, se o comando for justo cat, você poderá substituir <(cat packages)por packages.

Ou:

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

Dependendo do formato do arquivo "packages" (o xargs está esperando uma lista em branco separada de argumentos e processos entre aspas ( ", 'e \), embora $(...)não processe aspas e expanda padrões de globbing), você também pode:

sudo apt-get remove $(cat packages)

Mas observe que muitos sistemas operacionais têm um limite no comprimento de uma linha de comando; portanto, isso pode não funcionar se a lista for grande (enquanto xargsisso contornará o problema executando vários apt-getcomandos).

Stéphane Chazelas
fonte
0

Posso estar errado, mas você pode tentar isso e ver se funciona:

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