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

2 つのスクリプトを「/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

read コマンドは、変更されていない行を読み取るため、この形式でも優れている可能性があります。

... | while IFS= read -r line

| while ...プロセス置換の使用を提案する人もいますが、この方法を使用すると、ループがサブシェルで実行され、クラッシュした場合に備えwhileて外側のループを安全に保つことができるため、今回はお勧めしません。その上、ループの外側で必要となるループforからの変数は実際にはありません。while

私は実際に、問題が実際には入力に関連していて、while read line; do ...; doneブロックがnetcat 自体ではなくそれを処理する方法に関連していた可能性があるという考えを持っています。あなたの変数が "" の周りで適切に引用されていないのは、その 1 つかもしれませんし、おそらくnetcat がクラッシュする実際の理由かもしれません。

于 2013-08-12T10:21:55.423 に答える
3

約 12 時間後、システム全体が機能しなくなる」とおっしゃっていましたが、スクリプトが実行中のものを実行していて[start a command]、メモリが肥大化している可能性があります。[start a command]多くのプロセスを非常に頻繁に分岐させたり、メモリを解放したりしていませんか?

于 2013-08-11T21:38:18.080 に答える
3

ncまたはで奇妙な動作を経験することがよくありnetcatます。ncatほとんど同じツールですが、すべてのプラットフォームで同じように動作します (ディストリビューション、Linux、BSD、Mac によって動作が異なります) ncnetcat

于 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 をすべてのアドレス 0.0.0.0 にバインドする代わりに、監視している特定の IP にバインドできると思います

于 2013-08-15T22:03:34.923 に答える