bash 实时从标准输出读取内容
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17545750/
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
Read content from stdout in realtime
提问by Oskar Birkne
I have an external device that I need to power up and then wait for it to get started properly. The way I want to do this is by connecting to it via serial port (via Plink which is a command-line tool for PuTTY) and read all text lines that it prints and try to find the text string that indicates that it has been started properly. When that text string is found, the script will proceed.
我有一个外部设备,需要打开电源,然后等待它正常启动。我想要这样做的方法是通过串行端口连接到它(通过 Plink,它是 PuTTY 的命令行工具)并读取它打印的所有文本行并尝试找到指示它已启动的文本字符串适当地。找到该文本字符串后,脚本将继续执行。
The problem is that I need to read these text lines in real-time. So far, I have only seen methods for calling a command and then process its output when that command is finished. Alternatively, I could let Plink run in the background by appending an & to the command and redirecting the output to a file. But the problem is that this file will be empty from the beginning so the script will just proceed directly. Is there maybe a way to wait for a new line of a certain file and read it once it comes? Or does anyone have any other ideas how to accomplish this?
问题是我需要实时阅读这些文本行。到目前为止,我只看到了调用命令然后在该命令完成时处理其输出的方法。或者,我可以通过将 & 附加到命令并将输出重定向到文件来让 Plink 在后台运行。但问题是这个文件从一开始就是空的,所以脚本会直接继续。有没有办法等待某个文件的新行并在它出现时读取它?或者有没有人有任何其他想法如何实现这一目标?
Here is the best solution I have found so far:
这是我迄今为止找到的最佳解决方案:
./plink "connection_name" > new_file &
sleep 10 # Because I know that it will take a little while before the correct text string pops up but I don't know the exact time it will take...
while read -r line
do
# If $line is the correct string, proceed
done < new_file
However, I want the script to proceed directly when the correct text string is found.
但是,我希望脚本在找到正确的文本字符串时直接进行。
So, in short, is there any way to access the output of a command continously before it has finished executing?
那么,简而言之,有没有办法在命令完成执行之前连续访问它的输出?
回答by gniourf_gniourf
This might be what you're looking for:
这可能是您要找的:
while read -r line; do
# do your stuff here with $line
done < <(./plink "connection_name")
And if you need to sleep 10:
如果您需要sleep 10:
{
sleep 10
while read -r line; do
# do your stuff here with $line
done
} < <(./plink "connection_name")
The advantage of this solution compared to the following:
与以下解决方案相比,此解决方案的优势在于:
./plink "connection_name" | while read -r line; do
# do stuff here with $line
done
(that I'm sure someone will suggest soon) is that the whileloop is not run in a subshell.
(我相信很快有人会建议)是while循环不是在子shell中运行的。
The construct <( ... )is called Process Substitution.
该构造<( ... )称为Process Substitution。
Hope this helps!
希望这可以帮助!
回答by chepner
Instead of using a regular file, use a named pipe.
不要使用常规文件,而是使用命名管道。
mkfifo new_file
./plink "connection_name" > new_file &
while read -r line
do
# If $line is the correct string, proceed
done < new_file
The whileloop will block until there is something to read from new_file, so there is no need to sleep.
该while循环将阻塞,直到有东西从阅读new_file,所以没有必要的睡眠。
(This is basically what process substitution does behind the scenes, but doesn't require any special shell support; POSIX shell does not support process substitution.)
(这基本上是进程替换在幕后所做的,但不需要任何特殊的 shell 支持;POSIX shell 不支持进程替换。)
Newer versions of bash(4.2 or later) also support an option to allow the final command of a pipeline to execute in the current shell, making the simple solution
较新版本bash(4.2 或更高版本)还支持允许管道的最终命令在当前 shell 中执行的选项,从而使解决方案变得简单
shopt +s lastpipe
./plink "connection_name" | while read -r line; do
# ...
done
possible.
可能的。

