具有非阻塞读取的 Bash 脚本

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4874993/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 23:23:05  来源:igfitidea点击:

Bash script with non-blocking read

bashscriptingnonblocking

提问by michelemarcon

I want to send some data to a root process with a named pipe. Here is the script and it works great:

我想使用命名管道将一些数据发送到根进程。这是脚本,效果很好:

#!/bin/sh
pipe=/tmp/ntp

if [[ ! -p $pipe ]]; then
    mknod -m 666 $pipe p
fi

while true
do
    if read line <$pipe; then
         /root/netman/extra/bin/ntpclient -s -h $line > $pipe 2>&1
    fi
done

I actually have several script like this one. I would like to enclose all of them in a single script. The problem is that execution blocks on the first "read" and I cannot execute multiple "reads" in a single process. Isn't there anything I can do? Is it possible to have a "non-blocking" bash read?

我实际上有几个这样的脚本。我想将所有这些都包含在一个脚本中。问题是执行在第一次“读取”时阻塞,我无法在单个进程中执行多个“读取”。我没有什么可以做的吗?是否可以读取“非阻塞”bash?

采纳答案by michelemarcon

Just put the reading cycle into background (add & after done)?

只是将阅读周期置于后台(添加和完成后)?

回答by gabuzo

Bash's read embedded command has a -t parameter to set a timeout:

Bash 的 read 嵌入命令有一个 -t 参数来设置超时:

-t timeout
    Cause read to time out and return failure if a complete line of input is not
    read within timeout seconds. This option has no effect if read is not reading
    input from the terminal or a pipe.

This should help you solve this issue.

这应该可以帮助您解决此问题。

Edit:

编辑:

There are some restrictions for this solution to work as the man page indicates: This option has no effect if read is not reading input from the terminal or a pipe.

此解决方案的工作有一些限制,如手册页所示:如果 read 不是从终端或管道读取输入,则此选项无效。

So if I create a pipe in /tmp:

因此,如果我在 /tmp 中创建一个管道:

mknod /tmp/pipe p

Reading directly from the pipe is not working:

直接从管道读取不起作用:

$ read -t 1 </tmp/pipe  ; echo $?

Hangs forever.

永远挂起。

$ cat /tmp/pipe | ( read -t 1 ; echo $? )
1

It is working but cat is not exiting.

它正在工作,但 cat 没有退出。

A solution is to assign the pipe to a file descriptor:

一种解决方案是将管道分配给文件描述符:

$ exec 7<>/tmp/pipe

And then read from this file descriptor either using redirection:

然后使用重定向从这个文件描述符中读取:

$ read -t 1 <&7  ; echo $?
1

Or the -uoption of read:

或以下-u选项read

$ read -t 1 -u 7  ; echo $?
1

回答by Foo Bah

You can use stty to set a timeout. IIRC its something like

您可以使用 stty 设置超时。IIRC它就像

stty -F $pipe -icanon time 0