Linux script с отключением netcat после x часов
У меня есть сценарии:
#!/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)
Спасибо
Ответы
Ответ 1
О цикле это может выглядеть так.
#!/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 сбой.
Ответ 2
Если ни одна из ваших команд, включая 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"
Ответ 3
Вы упомянули "примерно через 12 часов, вся система перестает работать". Вероятно, скрипты выполняют все, что у вас есть, в [start a command]
и раздувают память. Вы уверены, что [start a command]
не очень часто вызывает много процессов и освобождает память?
Ответ 4
Я часто испытывал странное поведение с nc
или netcat
. Вы должны взглянуть на ncat
почти такой же инструмент, но он ведет себя одинаково на всех платформах (nc
и netcat
ведут себя по-разному в зависимости от дистрибутива, linux, BSD, Mac).
Ответ 5
Периодически 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. Поскольку это сценарий2, это запуск script, но не соответствует используемому пакету 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
Ответ 6
вы не можете использовать опцию -p в случае, если вы будете ждать входящего запроса на соединение.
(см. справочную страницу nc) Имя хоста и порт - последние два аргумента командной строки.
Может быть, он подключается к собственному порту, и через несколько часов отсутствует какой-то ресурс?