(En BASH) Je veux qu'un sous-shell utilise un descripteur de fichier non-STDOUT non-STDERR pour transmettre certaines données au shell parent. Comment puis je faire ça? Finalement, j'aimerais enregistrer les données dans une variable du shell parent.
(
# The following two lines show the behavior of the subshell.
# We cannot change them.
echo "This should go to STDOUT"
echo "This is the data I want to pass to the parent Shell" >&3
)
#...
data_from_subshell=... # Somehow assign the value of &3 of the
# subshell to this variable
EDIT: le sous-shell exécute un programme de boîte noire qui écrit dans STDOUT et & 3.
ATTENTION, BASHISM AHEAD (il existe des shells posix qui sont nettement plus rapides que bash, par exemple ash ou dash, qui n'ont pas de substitution de processus).
Vous pouvez faire une danse de poignée pour déplacer la sortie standard d'origine vers un nouveau descripteur pour rendre la sortie standard disponible pour la tuyauterie (du haut de ma tête):
exec 3>&1 # creates 3 as alias for 1
run_in_subshell() { # just shortcut for the two cases below
echo "This goes to STDOUT" >&3
echo "And this goes to THE OTHER FUNCTION"
}
Vous devriez maintenant pouvoir écrire:
while read line; do
process $line
done < <(run_in_subshell)
mais la construction <()
est un bashisme. Vous pouvez le remplacer par un pipeline
run_in_subshell | while read line; do
process $line
done
sauf que la deuxième commande aussi s'exécute dans sous-shell , car toutes les commandes de pipeline faire.
La façon la plus simple est bien sûr de capturer la sortie directement dans le parent
data_from_subshell=$(echo "This is the data I want to pass to the parent Shell")
Vous pouvez utiliser un canal nommé comme un autre moyen de lire les données d'un enfant
mkfifo /tmp/fifo
vous pouvez maintenant rediriger l'enfant vers /tmp/fifo
(
echo "This should go to STDOUT"
echo "This is the data I want to pass to the parent Shell" >/tmp/fifo
) &
et le parent peut lire à partir de là
read data_from_subshell </tmp/fifo
Une autre façon consiste à utiliser coproc
pour démarrer un processus enfant. Cela crée un enfant avec un canal bidirectionnel et redirige les stdin et stdout de l'enfant vers les descripteurs de canal. Pour utiliser à la fois le canal et la sortie standard dans l'enfant, vous devez d'abord dupliquer la sortie standard dans le parent
exec 4>&1 # duplicate stdout for usage in client
coproc SUBSHELL (
exec 3>&1 1>&4- # redirect fd 3 to pipe, redirect fd 1 to stdout
(
echo "This should go to STDOUT"
echo "This is the data I want to pass to the parent Shell" >&3
)
)
exec 4>&- # close fd 4 in parent
read data <&${SUBSHELL[0]}
echo "Parent: $data"
Les coprocessus ont été introduits dans Bash 4.0.