bash 如何将子shell的输出文件描述符重定向到父shell中的输入文件描述符?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15153158/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to redirect an output file descriptor of a subshell to an input file descriptor in the parent shell?
提问by user716468
(In BASH) I want a subshell to use a non-STDOUT non-STDERR file descriptor to pass some data back to the parent shell. How can I do that? Eventually I would love to save the data into some variable of the parent shell.
(在 BASH 中)我希望子 shell 使用非 STDOUT 非 STDERR 文件描述符将一些数据传递回父 shell。我怎样才能做到这一点?最终,我希望将数据保存到父 shell 的某个变量中。
(
# 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: The subshell runs a black-box program that writes to STDOUT and &3.
编辑:子外壳运行一个黑盒程序,该程序写入 STDOUT 和 &3。
采纳答案by Jan Hudec
BEWARE, BASHISM AHEAD(there are posix shells that are significantly faster than bash, e.g. ash or dash, that don't have process substitution).
当心,BASHISM AHEAD(有比 bash 快得多的 posix shell,例如 ash 或 dash,它们没有进程替换)。
You can do a handle dance to move original standard output to a new descriptor to make standard output available for piping (from the top of my head):
您可以执行手柄舞将原始标准输出移动到新描述符,以使标准输出可用于管道(从我的头顶):
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"
}
Now you should be able to write:
现在你应该可以写:
while read line; do
process $line
done < <(run_in_subshell)
but the <()
construct is a bashism. You can replace it with pipeline
但这种<()
结构是一种bashism。你可以用管道替换它
run_in_subshell | while read line; do
process $line
done
except than the second command alsoruns in subshell, because all commands in pipeline do.
除了第二个命令也在subshell 中运行,因为管道中的所有命令都可以。
回答by Olaf Dietsche
The easiest way of course, is to capture the output directly in the parent
最简单的方法当然是直接在 parent 中捕获输出
data_from_subshell=$(echo "This is the data I want to pass to the parent shell")
You can use a named pipe as an alternative way to read data from a child
您可以使用命名管道作为从子级读取数据的替代方法
mkfifo /tmp/fifo
now you can redirect the child to /tmp/fifo
现在您可以将孩子重定向到 /tmp/fifo
(
echo "This should go to STDOUT"
echo "This is the data I want to pass to the parent shell" >/tmp/fifo
) &
and the parent can read from there
父母可以从那里阅读
read data_from_subshell </tmp/fifo
Another way is to use coproc
to start a child process. This creates a child with a bidirectional pipe and redirects the child's stdin and stdout to the pipe descriptors. To use both the pipe and stdout in the child, you must duplicate stdout in the parent first
另一种方法是使用coproc
启动子进程。这将创建一个具有双向管道的子级,并将子级的 stdin 和 stdout 重定向到管道描述符。要在子进程中同时使用管道和标准输出,您必须首先在父进程中复制标准输出
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"
Coprocesses were introduced in Bash 4.0.
协进程是在 Bash 4.0 中引入的。