GNU/Linux >> Linux の 問題 >  >> Linux

シェルスクリプトでフォークされた子プロセスから PID を取得する方法

バックグラウンドの子プロセスの PID は $! に格納されます 、現在のプロセスは $$ です :

fpfunction &
child_pid=$!     # in parent process, child's pid is $!
parent_pid=$$    # in parent process, parent's pid is $$

バックグラウンド関数の場合、子プロセスの PID は $BASHPID です $$ ではなく 、これが親の PID になります:

fpfunction() {
    local child_pid=$BASHPID   # in child process, child's pid is $BASHPID
    local parent_pid=$$        # in child process, parent's pid is $$
    ...
}

また、ループ ステートメントを単一の C ライクな for ループに結合することもできます。

for ((n = 1; n < 20; ++n)); do
    echo "Hello World-- $n times"
    sleep 2
    echo "Hello World2-- $n times"
done

Bash マニュアルから:

<ブロック引用>

!

最後に実行されたバックグラウンド (非同期) コマンドのプロセス ID に展開されます。

つまり、$! を使用します .


スクリプト、子および親の PID は、親スクリプトを開始する方法に関係なく、常に親スクリプトで正しく決定できます。

child () { :; }

child &
( child ) &
sh -c "child () { :; }; child" &

script_pid="${$}"    # PID of the running shell script
child_pid="${!}"     # last started child process
parent_pid="${PPID}" # PID of parent process

子プロセスで情報にアクセスできるかどうかは、子プロセスがどのように開始されたかによって異なります。

関数を使用:

 child ()
 {
     sleep "$( expr "${2-1}" '*' 5 )"
     script_pid="${3-}"
     child_pid="${$}"
     parent_pid="${PPID}"
     message="CHILD ${1-}"
     test x"${script_pid}" != x"${child_pid}" || message="${message}"' UNFORTUNATELY WRONG!'
     report
     sleep 20
 }

および非同期呼び出し:

child FUNC "${indx}" "${$}" &

( child SUB "${indx}" "${$}" ) &

sh -c "${FUNCTIONS}
child SH "${indx}" \"${$}\"" &

出力は、明示的な sh -c で呼び出された関数のみを示しています 正しい PID/PPID 情報にアクセスできる:

# --------------------------------------------------
#   :PRC:   CHILD FUNC UNFORTUNATELY WRONG!
#   :DBG:   script_pid     : [20634]
#   :DBG:   child_pid      : [20634]
#   :DBG:   parent_pid     : [10857]
F   UID   PID  PPID PRI  NI    VSZ   RSS WCHAN  STAT TTY        TIME COMMAND
0  1114 10857 10853  20   0 2756840 1942820 poll_s Ssl ?       95:15 emacs
0  1114 20634 10857  20   0   4636  1732 wait   Ss+  pts/22     0:00 sh /tmp/check_child_and_parent_pids.sh

# --------------------------------------------------
#   :PRC:   CHILD SUB UNFORTUNATELY WRONG!
#   :DBG:   script_pid     : [20634]
#   :DBG:   child_pid      : [20634]
#   :DBG:   parent_pid     : [10857]
F   UID   PID  PPID PRI  NI    VSZ   RSS WCHAN  STAT TTY        TIME COMMAND
0  1114 10857 10853  20   0 2756840 1942820 poll_s Ssl ?       95:15 emacs
0  1114 20634 10857  20   0   4636  1732 wait   Ss+  pts/22     0:00 sh /tmp/check_child_and_parent_pids.sh

# --------------------------------------------------
#   :PRC:   CHILD SH
#   :DBG:   script_pid     : [20634]
#   :DBG:   child_pid      : [20658]
#   :DBG:   parent_pid     : [20634]
F   UID   PID  PPID PRI  NI    VSZ   RSS WCHAN  STAT TTY        TIME COMMAND
0  1114 20634 10857  20   0   4636  1732 wait   Ss+  pts/22     0:00 sh /tmp/check_child_and_parent_pids.sh
0  1114 20658 20634  20   0   4636  1720 wait   S+   pts/22     0:00 sh -c show_processes () {     test -z

完全なテスト スクリプトは次のとおりです。

FUNCTIONS="$(
cat <<'EOF'
show_processes ()
{
    test -z "${1-}" || printf "%s\n" "${1}"

    _sep=
    pids_rx=
    for _pid in "${script_pid}" "${child_pid}" "${parent_pid}"
    do
    test -n "${_pid}" || continue
    pids_rx="${pids_rx}${_sep}${_pid}"
    _sep='\|'
    done

    ps axl | head -1
    ps axl | grep '^[^ ]*  *[^ ]*  *\('"${pids_rx}"'\)' | cut -c -107 | sort -k 3
}

report ()
{
    printf "%s\n" ""
    printf >&2 "# --------------------------------------------------\n"
    printf >&2 "#   "":PRC:   %s\n" "${message}"
    test -z "${script_pid}" || \
    printf >&2 "#   "":DBG:   %-${dbg_fwid-15}s: [%s]\n" "script_pid" "${script_pid}"
    test -z "${child_pid}" || \
    printf >&2 "#   "":DBG:   %-${dbg_fwid-15}s: [%s]\n" "child_pid" "${child_pid}"
    test -z "${parent_pid}" || \
    printf >&2 "#   "":DBG:   %-${dbg_fwid-15}s: [%s]\n" "parent_pid" "${parent_pid}"
    show_processes
}

child ()
{
    sleep "$( expr "${2-1}" '*' 5 )"
    script_pid="${3-}"
    child_pid="${$}"
    parent_pid="${PPID}"
    message="CHILD ${1-}"
    test x"${script_pid}" != x"${child_pid}" || message="${message}"' UNFORTUNATELY WRONG!'
    report
    sleep 20
}
EOF
)"

