11

我必须编写脚本:

#!/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 小时后,整个系统停止工作。我已经输入了一些登录信息,但脚本似乎不再反应了。但是当我;

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 机器……

我已经插入了一些登录信息,这是结果;

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)

谢谢

4

6 回答 6

6

如果包括 netcat 在内的所有命令都没有从标准输入读取输入,则可以完全使其独立于终端运行。有时,仍然依赖于终端的后台进程在尝试从后台读取输入时会暂停 (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"
于 2013-08-13T18:09:52.080 回答
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循环将能够在子外壳上运行并保持外for循环安全,以防万一它崩溃。while此外,在循环之外并没有真正需要的变量。

我现在实际上有了这样的想法,即问题实际上可能与输入以及while read line; do ...; done块如何处理它而不是 netcat 本身有关。您的变量在 "" 周围没有被正确引用可能是其中之一,或者可能是您的 netcat 崩溃的实际原因。

于 2013-08-12T10:21:55.423 回答
3

您提到“大约 12 小时后,整个系统停止工作” - 脚本很可能正在执行您所拥有的任何内容[start a command]并且正在膨胀内存。您确定[start a command]不会非常频繁地分叉许多进程并释放内存吗?

于 2013-08-11T21:38:18.080 回答
3

我经常遇到使用ncor的奇怪行为netcat。你应该看看ncat它几乎是同一个工具,但它在所有平台上的行为都是一样的(nc并且netcat根据 distri、linux、BSD、Mac 的不同表现不同)。

于 2013-08-11T21:44:36.090 回答
2

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

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

我对您的解决方案是将 netcat 的输出通过管道传输到 sed,然后将该(大大减少的)行传输到 read 内置...

#!/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 兼容,但是,调用您的 script2.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

于 2013-08-15T22:03:34.923 回答
1

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

可能是它连接到自己的端口,几个小时后缺少一些资源?

于 2013-08-07T15:17:31.877 回答