首页 > 解决方案 > Docker 容器中的管道和 grep 似乎被阻塞了

问题描述

我有一个简单的 bash 脚本,如下所示,它是 docker 映像的一部分。

test.sh,

#!/bin/bash

set -e

logit() {
    log_date=`date +"%F %T"`
    echo "[$log_date][INFO] $1"
}

waitForServerToStart() {
    while true; do
        logit "Testing .... 1"
        netstat -anpt
        logit "Testing .... 2"
        netstat -anpt | grep tcp
        logit "Testing .... 3"
        sleep 5
        logit "Testing .... 4"
    done
}

waitForServerToStart

run.sh,

#!/bin/sh

/test.sh &

# Run forever
while true; do sleep 5; done

Dockerfile,

FROM openjdk:8u191-jre-alpine3.9

COPY files/run.sh /
COPY files/test.sh /

CMD ["/run.sh"]

如果我运行这个容器,我只会得到以下输出,这让我相信不知何故grep,“管道”似乎被阻塞了。

[2019-03-06 11:10:45][INFO] Testing .... 1
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 172.17.0.2:58278        xxx.xxx.xx.xx:443     FIN_WAIT2   -
[2019-03-06 11:10:45][INFO] Testing .... 2 

有人可以对此有所了解吗?

如果我注释掉,它工作正常netstat -anpt | grep tcp。然后我会看到后续的日志行,它也会在循环中继续。

[2019-03-06 11:25:36][INFO] Testing .... 3
[2019-03-06 11:25:41][INFO] Testing .... 4

标签: bashdockergrep

解决方案


这个让我很疑惑!但我有一个解决方案给你:

使用 awk 代替 grep

test.sh使用这个代替:

netstat -anpt | awk /tcp/

使文件看起来像这样:

#!/bin/bash

set -e

logit() {
    log_date=`date +"%F %T"`
    echo "[$log_date][INFO] $1"
}

waitForServerToStart() {
    while true; do
        logit "Testing .... 1"
        netstat -anpt
        logit "Testing .... 2"
        netstat -anpt | awk /tcp/
        logit "Testing .... 3"
        sleep 5
        logit "Testing .... 4"
    done
}

waitForServerToStart

由于我无法解释的原因 -grep从脚本调用时从管道读取时不会返回。我在本地创建了您的容器,运行并输入了它 - 该命令netstat -anpt | grep tcp运行良好并退出。netstat -anpt | cat如果你在你的脚本中替换它test.sh,那么它也会通过就好了。

我到处寻找与您正在使用的发行版、版本等的容器中的 grep 有相同问题的人 - 但空手而归。

我相信这可能与 grep 等待一个永远不会登陆的 EOF 角色有关——但我不确定。


推荐阅读