linux script with netcat stops working after x hours linux script with netcat stops working after x hours linux linux

linux script with netcat stops working after x hours


If none of your commands including netcat reads input from stdin you can completely make it run independent of the terminal. Sometimes background process that are still dependent on the terminal pauses (S) when they try to read input from it on a background. Actually since you're running a daemon, you should make sure that none of your commands reads input from it (terminal).

#!/bin/bashset +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"

And I think we could try the logging thing again:

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 1sdisown "$TASKPID"


About the loop it could look like this.

#!/bin/bashfor (( ;; ))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 4sdone

with added double quotes to keep it safer.

And you could try capturing errors and add some logging with this format:

#!/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

Your read command could also be better in this format since it would read lines unmodified:

... | while IFS= read -r line

Some could also suggest the use of process substitution but I don't recommend it this time since through the | while ... method the while loop would be able to run on a subshell and keep the outer for loop safe just in case it crashes. Besides there isn't really a variable from the while loop that would be needed outside of it.

I'm actually having the idea now that the issue might actually have been related to the input and how the while read line; do ...; done block handles it and not netcat itself. Your variables not being quoted properly around "" could be one of it, or could probably be the actual reason why your netcat is crashing.


You mentioned "after around 12 hours, the whole system stops working" - It is likely that the scripts are executing whatever you have in [start a command] and is bloating the memory. Are you sure the [start a command] is not forking out many processes very frequently and releasing memory?