打破无限循环

Mat*_*ner 5 bash loops cat

我在bash中运行此查询:

mkfifo resp
while true; do 
    sudo nc -l -p 80 < resp |
    (cat & echo -e "HTTP/1.1 200 OK\r\n\r\nhello :)" > resp) ||
    break; 
done
Run Code Online (Sandbox Code Playgroud)

然而,当我Ctrl+C,没有任何反应,终端锁定.

为什么?我究竟做错了什么?

Chr*_*lan 2

我无法在我的环境 (RHEL) 中重新创建它 - CTRL-C 在这方面对我来说效果很好。在您的终端锁定后,我会打开一个新终端并使用它strace -p来查看发生了什么。

不过,我认为命令设置总体上存在一些问题。

首先,您cat在子 shell 中处于后台。 这样做会生成stdin命令的cat/dev/null而不是nc您通过管道传输到子 shell 中的输出。您可以通过比较以下输出来看到差异:

#! /bin/bash
# doesn't print yay
while true; do
    echo yay |
    (cat & false) ||
    break
done
Run Code Online (Sandbox Code Playgroud)

有了这个:

#! /bin/bash
# does print yay
while true; do
    echo yay |
    (cat ; false) ||
    break
done
Run Code Online (Sandbox Code Playgroud)

另外,我不清楚这是否是有意的,但是循环的中断条件通常基于子 shell 的退出代码,而子 shell 的退出代码又将是 的退出代码echo,它总是会成功,所以一般来说,循环是无限的。您可以通过将false上述内容之一替换为以下内容来查看这一点echo

#! /bin/bash
while true; do
    echo yay |
    (cat & echo test) ||
    break
done
Run Code Online (Sandbox Code Playgroud)

而且,正如@chepner 指出的那样,您的使用nc一般也是不正确的。根据其联机帮助页:

-l      Used to specify that nc should listen for an incoming connection rather than initiate a connection to a remote host.  It is an error to use this option in conjunction with the -p, -s, or -z options.
Run Code Online (Sandbox Code Playgroud)

这实际上导致您的nc命令根本不执行任何操作(没有输出,只是坐在那里)。您可以通过mkfifo resp ; nc -l -p 80 < resp以 root 身份在一个 shell 中运行,然后echo -e "HTTP/1.1 200 OK\r\n\r\nhello :)" > resp以 root 身份在另一个 shell 中运行来看到这一点。

希望这可以帮助。