eval "${FUNCTIONS}"

shell_report ()
{
    script_pid="${$}"
    child_pid="${!}"
    parent_pid="${PPID}"
    sleep 1
    message="SHELL ${indx}"
    report
    indx="$( expr "${indx}" + 1 )"
}

indx=1

child FUNC "${indx}" "${$}" &
shell_report

( child SUB "${indx}" "${$}" ) &
shell_report

sh -c "${FUNCTIONS}
child SH "${indx}" \"${$}\"" &
shell_report

sleep "$( expr "${indx}" '*' 5 )"
The complete output is:

# --------------------------------------------------
#   :PRC:   SHELL 1
#   :DBG:   script_pid     : [20634]
#   :DBG:   child_pid      : [20636]
#   :DBG:   parent_pid     : [10857]
F   UID   PID  PPID PRI  NI    VSZ   RSS WCHAN  STAT TTY        TIME COMMAND
0  1114 10857 10853  20   0 2756840 1942820 poll_s Ssl ?       95:15 emacs
0  1114 20634 10857  20   0   4636  1728 wait   Ss+  pts/22     0:00 sh /tmp/check_child_and_parent_pids.sh
1  1114 20636 20634  20   0   4636   104 wait   S+   pts/22     0:00 sh /tmp/check_child_and_parent_pids.sh

# --------------------------------------------------
#   :PRC:   SHELL 2
#   :DBG:   script_pid     : [20634]
#   :DBG:   child_pid      : [20647]
#   :DBG:   parent_pid     : [10857]
F   UID   PID  PPID PRI  NI    VSZ   RSS WCHAN  STAT TTY        TIME COMMAND
0  1114 10857 10853  20   0 2756840 1942820 -   Rsl  ?         95:15 emacs
0  1114 20634 10857  20   0   4636  1732 wait   Ss+  pts/22     0:00 sh /tmp/check_child_and_parent_pids.sh
1  1114 20647 20634  20   0   4636   108 wait   S+   pts/22     0:00 sh /tmp/check_child_and_parent_pids.sh

# --------------------------------------------------
#   :PRC:   SHELL 3
#   :DBG:   script_pid     : [20634]
#   :DBG:   child_pid      : [20658]
#   :DBG:   parent_pid     : [10857]
F   UID   PID  PPID PRI  NI    VSZ   RSS WCHAN  STAT TTY        TIME COMMAND
0  1114 10857 10853  20   0 2756840 1942820 poll_s Ssl ?       95:15 emacs
0  1114 20634 10857  20   0   4636  1732 wait   Ss+  pts/22     0:00 sh /tmp/check_child_and_parent_pids.sh
0  1114 20658 20634  20   0   4636   928 wait   S+   pts/22     0:00 sh -c show_processes () {     test -z

# --------------------------------------------------
#   :PRC:   CHILD FUNC UNFORTUNATELY WRONG!
#   :DBG:   script_pid     : [20634]
#   :DBG:   child_pid      : [20634]
#   :DBG:   parent_pid     : [10857]
F   UID   PID  PPID PRI  NI    VSZ   RSS WCHAN  STAT TTY        TIME COMMAND
0  1114 10857 10853  20   0 2756840 1942820 poll_s Ssl ?       95:15 emacs
0  1114 20634 10857  20   0   4636  1732 wait   Ss+  pts/22     0:00 sh /tmp/check_child_and_parent_pids.sh

# --------------------------------------------------
#   :PRC:   CHILD SUB UNFORTUNATELY WRONG!
#   :DBG:   script_pid     : [20634]
#   :DBG:   child_pid      : [20634]
#   :DBG:   parent_pid     : [10857]
F   UID   PID  PPID PRI  NI    VSZ   RSS WCHAN  STAT TTY        TIME COMMAND
0  1114 10857 10853  20   0 2756840 1942820 poll_s Ssl ?       95:15 emacs
0  1114 20634 10857  20   0   4636  1732 wait   Ss+  pts/22     0:00 sh /tmp/check_child_and_parent_pids.sh

# --------------------------------------------------
#   :PRC:   CHILD SH
#   :DBG:   script_pid     : [20634]
#   :DBG:   child_pid      : [20658]
#   :DBG:   parent_pid     : [20634]
F   UID   PID  PPID PRI  NI    VSZ   RSS WCHAN  STAT TTY        TIME COMMAND
0  1114 20634 10857  20   0   4636  1732 wait   Ss+  pts/22     0:00 sh /tmp/check_child_and_parent_pids.sh
0  1114 20658 20634  20   0   4636  1720 wait   S+   pts/22     0:00 sh -c show_processes () {     test -z

Linux
  1. CからLinuxでPIDによってプロセスのCPU使用率を計算する方法は?

  2. バックグラウンドプロセスのプロセスIDを取得するには?

  3. シェル スクリプトでプロセスの PID を取得する

  1. 親プロセスから子プロセスを取得する方法

  2. pidを使用してPythonからプロセスを終了するには?

  3. プロセス名でPIDを取得するには?

  1. コマンドラインからGNU/Linuxで特定のプロセスの親PIDを取得するには?

  2. プロセスの pid を取得し、シェル スクリプトで kill -9 を呼び出す方法は?

  3. 開始したばかりのプロセスのpidを取得する方法