Bash:从文件读取标准输入并将标准输出写入文件

16

我正在尝试运行一个应用程序(比如说top),以便它从文件中读取stdin并将stdout写入另一个文件。

目前我有以下代码:

mkfifo stdin.pipe
(tail -f stdin.pipe) | top

如预期工作正常,因此我可以通过echo一些内容到该文件中,然后top将接收到它。 但是,我无法重定向top的输出。 我该如何实现?

编辑:

好的,让我们放弃top。 我正在使用这个进行测试:

cat test.sh

echo Say something
read something
echo you said $something

你确定 topstdin 读取吗?我的不是。你可以使用 -b(批处理)选项重定向 top 的输出:top -n 1 -b > gash - cdarke
@cdarke 对不起,你是对的。我正在使用另一个应用程序进行测试。 top 的工作方式不同。有没有办法将 stdin 和 stdout 映射到文件并使用它们来控制 cli 应用程序? - alexandernst
2个回答

51

我们可以忘记关于top的内容,它似乎是一个误导。

要将标准输入或输出映射到文件,您可以使用重定向:

some_program < input_file          # Redirects stdin

another_program > output_file      # Redirects stdout

或者甚至:

yet_another  < input_file > output_file

这是异步还是同步的?我刚用一个只有2行代码的Bash测试了一下,它会输出“你好”,等待输入,然后输出“再见”。当我将某些内容重定向到输入文件中(也就是应用程序完成运行时),我能够在输出文件中看到输出。 - alexandernst
如果您正在程序之间进行通信,那么请使用匿名管道,这比使用临时文件更有效。在这种情况下,同步/异步是什么意思取决于您的定义,但所有shell IO都是缓存的。每次重定向后都会清空缓冲区并关闭文件,但如果一个程序正在写入(到文件而不是管道),而另一个程序正在读取,则可能会出现问题。 - cdarke
问题在于我正在尝试从PHP控制CLI应用程序,因此无法保存管道的句柄,这就是为什么我需要能够读/写文件。如何强制输出刷新而不是进入缓冲区? - alexandernst
使用命名管道而不是文件,您可以像文件一样重定向到命名管道(嗯,实际上它就是一个文件)。您也可以像读取文本文件一样从PHP中读取命名管道。 - cdarke
你确定这个方法适用于我在问题中发布的示例脚本吗?(编辑部分)我只是创建了mkfifo“in”和“out”,然后运行了我的脚本。我期望在“cat out”之后得到“Say something”,但实际上没有得到任何东西。 - alexandernst
如何在达到文件结尾时自动退出脚本并接收输入。我处于无限循环中,当EOF被读取时无法跳出循环。 - Windy Day

8

有没有一种方法可以将stdin和stdout映射到文件并使用它们来控制cli应用程序?

听起来你正在寻找Bash 4.0中添加的协处理

coproc cat                    # Start cat in background
echo Hello >&${COPROC[1]}     # Say "Hello" to cat
read LINE <&${COPROC[0]}      # Read response
echo $LINE                    # cat replied "Hello"!

在4.0之前,您需要使用两个命名管道才能实现此功能。

有趣的补充! - hesham_EE

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接