How to get the PID of a process that is piped to another process in Bash?

前端 未结 14 1163
无人共我
无人共我 2020-12-01 01:35

I am trying to implement a simple log server in Bash. It should take a file as a parameter and serve it on a port with netcat.

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


        
相关标签:
14条回答
  • 2020-12-01 02:25

    bobbogo answer works but requires a intermediary pid file.

    You can leverage the process substitution feature >() which works like| but without waiting for tail to finish

    tail -f $1 > >(nc -l -p 9977) & pid=!
    
    0 讨论(0)
  • 2020-12-01 02:26

    This works for me (SLES Linux):

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

    The ps|grep|kill trick mentioned in this thread would not work if a user can run the script for two "instances" on the same machine.

    jobs -x echo %1 did not work for me (man page not having the -x flag) but gave me the idea to try jobs -p.

    0 讨论(0)
  • 2020-12-01 02:26

    Maybe you could use a fifo, so that you can capture the pid of the first process, e.g.:

    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
    
    0 讨论(0)
  • 2020-12-01 02:31

    Finally, I have managed to find the tail process using ps. Thanks to the idea from ennuikiller.

    I have used the ps to grep tail from the args and kill it. It is kind of a hack but it worked. :)

    If you can find a better way please share.

    Here is the complete script:
    (Latest version can be found here: 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
    
    0 讨论(0)
  • 2020-12-01 02:35

    Not an ideal answer, but I found a workaround for a logger daemon I worked on:

    #!/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
    
    0 讨论(0)
  • 2020-12-01 02:37

    how about this:

    jobs -x echo %1
    

    %1 is for first job in chain, %2 for second, etc. jobs -x replaces job specifier with PID.

    0 讨论(0)
提交回复
热议问题