Ответ 1
Записать хвостовой идентификатор PID в дескриптор файла 3, а затем зафиксировать его оттуда.
( tail -f $1 & echo $! >&3 ) 3>pid | nc -l -p 9977
kill $(<pid)
Я пытаюсь реализовать простой сервер журнала в Bash. Он должен взять файл в качестве параметра и выполнить его на порту с netcat.
( tail -f $1 & ) | nc -l -p 9977
Но проблема в том, что когда netcat завершается, хвост остается за ходом. (Уточнение: если я не откажу хвостовой процесс, он будет продолжать работать вечно, даже netcat завершается.)
Если я каким-то образом узнаю ПИД хвоста, тогда я могу его убить потом. Очевидно, используя $! вернет PID netcat.
Как я могу получить PID хвостового процесса?
Записать хвостовой идентификатор PID в дескриптор файла 3, а затем зафиксировать его оттуда.
( tail -f $1 & echo $! >&3 ) 3>pid | nc -l -p 9977
kill $(<pid)
Другой вариант: используйте перенаправление к подоболочке. Это изменяет порядок запуска фоновых процессов, поэтому $! дает PID процесса tail
.
tail -f $1 > >(nc -l -p 9977) &
wait $!
как насчет этого:
jobs -x echo %1
%1
для первого задания в цепочке, %2
для второго и т.д. jobs -x
заменяет спецификатор задания на PID.
Это работает для меня (SLES Linux):
tail -F xxxx | tee -a yyyy &
export TAIL_PID=`jobs -p`
# export TEE_PID="$!"
Тройка ps|grep|kill
, упомянутая в этом потоке, не будет работать, если пользователь может запустить script для двух "экземпляров" на одной машине.
jobs -x echo %1
не работал у меня (man-страница не имела флага -x
), но мне предложили попробовать jobs -p
.
Возможно, вы могли бы использовать fifo, чтобы вы могли захватить pid первого процесса, например:
FIFO=my_fifo
rm -f $FIFO
mkfifo $FIFO
tail -f $1 > $FIFO &
TAIL_PID=$!
cat $FIFO | nc -l -p 9977
kill $TAIL_PID
rm -f $FIFO
Наконец, мне удалось найти хвостовой процесс, используя ps
. Благодаря идее эннуикиллера.
Я использовал ps
для grep хвоста из args и убил его. Это своего рода хак, но это сработало.:)
Если вы можете найти лучший способ, поделитесь им.
Вот полный script:
(Последнюю версию можно найти здесь: http://docs.karamatli.com/dotfiles/bin/logserver)
if [ -z "$1" ]; then
echo Usage: $0 LOGFILE [PORT]
exit -1
fi
if [ -n "$2" ]; then
PORT=$2
else
PORT=9977
fi
TAIL_CMD="tail -f $1"
function kill_tail {
# find and kill the tail process that is detached from the current process
TAIL_PID=$(/bin/ps -eo pid,args | grep "$TAIL_CMD" | grep -v grep | awk '{ print $1 }')
kill $TAIL_PID
}
trap "kill_tail; exit 0" SIGINT SIGTERM
while true; do
( $TAIL_CMD & ) | nc -l -p $PORT -vvv
kill_tail
done
ncat
автоматически завершает tail -f
при выходе (в Mac OS X 10.6.7)!
# simple log server in Bash using ncat
# cf. http://nmap.org/ncat/
touch file.log
ncat -l 9977 -c "tail -f file.log" </dev/null # terminal window 1
ncat localhost 9977 </dev/null # terminal window 2
echo hello > file.log # terminal window 3
Один из способов - просто сделать ps -ef и grep для хвоста с помощью script ppid
Вы пробовали:
nc -l -p 9977 -c "tail -f $1"
(непроверенные)
Или -e
с файлом сценария, если ваш nc
не имеет -c
. Возможно, вам понадобится nc
, который был скомпилирован с опцией GAPING_SECURITY_HOLE
. Да, вы должны вывести соответствующие оговорки из этого имени опции.
Вы можете сохранить pid команды tail
в переменной, используя только перенаправления ввода/вывода Bash (см. Как получить PID процесса в конвейере).
# terminal window 1
# using nc on Mac OS X (FreeBSD nc)
: > /tmp/foo
PID=$( { { tail -f /tmp/foo 0<&4 & echo $! >&3 ; } 4<&0 | { nc -l 9977 ;} & } 3>&1 | head -1 )
kill $PID
# terminal window 2
nc localhost 9977
# terminal window 3
echo line > /tmp/foo
Не идеальный ответ, но я нашел обходной путь для демона logger, над которым я работал:
#!/bin/sh
tail -f /etc/service/rt4/log/main/current --pid=$$ | grep error
from $info tail:
--pid=PID
with -f, terminate after process ID, PID dies
Вариант -pid для хвоста - ваш лучший друг здесь. Это позволит вам полностью контролировать работу трубопровода в фоновом режиме. прочитайте параметры команды tail для большей устойчивости, если ваш файл активно повернут другим процессом, который может оставить вас в хвосте неактивного inode. Пример ниже, хотя и не используется для обработки данных, демонстрирует "наложенное" ограничение на хвост и способность сказать ему выйти в любое время. Это используется для измерения рабочего давления на httpd.
# Set the tail to die in 100 second even if we die unexpectedlly.
sleep 100 & ; ctlpid=$!
tail -q -n 0 --follow=name --retry --max-unchanged-stats=1 --pid=$ctlpid -f /var/log/httpd/access_log 2>/dev/null | wc –l > /tmp/thisSampleRate &
…. Do some other work
…. Can kill the pipe at any time by killing $ctlpid
…. Calculate preassure if /tmp/thisSampleRate is ready