66

Bashに単純なログサーバーを実装しようとしています。パラメータとしてファイルを受け取り、netcatを使用してポートで提供する必要があります。

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

しかし、問題は、netcatが終了すると、テールが実行されたままになることです。(明確化:テールプロセスをフォークしないと、netcatが終了しても永久に実行され続けます。)

どういうわけか尾のPIDを知っていれば、後でそれを殺すことができます。
明らかに、$を使用します!netcatのPIDを返します。

テールプロセスのPIDを取得するにはどうすればよいですか?

4

14 に答える 14

57

別のオプション: サブシェルへのリダイレクトを使用します。これにより、バックグラウンド プロセスが開始される順序が変更されるため、$! プロセスの PID を与えtailます。

tail -f $1 > >(nc -l -p 9977) &
wait $!
于 2011-11-08T09:47:49.767 に答える
50

tail の PID をファイル記述子 3 に書き込み、そこからキャプチャします。

( tail -f $1 & echo $! >&3 ) 3>pid | nc -l -p 9977
kill $(<pid)
于 2010-09-24T12:15:38.720 に答える
20

これはどう:

jobs -x echo %1

%1チェーン内の最初のジョブ、%22 番目などjobs -xです。ジョブ指定子を PID に置き換えます。

于 2012-01-18T09:38:33.440 に答える
13

これは私にとってはうまくいきます(SLES Linux):

tail -F xxxx | tee -a yyyy &
export TAIL_PID=`jobs -p`
# export TEE_PID="$!"

ps|grep|killユーザーが同じマシンで 2 つの「インスタンス」に対してスクリプトを実行できる場合、このスレッドで言及されているトリックは機能しません。

jobs -x echo %1私にはうまくいきませんでした(manページに-xフラグがありません)が、試してみることにしましたjobs -p

于 2012-08-20T16:19:54.087 に答える
7

たぶん、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
于 2009-10-30T22:59:15.040 に答える
2

最後に、を使用してテールプロセスを見つけることができましたps。ennuikillerからのアイデアに感謝します。

私はps、引数からテールをgrepして、それを強制終了するために使用しました。それは一種のハックですが、うまくいきました。:)

あなたがより良い方法を見つけることができるならば、共有してください。

完全なスクリプトは次のとおりです
(最新バージョンはここにあります: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
于 2009-10-31T12:08:25.690 に答える
2

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
于 2011-07-07T08:59:10.297 に答える
1

1つの方法は、スクリプトppidを使用してテールに対してps-efとgrepを実行することです。

于 2009-10-30T22:49:16.140 に答える
1

理想的な答えではありませんが、私が取り組んだロガーデーモンの回避策を見つけました:

#!/bin/sh
tail -f /etc/service/rt4/log/main/current --pid=$$ | grep error

$info 末尾から:

--pid=PID
          with -f, terminate after process ID, PID dies
于 2012-07-24T01:48:41.520 に答える
1

やってみました:

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

(未テスト)

または、持っていない-e場合はスクリプトファイルを使用します。オプションでコンパイルされた が必要な場合があります。はい、そのオプション名から適切な警告を推測する必要があります。nc-cncGAPING_SECURITY_HOLE

于 2009-10-30T23:50:38.833 に答える
1

bobbogo answerは機能しますが、中間のpid ファイルが必要です。

同様に機能するプロセス置換機能 を利用できますが、終了を待つ必要はありません>()|tail

tail -f $1 > >(nc -l -p 9977) & pid=!
于 2020-05-13T11:53:19.023 に答える
1

tailBash I/O リダイレクトのみを使用して、コマンドの pid を変数に格納できます (パイプラインでプロセスの 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
于 2011-09-18T17:44:14.897 に答える
0

tail の --pid オプションは、ここでの親友です。バックグラウンドで実行されているパイプラインを完全に制御できます。ファイルが別のプロセスによってアクティブにローテーションされ、非アクティブな inode をテーリングする可能性がある場合に備えて、回復力を高めるために tail コマンド オプションをお読みください。以下の例は、データの処理には使用されていませんが、テールに「課された」制限と、いつでも終了するように指示する機能を示しています。これは、 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
于 2015-01-09T13:29:32.653 に答える