使用netcat的linux脚本在x小时后停止工作

时间:2013-08-07 13:53:18

标签: linux bash raspberry-pi netcat

我必须要脚本:

#!/bin/bash

netcat -lk -p 12345 | while read line
do
    match=$(echo $line | grep -c 'Keep-Alive')
    if [ $match -eq 1 ]; then
        [start a command]
    fi
done

#!/bin/bash

netcat -lk -p 12346 | while read line
do
    match=$(echo $line | grep -c 'Keep-Alive')
    if [ $match -eq 1 ]; then
        [start a command]
    fi
done

我把两个脚本放在'/etc/init.d /'

当我重新启动我的Linux机器(RasbPi)时,两个脚本都可以正常工作。

我已经尝试了20次,他们一直都很好。

但是大约12个小时后,整个系统停止工作。我已经添加了一些loggin,但似乎脚本不再响应了。但是当我;

ps aux

我可以看到脚本仍在运行:

root      1686  0.0  0.2   2740  1184 ?        S    Aug12   0:00 /bin/bash /etc/init.d/script1.sh start
root      1689  0.0  0.1   2268   512 ?        S    Aug12   0:00 netcat -lk 12345
root      1690  0.0  0.1   2744   784 ?        S    Aug12   0:00 /bin/bash /etc/init.d/script1.sh start
root      1691  0.0  0.2   2740  1184 ?        S    Aug12   0:00 /bin/bash /etc/init.d/script2.sh start
root      1694  0.0  0.1   2268   512 ?        S    Aug12   0:00 netcat -lk 12346
root      1695  0.0  0.1   2744   784 ?        S    Aug12   0:00 /bin/bash /etc/init.d/script2.sh start

重新启动后,他们再次开始工作......但这是一个罪过,定期重启Linux机器......

我已插入一些loggin,这是结果;

