Wie die PID eines Prozesses erhalten, die zu einem anderen Prozess in Bash geleitet wird?

StackOverflow https://stackoverflow.com/questions/1652680

  •  22-07-2019
  •  | 
  •  

Frage

Ich versuche, einen einfachen Log-Server in Bash zu implementieren. Es sollte eine Datei als Parameter nehmen und es auf einem Port mit netcat dienen.

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

Aber das Problem ist, dass, wenn der netcat endet, Schweif hinter laufen gelassen wird. (Zur Verdeutlichung:. Wenn ich es nicht den Schwanz Prozess Gabel wird auch weiterhin immer noch die netcat beendet laufen)

Wenn ich irgendwie die PID des Schwanzes weiß dann könnte ich es danach töten.
Offensichtlich mit $! wird die PID netcat zurück.

Wie kann ich die PID des Schwanzes Prozess bekommen?

War es hilfreich?

Lösung

Schreiben Schwanz PID Dateideskriptor 3 und erfassen sie dann von dort aus.

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

Andere Tipps

Eine weitere Option: Verwenden Sie eine Umleitung Subshell. Dadurch ändert sich die Reihenfolge, in der Hintergrund-Prozesse gestartet werden, so $! PID des tail Prozess gibt.

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

Wie wäre es dieses:

jobs -x echo %1

%1 für den ersten Job in der Kette ist, %2 für die zweite usw. jobs -x ersetzt Job Spezifizierer mit PID.

Dies funktioniert für mich (SLES Linux):

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

Der ps|grep|kill Trick in diesem Thread erwähnt würde nicht funktionieren, wenn ein Benutzer das Skript für zwei „Instanzen“ auf der gleichen Maschine laufen kann.

jobs -x echo %1 nicht für mich arbeiten (man-Seite nicht die -x Flagge mit), aber gab mir die Idee jobs -p zu versuchen.

Vielleicht könnten Sie ein Fifo verwenden, so dass Sie die pid des ersten Prozesses erfassen , zum Beispiel:

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

Schließlich habe ich es geschafft, die Schwanz-Prozess zu finden ps verwenden. Dank der Idee von ennuikiller.

Ich habe die ps grep Schwanz von dem args verwendet und es zu töten. Es ist eine Art ein Hack, aber es funktionierte. :)

Wenn Sie einen besseren Weg finden, bitte teilen.

Dies ist die komplette Skript:
(Neueste Version finden Sie hier: 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 automatisch tail -f auf exit beendet (auf 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

Eine Möglichkeit wäre, einfach tun, um einen ps -ef und grep für Schwanz mit Ihrem Skript ppid

Haben Sie versucht:

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

(ungetestet)

oder -e mit einem Script wenn Ihr nc nicht über -c. Sie können einen nc haben, die mit der GAPING_SECURITY_HOLE Option kompiliert wurde. Ja, Sie sollten entsprechende Einsprüche von dieser Option Namen entnehmen.

Sie können speichern Sie die pid des tail Befehls in einer Variablen mit Schlag-I / O-Umleitungen nur (siehe Wie die PID eines Prozesses in einer Pipeline zu bekommen).

# 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

Keine ideale Antwort, aber ich fand für einen Logger-Daemon eine Abhilfe, die ich arbeitete an:

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

von $ info Schwanz:

--pid=PID
          with -f, terminate after process ID, PID dies

Die --pid Option Schwanz ist dein bester Freund hier. Es wird Ihnen die Kontrolle über die Pipeline im Hintergrund laufen insgesamt ermöglichen. lesen Sie die tail-Befehlsoptionen für mehr Elastizität, falls Ihre Datei aktiv von einem anderen Prozess gedreht wird, die Sie verlassen könnte eine inaktive inode Tailing. Das folgende Beispiel, wenn auch nicht verwendet, die Daten zu verarbeiten zeigen die „auferlegt“ Beschränkung des Schwanz und die Fähigkeit, ihm zu sagen, zu jeder Zeit zu beenden. Dieser wird zur Messung des Betriebsdruckes auf httpd verwendet.

  # 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

Sie könnten den coproc Befehl zweimal verwendet werden.

Das gegebene Beispiel übersetzt:

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"

(I ein -v und ein paar echo da drin für die Fehlerbehebung geworfen haben.)

coproc Mit fühlt sich viel wie mit Popen () in verschiedenen anderen Skriptsprachen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top