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.


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.


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'

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

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.


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

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.

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.