Listening on [0.0.0.0] (family 0, port 12345)
[2013-08-14 11:55:00] Starting loop.
[2013-08-14 11:55:00] Starting netcat.
netcat: Address already in use
[2013-08-14 11:55:00] Netcat has stopped or crashed.
[2013-08-14 11:49:52] Starting loop.
[2013-08-14 11:49:52] Starting netcat.
Listening on [0.0.0.0] (family 0, port 12345)
Connection from [16.8.94.19] port 12345 [tcp/*] accepted (family 2, sport 6333)
Connection closed, listening again.
Connection from [16.8.94.19] port 12345 [tcp/*] accepted (family 2, sport 6334)
[2013-08-14 12:40:02] Starting loop.
[2013-08-14 12:40:02] Starting netcat.
netcat: Address already in use
[2013-08-14 12:40:02] Netcat has stopped or crashed.
[2013-08-14 12:17:16] Starting loop.
[2013-08-14 12:17:16] Starting netcat.
Listening on [0.0.0.0] (family 0, port 12345)
Connection from [16.8.94.19] port 12345 [tcp/*] accepted (family 2, sport 6387)
Connection closed, listening again.
Connection from [16.8.94.19] port 12345 [tcp/*] accepted (family 2, sport 6388)
[2013-08-14 13:10:08] Starting loop.
[2013-08-14 13:10:08] Starting netcat.
netcat: Address already in use
[2013-08-14 13:10:08] Netcat has stopped or crashed.
[2013-08-14 12:17:16] Starting loop.
[2013-08-14 12:17:16] Starting netcat.
Listening on [0.0.0.0] (family 0, port 12345)
Connection from [16.8.94.19] port 12345 [tcp/*] accepted (family 2, sport 6167)
Connection closed, listening again.
Connection from [16.8.94.19] port 12345 [tcp/*] accepted (family 2, sport 6168)

由于

6 个答案:

答案 0 :(得分:5)

关于循环它可能看起来像这样。

#!/bin/bash

for (( ;; ))
do
    netcat -lk -p 12345 | while read line
    do
        match=$(echo "$line" | grep -c 'Keep-Alive')
        if [ "$match" -eq 1 ]; then
            [start a command]
        fi
    done
    sleep 4s
done

添加双引号以使其更安全。

您可以尝试捕获错误并使用以下格式添加一些日志记录:

#!/bin/bash

{
    echo "[$(date "+%F %T")] Starting loop."

    for (( ;; ))
    do
        echo "[$(date "+%F %T")] Starting netcat."

        netcat -lk -p 12345 | while read line
        do
            match=$(echo "$line" | grep -c 'Keep-Alive')
            if [ "$match" -eq 1 ]; then
                [start a command]
            fi
        done

        echo "[$(date "+%F %T")] Netcat has stopped or crashed."

        sleep 4s
    done
} >> "/var/log/something.log" 2>&1

您的读取命令在这种格式下也可能更好,因为它会读取未经修改的行:

... | while IFS= read -r line

有些人也可以建议使用进程替换,但我这次不建议使用,因为通过| while ...方法,while循环可以在子shell上运行并保留外部{ {1}}循环安全以防它崩溃。此外,实际上并不存在for循环中需要的变量。

我实际上已经知道这个问题可能实际上与输入有关, while 块如何处理它而不是netcat本身。您的变量未被正确引用可能是其中之一,或者可能是实际原因为什么您的netcat崩溃。

答案 1 :(得分:5)

如果你的命令没有包括netcat从stdin读取输入,你可以完全使它独立于终端运行。有时,仍然依赖于终端的后台进程在尝试从后台读取输入时会暂停(S)。实际上,因为你正在运行一个守护进程,你应该确保没有任何命令从它(终端)读取输入。

#!/bin/bash

set +o monitor # Make sure job control is disabled.

(
    : # Make sure the shell runs a subshell.
    exec netcat -lk -p 12345 | while read line  ## Use exec to overwrite the subshell.
    do
        match=$(echo $line | grep -c 'Keep-Alive')
        if [ $match -eq 1 ]; then
            [start a command]
        fi
    done
) <&- >&- 2>&- </dev/null &>/dev/null &

TASKPID=$!
sleep 1s ## Let the task initialize a bit before we disown it.
disown "$TASKPID"

我认为我们可以再次尝试记录事件:

set +o monitor

(
    echo "[$(date "+%F %T")] Starting loop with PID $BASHPID."

    for (( ;; ))
    do
        echo "[$(date "+%F %T")] Starting netcat."

        netcat -vv -lk -p 12345 | while read line
        do
            match=$(echo "$line" | grep -c 'Keep-Alive')
            if [ "$match" -eq 1 ]; then
                [start a command]
            fi
        done

        echo "[$(date "+%F %T")] Netcat has stopped or crashed."

        sleep 4s
    done
) <&- >&- 2>&- </dev/null >> "/var/log/something.log" 2>&1 &

TASKPID=$!
sleep 1s
disown "$TASKPID"

答案 2 :(得分:3)

你提到“大约12个小时之后,整个系统停止工作” - 脚本可能正在执行[start a command]中的任何内容,并使内存膨胀。你确定[start a command]不是经常分发许多进程并释放内存吗?

答案 3 :(得分:3)

我经常遇到ncnetcat的奇怪行为。您应该看一下ncat几乎相同的工具,但它在所有平台上的行为都相同(ncnetcat表现不同,具体取决于distri,linux,BSD,Mac)。 / p>

答案 4 :(得分:2)

定期netcat将打印,而不是一行,而是一块二进制数据。因此,内置读取可能会失败。

我认为您正在使用此程序验证远程主机是否仍连接到端口12345和12346并且尚未重新启动。

我的解决方案是将netcat的输出传递给sed,然后将那个(大大减少的)一行传递给read builtin ...

#!/bin/bash

{
    echo "[$(date "+%F %T")] Starting loop."

    for (( ;; ))
    do
        echo "[$(date "+%F %T")] Starting netcat."

        netcat -lk -p 12345 | sed 's/.*Keep-Alive.*/Keep-Alive/g' | \
        \
        while read line
        do
            match=$(echo "$line" | grep -c 'Keep-Alive')
            if [ "$match" -eq 1 ]; then
                [start a command]
            fi
        done

        echo "[$(date "+%F %T")] Netcat has stopped or crashed."

        sleep 4s
    done
} >> "/var/log/something.log" 2>&1

此外,您需要查看/etc/init.d中的一些其他启动程序,以确保它们与系统使用的任何版本的rc兼容,但是,调用您的脚本2会容易得多.sh从init.d中的一些简单文件的副本。目前,script2是启动脚本,但不符合您使用的init包。

这听起来更复杂,我的意思是......让我更好地解释一下:

/etc/init.d/syslogd        ## a standard init script that calls syslogd
/etc/init.d/start-monitor   ## a copy of a standard init script that calls script2.sh

作为补充说明,我认为您可以将netcat绑定到您正在监视的特定IP,而不是将其绑定到所有地址0.0.0.0

答案 5 :(得分:1)

如果您要等待传入的连接请求,则不能使用-p选项。 (参见nc的手册页)Hostname和Port是命令行的最后两个参数。

可能是它连接到自己的端口,几个小时后会丢失一些资源吗?