バックグラウンドパイプラインコマンドシーケンスからすべてのコマンドのPIDを取得します。

バックグラウンドパイプラインコマンドシーケンスからすべてのコマンドのPIDを取得します。

にある場合は、bash次を実行します。

cmd1 | cmd2 | ... | cmdi | ... | cmdn &

明確ではないかもしれませんcmd{1..n}。 PIDをどのように取得しますかcmdi?または、どのようにcmdiプロセスにシグナルを送信できますか? (例:送信SIGUSR1?) pkill/ pgrepetcは、同じパイプラインの一部を含む他のインスタンスが実行されている可能性があるため、pidof良い答えではないようです。のPIDを教えcmdiてください。jobs -pcmd1

iでは何でも構いません{1..n}

答え1

質問の元のバージョンでは、最後のコマンドのPIDのみが必要なときに特別な変数が$!完璧です。

foo | bar | baz &
baz_pid=$!

他のプロセスのPIDに簡単にアクセスできる同様の方法はありません。

$pipestatus(zsh)と(bash)を追加するのに長い時間がかかり、最終的にパイプラインのすべての終了$PIPESTATUS状態に加えて、$?元のBourneシェル以降にあった最後の終了状態にアクセスできるようになりました。おそらく同様のことが最終的に起こります$!

答え2

私の考えでは、あなたが提案したように何かをすることができると思います。ここ

(ls -l | echo "Hello" | df -h & echo $! >&3 ) 3>pid

上記の例では、3番目のパイプラインプロセスのpidを検索してpidファイルに書き込みました。配管過程をすべて書くことができます。

答え3

移植性の低いLinux関連のソリューションは、プロセスを追跡するためにプロセスを接続するパイプを使用することです。jobs -pパイプラインから最初の()および最後の()コマンドのPIDを取得できます。$!PIDの1つを使用して、このスクリプトは操作を実行します。

#! /bin/bash

PROC=$1
echo $PROC

if [[ $(readlink /proc/$PROC/fd/1) =~ ^pipe: ]]
then
    # Assuming first process in chain...
    NEXT_FD=1
elif [[ $(readlink /proc/$PROC/fd/0) =~ ^pipe: ]]
then
    # Last process in chain...
    NEXT_FD=0
else
    # Doesn't look like a pipe.
    exit
fi

NEXT_PROC_PIPE=$(readlink /proc/$PROC/fd/$NEXT_FD)

while [[ $NEXT_PROC_PIPE =~ ^pipe: ]] 
do
    PROC=$(find /proc/*/fd -type l -printf "%p/%l\n" 2>/dev/null | awk -F'/' '($6 == "'"$NEXT_PROC_PIPE"'") && ($3 != "'$PROC'" ) {print $3}')
    NEXT_PROC_PIPE=$(readlink /proc/$PROC/fd/$NEXT_FD)
    echo $PROC
done

答え4

このコードでは、0から始まる配列を使用しています。ただ通過することに注意してくださいeval

#!/bin/bash

cmd=('sleep 10' 'sleep 2' 'sleep 5')
first=1
for c in "${cmd[@]}"; do
  ((first)) && { pipe=$c; first=0; } || pipe+='|'$c
done
shopt -u lastpipe
eval $pipe &

printf 'Pipe:\n%s\n\n' "$pipe"

shellpid=$BASHPID
parent=$(ps -o pid= --ppid $shellpid | head -n -1)
declare -a pids=()
mapfile -t pids < <(printf '%s\n' $(ps -o pid= --ppid $parent))
printf '%s\n' 'Listing the arrays:'
printf '%2s %6s %s\n' i PID command
for i in "${!cmd[@]}"; do
    printf '%2d %6d %s\n' "$i" "${pids[i]}" "${cmd[i]}"
done

printf '\n%s\n' 'ps listing:'
ps xao pid,ppid,command | head -n 1
ps xao pid,ppid,command | tail | head -n -3

関連情報