Inserir entrada automaticamente na linha de comando


142

Estou executando um script que solicita a inserção de 'y' em cada operação, estou procurando uma solução que goste $ ./script < echo 'yyyyyyyyyyyyyy'de passar todas as minhas entradas de uma só vez.


Às vezes, a -fopção funciona bem com determinados comandos.
— Izmilind

Respostas:


258

Existe um comando criado especificamente para esse caso: yes

$ yes | ./script

O que isso faz é conectar a saída de yesà entrada de ./script. Então, quando ./scriptsolicita a entrada do usuário, ela obtém a saída de yes. A saída de yesé um fluxo interminável de yseguido por uma nova linha. Então, basicamente, como se o usuário estivesse entrando ypara todas as perguntas de ./script.

Se você quiser dizer não ( n) em vez de sim ( y), faça o seguinte:

$ yes n | ./script

Observe que algumas ferramentas têm a opção de sempre assumir yescomo resposta. Veja aqui por exemplo: ignore o prompt yes / no em 'apt-get upgrade'


Outros métodos para inserir entrada:

Se você sabe exatamente quantos yscripts o seu está esperando, você pode fazê-lo assim:

$ printf 'y\ny\ny\n' | ./script

As novas linhas ( \n) são as teclas de entrada.

Usando em printfvez de yesvocê, você tem um controle mais refinado da entrada:

$ printf 'yes\nno\nmaybe\n' | ./script

Observe que, em alguns casos raros, o comando não exige que o usuário pressione enter após o caractere. nesse caso, deixe as novas linhas de fora:

$ printf 'yyy' | ./script

Por uma questão de integridade, você também pode usar um documento aqui :

$ ./script << EOF
y
y
y
EOF

Ou se o seu shell suportar uma string here :

$ ./script <<< "y
y
y
"

Ou você pode criar um arquivo com uma entrada por linha:

$ ./script < inputfile

Se o comando for suficientemente complexo e os métodos acima não forem mais suficientes, você poderá usar o expect .

Aqui está um exemplo de um script de espera super simples:

spawn ./script
expect "are you sure?"
send "yes\r"
expect "are you really sure?"
send "YES!\r"
expect eof

Nitpick técnico:

A chamada de comando hipotético que você deu na sua pergunta não funciona:

$ ./script < echo 'yyyyyyyyyyyyyy'
bash: echo: No such file or directory

Isso ocorre porque a gramática do shell permite um operador de redirecionamento em qualquer lugar da linha de comando. No que diz respeito ao shell, sua linha de comando hipotética é a mesma que esta:

$ ./script 'yyyyyyyyyyyyyy' < echo
bash: echo: No such file or directory

Isso significa ./scriptque será chamado com o argumento 'yyyyyyyyyyyyyy'e o stdin obterá entrada de um arquivo chamado echo. E o bash reclama, já que o arquivo não existe.


11
Eu recebo um cannot enable tty mode on non tty input. Você conheceria uma solução alternativa para isso?
— Bpmasini # 22/16

Quando tento o printftruque com um runarquivo do qual preciso automatizar o processo de instalação, tudo o que acontece é que recebo uma mensagem de erro dizendo Warning: Tried to connect to session manager, None of the authentication protocols specified are supported, e o script é aberto em um novo terminal e solicita que eu insira minha entrada manualmente, como de costume. A propósito, isso está acontecendo no Debian. Alguma sugestão?
— DavidB

precisa de mais detalhes. grande demais para comentários. faça uma nova pergunta com todos os detalhes. você pode colocar um link aqui.
— Lesmana

nada funciona com 'vagrant destroy' em centos #
— Drew

Malvado fácil! Funciona nas importações de dados SQL do Google Cloud Beta! Muito apreciado!
— 30818 G_Style

11

Use o comando yes:

yes | script

Trecho da página de manual:

NAME
       yes - output a string repeatedly until killed

SYNOPSIS
       yes [STRING]...
       yes OPTION

