Подтвердить что ты не робот

Как получить PID процесса, который передается на другой процесс в Bash?

Я пытаюсь реализовать простой сервер журнала в Bash. Он должен взять файл в качестве параметра и выполнить его на порту с netcat.

( tail -f $1 & ) | nc -l -p 9977

Но проблема в том, что когда netcat завершается, хвост остается за ходом. (Уточнение: если я не откажу хвостовой процесс, он будет продолжать работать вечно, даже netcat завершается.)

Если я каким-то образом узнаю ПИД хвоста, тогда я могу его убить потом. Очевидно, используя $! вернет PID netcat.

Как я могу получить PID хвостового процесса?

4b9b3361

Ответ 1

Записать хвостовой идентификатор PID в дескриптор файла 3, а затем зафиксировать его оттуда.

( tail -f $1 & echo $! >&3 ) 3>pid | nc -l -p 9977
kill $(<pid)

Ответ 2

Другой вариант: используйте перенаправление к подоболочке. Это изменяет порядок запуска фоновых процессов, поэтому $! дает PID процесса tail.

tail -f $1 > >(nc -l -p 9977) &
wait $!

Ответ 3

как насчет этого:

jobs -x echo %1

%1 для первого задания в цепочке, %2 для второго и т.д. jobs -x заменяет спецификатор задания на PID.

Ответ 4

Это работает для меня (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.

Ответ 5

Возможно, вы могли бы использовать 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

Ответ 6

Наконец, мне удалось найти хвостовой процесс, используя 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

Ответ 7

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

Ответ 8

Один из способов - просто сделать ps -ef и grep для хвоста с помощью script ppid

Ответ 9

Вы пробовали:

nc -l -p 9977 -c "tail -f $1"

(непроверенные)

Или -e с файлом сценария, если ваш nc не имеет -c. Возможно, вам понадобится nc, который был скомпилирован с опцией GAPING_SECURITY_HOLE. Да, вы должны вывести соответствующие оговорки из этого имени опции.

Ответ 10

Вы можете сохранить 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

Ответ 11

Не идеальный ответ, но я нашел обходной путь для демона 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

Ответ 12

Вариант -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