Já existem perguntas semelhantes, mas estou postando porque nenhuma das respostas funcionou. Estou escrevendo um script bash para automatizar a instalação de pacotes pacman e AUR em meu sistema Arch. A ideia é ler um arquivo (myfile) com os nomes dos pacotes primeiro linha por linha e depois palavra por palavra e realizar a instalação para cada palavra. Isso funciona bem para o pacman, mas não para o AUR Helper (aurman). A parte para aurman é assim:
while read line; do
if [[ "$line" =~ \$[[:space:]]aurman[[:space:]]-S[[:space:]][[:alnum:]]* ]]
then
aurline=$(echo "$line" | awk '{ $1=""; $2=""; $3=""; print}' | sed 's/^ *//')
for aurpkg in $aurline
do
sudo -u "${my_user}" bash << EOF
aurman -S --noconfirm --needed --noedit "$aurpkg"
wait
EOF
done
fi
done < "$myfile"
Com as opções--noconfirm --needed --noeditaurman não solicita Sim/Não, mas para alguns pacotes ele solicita um número. Então o problema é que neste caso o script não espera, o pacote não é instalado e o aurman produz um erro "EOFError: EOF ao ler uma linha". Eu tentei pausar o script assim:
aurman ...
wait
ou assim:
aurman ... &
wait
mas nada disso funciona.
Então, como posso pausar meu script quando aurman me solicita um número? Qual é a abordagem geral em casos como este? Como eu poderia dar uma resposta para um pacote específico desde o início, quando executo o script (por exemplo, 1 para o pacote x)?
Responder1
O problema básico é que o stdin (que aurman
está tentando ler) não vem do usuário, está sendo redirecionado primeiro de $myfile
e depois de um documento aqui contendo os comandos do shell para sudo
execução. Uma opção é passar esses arquivos por meio de um descritor de arquivo diferente, como o nº 3 (que normalmente não é usado). EUpensarvocê também pode simplificá-lo eliminando o shell executado sudo
- como você está executando aurman
em primeiro plano, não há necessidade wait
disso, então você não precisa do shell (e, portanto, não precisa do documento aqui).
while read line <&3; do
if [[ "$line" =~ \$[[:space:]]aurman[[:space:]]-S[[:space:]][[:alnum:]]* ]]
then
aurline=$(echo "$line" | awk '{ $1=""; $2=""; $3=""; print}' | sed 's/^ *//')
for aurpkg in $aurline
do
sudo -u "${my_user}" aurman -S --noconfirm --needed --noedit "$aurpkg"
done
fi
done 3< "$myfile"
Se isso não funcionar e você realmente precisar que o shell seja executado em sudo
, você também pode redirecioná-lo via FD #3 e ler bash
isso como um script, assim:
sudo -u "${my_user}" bash /dev/fd/3 3<< EOF
aurman -S --noconfirm --needed --noedit "$aurpkg"
wait
EOF
Responder2
Para bash, existe odormircomando, que coloca o script em suspensão até que um período de tempo em segundos tenha passado. Porém, se o que você deseja é pegar uma senha, recomendo um dos 2 métodos abaixo (confira o script que coloquei abaixo, para ilustrar como funciona o sono, e também as 2 alternativas mencionadas abaixo).
- Você pode enviar a senha como parâmetro ao iniciar o script.
- Você pode usarlercomando, isso registrará as entradas até que o cliente pressione enter.
[root@client ~]# cat readPass.sh
#!/bin/bash
# Author: @djcerdas
password="$1"
# Sample sleep command
echo "Hi, I am the PID $$, I am going to sleep 3 seconds"
date&&sleep 3&&date
echo "---------------------------------------"
# Sample method 1: passing password a parameter
echo "Method 1: The password is $password"
password=""
echo "---------------------------------------"
# Sample method 2: using read
echo "Method 2: Please provide your password:"
read password
echo The password is $password
[root@client ~]# ./readPass.sh myPasswordX
Hi, I am the PID 2257, I am going to sleep 3 seconds
Tue Apr 3 01:17:55 CST 2018
Tue Apr 3 01:17:58 CST 2018
---------------------------------------
Method 1: The password is myPasswordX
---------------------------------------
Method 2: Please provide your password:
myNewPassword
The password is myNewPassword
[root@client ~]#