DESCRIPTION
       Repeatedly output a line with all specified STRING(s), or 'y'.

9

Algumas coisas ( apt-getpor exemplo) aceitam sinalizadores especiais para executar no modo silencioso (e aceitam padrões). No apt-getcaso, você apenas passa uma -ybandeira. Isso depende completamente do seu script.

Se você precisar de coisas mais complicadas, poderá agrupar seu script em um script esperado. expect permite que você leia a saída e envie a entrada para que você possa fazer coisas bastante complicadas que outros scripts não permitiriam. Aqui está um dos exemplos de sua página da Wikipedia :

# Assume $remote_server, $my_user_id, $my_password, and $my_command were read in earlier
# in the script.
# Open a telnet session to a remote server, and wait for a username prompt.
spawn telnet $remote_server
expect "username:"
# Send the username, and then wait for a password prompt.
send "$my_user_id\r"
expect "password:"
# Send the password, and then wait for a shell prompt.
send "$my_password\r"
expect "%"
# Send the prebuilt command, and then wait for another shell prompt.
send "$my_command\r"
expect "%"
# Capture the results of the command into a variable. This can be displayed, or written to disk.
set results $expect_out(buffer)
# Exit the telnet session, and wait for a special end-of-file character.
send "exit\r"
expect eof

Isso não pode ser usado com um .shscript de shell, certo? Ou existe um caminho?
— Shayan

7

No script shell, você também pode usar o seguinte truque de desova, esperar e enviar

spawn script.sh
expect "Are you sure you want to continue connecting (yes/no)?"
send "yes"

No entanto, no cenário acima, você deverá fornecer a frase que espera obter enquanto executa o script. Para obter mais exemplos, acesse o link a seguir

Espere no Bash


2

Ok, isso pode não ser uma solução muito elegante, mas se você escrever suas opções em um arquivo separado e depois passá-lo como uma entrada para o script, também funcionará. Portanto, se você criar um novo arquivo com todas as suas opções (chame esse arquivo como 'options.in'), poderá executar facilmente seu script ./script.sh < options.ine editar / criar arquivos de opções diferentes, conforme adequado.


Como devo escrever o options.inarquivo? Você pode dar um exemplo?
— Shayan

0

Eu estava escrevendo um script bash com o Dialog e precisava que isso acontecesse automaticamente também. Eu fiz isso e funcionou como um encanto.

# -Wy force signaturewipe (if exists)
echo "y" | sudo lvcreate -W y -n $lvName -L "$lvSize"G /dev/"$svg" >> $nfsUtilLog

-1

Você pode fornecer entrada do usuário ao seu script com cat, a partir de um arquivo de texto, canalizado para o seu script da bashseguinte maneira:

cat input.txt | bash your_script.sh

Basta inserir a entrada do usuário desejada no arquivo input.txt, quaisquer que sejam as respostas desejadas - y, n, dígitos, seqüências de caracteres, etc.



@ muru Para mim, a solução que você mencionou não funcionou, então eu tenho que inventar a minha.
— WebComer 05/07/19

Improvável. Ambos descrevem a mesma coisa.
— muru

A idéia semelhante de respostas de fornecimento do arquivo (que pode ser feita de várias maneiras) não é a mesma coisa e, além disso, é realizada de maneira bem diferente. Você deve poder vê-lo. Se a solução que você indicou funcionasse para mim, hoje não vou gastar meu tempo reinventando a roda. Você pode usar qualquer trabalho para você.
— WebComer 05/07/19

@muru Eu acredito que há uma diferença entre os dois, alguns dos quais descritos nas respostas dizem aqui askubuntu.com/questions/172982/… . Para mim, por exemplo, meu código, se a saída for redirecionada para o arquivo, parece mais claro como um fluxo natural da esquerda para a direita. Afinal, reduzir a votação de soluções que funcionem bem como você não estimula as pessoas a compartilhar suas soluções aqui. Eu acredito que isso é suficiente para remover a votação decrescente.
— WebComer 05/07/19
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.