## bash script  
foo(){

    sleep 0.0001
    read -s -t 0.0002 var  ## get the pipeline input if have 
    if [ -n "$var" ];then
        echo "has pipe input"
    fi

    if [ $# -gt 0 ];then
        echo "has std input"
    fi
    read -s -t 30 var1  #1 # expect wait for 30 seconds , but acturaly not
    echo "failed"     
    read -s -t 30 var2  #2  
    echo "failed again"
}

echo "ok1"|  foo "ok"

## output: 
has pipe input
has std input
failed
failed again

Si le toto a une entrée de pipeline, la commande de lecture en # 1 & # 2 retournera immédiatement sans attendre l'entrée TIMEOUT

Dans mon vrai script, il y a trois besoins:

1 fonction créée pourrait accepter l'entrée de pipeline et le paramètre en même temps (parce que je veux que ma fonction puisse prendre la configuration de l'entrée de pipeline, je pense que ce sera bien pour moi. Par exemple :)

foo(){
    local config
    sleep 0.0001
    read -t 0.0002 config
    eval "$config"
}

then i can pass configuration like this 
foo para1 para2 <<EOF
G_TIMEOUT=300
G_ROW_SPACE=2
G_LINE_NUM=10
EOF

2 dans ma fonction, j'ai besoin de lire les entrées de l'utilisateur à partir du clavier (j'ai besoin d'interagir avec l'utilisateur en utilisant lire

3 Attendre l'entrée de l'utilisateur doit avoir un délai d'attente (je veux implémenter un économiseur d'écran, s'il n'y a pas d'action après TIMEOUT secondes passées de l'utilisateur, appellera le script de l'économiseur d'écran, et après chaque keydown, l'écran de veille reviendra, et à nouveau pour attendre l'entrée d'utilisation

s'il existe un moyen de rediriger l'entrée de pipeline vers fd3 après avoir obtenu l'entrée de pipeline, puis de fermer fd3 pour briser le tuyau, puis de rouvrir fd0 sur l'entrée standard (clavier) et d'attendre l'entrée de l'utilisateur?

1
user10097023 20 nov. 2018 à 14:06

3 réponses

Meilleure réponse

parce que la fonction foo a une entrée de pipeline, donc dans le processus enfant, l'entrée fd a été redirigée automatiquement vers le pipeline, il suffit de rediriger l'entrée standard vers le clavier (/ proc / pid / 0) après avoir obtenu l'entrée du pipeline, résoudra le problème

merci pour ces gars donnez-moi cet indice, ce n'est pas un problème de commande de lecture, c'est un problème fd acturaly

foo(){                  
local config

sleep 0.0001
read -t 0.0002 config

if [ -n "$config" ];then
config=$(cat -)
fi
echo "$config"
exec 3</dev/tty
read -t 10 -u 3 input
echo "success!"
}

une meilleure approche:

foo(){                  
local config

sleep 0.0001
read -t 0.0002 config

if [ -n "$config" ];then
config=$(cat -)
fi
exec 0<&-   ## close current pipeline input 
exec 0</dev/tty   ##reopen input fd with standard input 

read -t 10 input  ##read will wait for input for keyboard :) good !
echo "success!"
}

de plus, si je peux détecter que l'entrée actuelle est une entrée de tuyau ou standard, je ne pourrais pas utiliser read config pour juger s'il y a une entrée de pipeline, mais comment y parvenir? [-t 0] est une bonne idée

une meilleure approche:

foo(){                  
local config

if [ ! -t 0 ];then
    config=$(cat -)
    exec 0<&-   ## close current pipeline input 
    exec 0</dev/tty   ##reopen input fd with standard input
fi

read -t 10 input  ##read will wait for input for keyboard :) great !
echo "success!"
}
1
user10097023 21 nov. 2018 à 12:08

Il n'attend pas l'entrée car il a atteint la fin du tube.

echo "ok1" | ... écrit une seule ligne dans le tube, puis le ferme. Le premier read de la fonction lit ok1 dans var. Tous les autres appels read reviennent immédiatement car il n'y a plus de données à lire et aucune chance que d'autres données apparaissent plus tard car l'extrémité d'écriture du tube a déjà été fermée.

Si vous voulez que le tuyau reste ouvert, vous devez faire quelque chose comme

{ echo ok1; sleep 40; echo ok2; } | foo
1
melpomene 20 nov. 2018 à 11:14

En plus de la réponse de melpomene, vous pouvez voir ceci lors de l'exécution de la ligne suivante:

$ echo foo | { read -t 10 var1; echo $?; read -t 10 var2; echo $?; }
0
1
$ read -t 1 var; echo $?
142

Cette ligne affiche les codes de retour de read et les états manuels

Le code de retour est zéro, sauf si la fin du fichier est rencontrée, la lecture expire (auquel cas le code de retour est supérieur à 128), ou un descripteur de fichier non valide est fourni comme argument à -u

source: man bash

De cela, nous voyons que la deuxième lecture de la première commande échoue car EOF est atteint.

0
kvantour 20 nov. 2018 à 11:27