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.

NewMrd
fonte
À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.

lesmana
fonte
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'.
Peter W. Osel
fonte
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
Oli
fonte
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

Tarun
fonte
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.

Sidhha
fonte
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
Benjamin West
fonte
-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.

WebComer
fonte
@ 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