¿Cómo forzar que el script bash espere la respuesta del usuario?

¿Cómo forzar que el script bash espere la respuesta del usuario?

Ya hay preguntas similares pero publico esto porque ninguna de las respuestas funcionó. Estoy escribiendo un script bash para automatizar la instalación de paquetes pacman y AUR en mi sistema Arch. La idea es leer un archivo (myfile) con los nombres de los paquetes primero línea por línea y luego palabra por palabra y realizar la instalación para cada palabra. Esto funciona bien para pacman pero no para AUR Helper (aurman). La parte de aurman se ve así:

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"

con las opciones--noconfirm --necesario --noeditaurman no me solicita Sí/No, pero para algunos paquetes me solicita un número. Entonces el problema es que en este caso el script no espera, el paquete no se instala y aurman produce un error "EOFError: EOF al leer una línea". Intenté pausar el script de esta manera:

aurman ...
wait

o así:

aurman ... &
wait

pero ninguno de estos funciona.

Entonces, ¿cómo puedo pausar mi script cuando aurman me pide un número? ¿Cuál es el enfoque general en casos como este? ¿Cómo podría dar una respuesta para un paquete específico desde el principio cuando ejecuto el script (por ejemplo, 1 para el paquete x)?

Respuesta1

El problema básico es que la entrada estándar (que aurmanintenta leer) no proviene del usuario, sino que se redirige primero desde $myfiley luego desde un documento aquí que contiene los comandos de shell para sudoejecutar. Una opción es pasar esos archivos a través de un descriptor de archivo diferente, como el número 3 (que normalmente no se utiliza). Ipensartambién puede simplificarlo eliminando el shell que se ejecuta sudo; dado que se está ejecutando aurmanen primer plano, no es necesario wait, por lo que no necesita el shell (y por lo tanto, no necesita el documento aquí).

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"

Si eso no funciona y realmente necesita que el shell se ejecute en sudo, también puede redirigirlo a través de FD #3 y leerlo bashcomo un script, como este:

            sudo -u "${my_user}" bash /dev/fd/3 3<< EOF
aurman -S --noconfirm --needed --noedit "$aurpkg"
wait
EOF

Respuesta2

Para bash, existe eldormircomando, que pone el script en suspensión hasta que haya transcurrido un período de tiempo en segundos. Sin embargo, si lo que desea es obtener una contraseña, le recomendaría uno de los 2 métodos siguientes (consulte el script que puse en la parte inferior para ilustrar cómo funciona la suspensión, y también las 2 alternativas que se mencionan a continuación).

  • Puede enviar la contraseña como parámetro al iniciar el script.
  • Puedes usarleercomando, esto registrará las entradas hasta que el cliente presione 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 ~]#

información relacionada