Passar argumentos para um programa interativo de forma não interativa

115

Eu tenho um script bash que emprega o readcomando para ler argumentos para comandos de forma interativa, por exemplo, opções sim / não. Existe uma maneira de chamar este script em um script não interativo passando valores de opção padrão como argumentos?

Não é apenas uma opção que devo passar para o script interativo.

Sharma Sidharth
fonte
2
Se estiver lendo de stdin, você pode canalizar sua entrada
lc.
4
Como esta questão fica com muitas duplicatas, vale ressaltar que não importa em qual idioma o programa interativo é escrito. Pode ser um programa C que lê a entrada padrão, ou um aplicativo Erlang, ou qualquer outro. Existe algo que é executado na linha de comando e exige uma entrada interativa, e você gostaria de automatizar isso.
tripleee
Claro, se você tiver controle sobre o aplicativo desagradável, reescreva-o para que possa ler as respostas de forma não interativa (por meio de um arquivo de configuração, opções de linha de comando ou qualquer outra coisa). Isso é muito mais confiável e robusto contra a alteração da ordem ou do texto das perguntas interativas.
tripleee

Respostas:

46

Para tarefas mais complexas existe expect( http://en.wikipedia.org/wiki/Expect ). Basicamente, simula um usuário, você pode codificar um script para reagir a saídas de programas específicos e coisas relacionadas.

Isso também funciona em casos como os sshque proíbem a transferência de senhas para ele.

Dani Gehtdichnixan
fonte
8
... Embora a solução adequada no caso SSH seja mudar para a autenticação de chave pública.
tripleee
154

Várias maneiras

canalize sua entrada

echo "yes
no
maybe" | your_program

redirecionar de um arquivo

your_program < answers.txt

use um documento aqui (pode ser muito legível)

your_program << ANSWERS
yes
no
maybe
ANSWERS

use uma string here

your_program <<< $'yes\nno\nmaybe\n'
glenn jackman
fonte
5
É importante ressaltar que isso só funciona se o programa ler a entrada padrão. Alguns programas se esforçam para ler, por exemplo, senhas de forma interativa, mesmo quando a entrada padrão é um pipe. Para senhas, isso faz sentido por motivos de segurança; embora alguns programas interativos sejam simplesmente mal projetados.
tripleee
@tripleee Junto com o que você disse, como um script lê senhas que não são afetadas por stdin? Eu sei que você pode usar readpara capturar stdin, qual função você pode usar para fazer o que descreveu?
flow2k
Nesse caso, você precisa ver se o programa com o qual está tentando interagir tem uma maneira especial de enviar a entrada para ele (por exemplo, sshpass, ssh-agent) ou use o expect para fazer o script da interação.
glenn jackman
2
O que programas como o Expect fazem é executar o cliente em um pseudo-tty, onde parece ao cliente que há um usuário com um terminal e um teclado na outra extremidade. Você não pode fazer isso com um cano normal.
tripleee
Notícia importante. Isso não funciona se adicionarmos espaços aos comandos fornecidos.
71GA
13

Você pode colocar os dados em um arquivo e redirecioná-los desta forma:

$ cat file.sh
#!/bin/bash

read x
read y
echo $x
echo $y

Dados para o script:

$ cat data.txt
2
3

Executando o script:

$ file.sh < data.txt
2
3
Guru
fonte
7

Só quero adicionar mais uma maneira. Encontrei em outro lugar, e é bastante simples. Digamos que eu queira passar sim para todos os prompts na linha de comando para um comando "execute_command". Então, eu simplesmente enviaria sim para ele.

yes | execute_command

Isso usará sim como resposta para todas as solicitações sim / não.


fonte
2

Você também pode usar printf para canalizar a entrada para seu script.

var=val
printf "yes\nno\nmaybe\n$var\n" | ./your_script.sh
Spanchan
fonte
Foi isso que me salvou. Obrigado @spanchan.
sk001
0

outra alternativa pode ser

echo "something" | tee /path/to/file

O comando tee imprime a entrada que recebe na tela e a salva em um arquivo ao mesmo tempo.

Prafulla Kumar Sahu
fonte