Bashに単純なログサーバーを実装しようとしています。ファイルをパラメーターとして受け取り、netcatを使用してポートで提供する必要があります。
( tail -f $1 & ) | nc -l -p 9977
しかし問題は、netcatが終了すると、tailが実行されたままになることです。 (明確化:テールプロセスをフォークしない場合、netcatが終了しても、テールプロセスは永遠に実行され続けます。)
尾のPIDをどうにか知っていれば、後でそれを殺すことができます。
明らかに、$! netcatのPIDを返します。
テールプロセスのPIDを取得するにはどうすればよいですか?
テールのPIDをファイル記述子3に書き込み、そこからキャプチャします。
( tail -f $1 & echo $! >&3 ) 3>pid | nc -l -p 9977
kill $(<pid)
別のオプション:サブシェルへのリダイレクトを使用します。これにより、バックグラウンドプロセスが開始される順序が変更されるため、$! tail
プロセスのPIDを提供します。
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
ユーザーが同じマシンで2つの「インスタンス」に対してスクリプトを実行できる場合、このスレッドで言及されているトリックは機能しません。
jobs -x echo %1
が機能しませんでした(manページに-x
flag)を試してみましたが、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
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
を使用してテールプロセスを見つけることができました。 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
tail
コマンドのpidは、Bash I/Oリダイレクトのみを使用して変数に保存できます( パイプラインでプロセスの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
やってみました:
nc -l -p 9977 -c "tail -f $1"
(未テスト)
または、nc
に-e
がない場合は、-c
とスクリプトファイルを使用します。 GAPING_SECURITY_HOLE
オプションでコンパイルされたnc
が必要になる場合があります。はい、そのオプション名から適切な警告を推測する必要があります。
1つの方法は、スクリプトppidでps -efとgrepをtailするだけです
理想的な答えではありませんが、私が取り組んでいたロガーデーモンの回避策を見つけました:
#!/bin/sh
tail -f /etc/service/rt4/log/main/current --pid=$$ | grep error
$ infoテールから:
--pid=PID
with -f, terminate after process ID, PID dies
coproc
コマンドを2回使用できます。
与えられた例は次のように翻訳されます:
coproc TAIL { tail -f $1; }; exec {TAIL[1]}<&-
coproc NC { nc -v -l -p 9977; } <&"${TAIL[0]}" >&1
wait $NC_PID; echo "nc exit code: $!"
kill $TAIL_PID; echo "done"
(トラブルシューティングのために-v
といくつかのecho
をそこに投げました。)
coproc
を使用することは、他のさまざまなスクリプト言語でPopen()を使用することによく似ています。
Tailの--pidオプションは、ここでのあなたの親友です。バックグラウンドで実行されているパイプラインを完全に制御できます。ファイルが別のプロセスによってアクティブにローテーションされ、非アクティブなiノードがテーリングされたままになった場合の復元力を高めるために、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