Por que o comando read não aceita opções interativas quando executado por sh?

5

Eu quero baixar um script de provisionamento que lê alguns parâmetros de configuração via read e executá-lo:

curl http://example.com/provisioning.sh | sh

O problema é que o comando read no script é chamado com o parâmetro -i para fornecer um padrão:

read -p "Name: " -i joe name
echo $name

Se eu baixar o script, defina a permissão +x e execute-a, tudo bem.

Se eu executar com cat provisioning.sh | sh ou sh provisioning.sh , ele falhará com:

read: Illegal option -i

Por que não ler o suporte fornecendo um padrão se for executado via sh?

Mas seja o que for, eu removerei o -i , ficando com

read -p "Name: " name
echo $name

Agora, se eu executar o script via cat provisioning.sh | sh , ele não fará nada. Por que isso?

Ubuntu 14.04.

    
por Dan Dascalescu 11.07.2014 / 11:59

2 respostas

7

Quando você canaliza a saída de curl para sh , está tornando o texto do script a entrada padrão do shell, que o utiliza como comandos a serem executados. Depois disso, não resta mais nada para read . Mesmo se fosse tentar, não receberia nada da entrada do terminal, porque não está conectado a ela. O pipe substituiu a entrada padrão para o processo sh .

O próximo problema é que read -i não é um recurso POSIX sh , mas sim uma extensão suportada por bash . O Ubuntu usa dash , um shell mínimo compatível com POSIX com extensões mínimas, como /bin/sh por padrão. É por isso que rejeita especificamente a opção -i (embora suporte -p ).

Se você estiver usando um shell mais capaz, tente algo como:

bash <(curl http://example.com/provisioning.sh)

que cria um canal para bash ler a saída de curl e fornece como argumento do arquivo de script. Nesse caso, a entrada padrão do script ainda está conectada ao terminal e read funcionará (mas observe a grande advertência abaixo da linha).

Também observarei que " curl | sh " é geralmente franziu a testa sobre como um problema de segurança óbvio, mas você conhece melhor a situação em que seu script está.

    
por 11.07.2014 / 12:20
0

Outra forma mais portátil de conseguir isso é criar outro descritor de arquivo:

exec 3<>/dev/tty
read -u 3 -p "Gimme some stuff: " stuff

Eu descobri que aqui: link

No meu caso, eu fiz uma rápida descoberta no meu script para que isso funcionasse:

exec 3<>/dev/tty
read_cmd="read -u 3"

$read_cmd -p "name: " my_name
$read_cmd -p "email: " my_email
$read_cmd -s -p "password: " my_password
    
por 05.06.2018 / 07:32