GNU/Linux >> Tutoriels Linux >  >> Linux

Comment obtenir le PID d'un processus enfant forké dans un script shell

Le PID d'un processus enfant en arrière-plan est stocké dans $! , et le processus actuel est $$ :

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

Lorsqu'il est dans la fonction en arrière-plan, le PID des processus enfants est $BASHPID plutôt que $$ , qui est maintenant le PID du parent :

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

De plus, pour ce que ça vaut, vous pouvez combiner les instructions en boucle dans une seule boucle for de type C :

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

Dans le manuel de Bash :

!

Développe l'ID de processus de la commande d'arrière-plan (asynchrone) la plus récemment exécutée.

c'est-à-dire, utilisez $! .


Les PID du script, de l'enfant et du parent peuvent toujours être déterminés correctement dans le script parent indépendamment de la méthode utilisée pour le démarrer :

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

L'accessibilité des informations dans le processus enfant dépend de la façon dont le processus enfant a été démarré.

Avec la fonction :

 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
 }

et les appels asynchrones :

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

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

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

la sortie montre que seule la fonction invoquée avec un sh -c explicite a accès aux informations PID/PPID correctes :

# --------------------------------------------------
#   :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

Le script de test complet est :

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. Comment calculer l'utilisation CPU d'un processus par PID sous Linux à partir de C ?

  2. Comment obtenir l'ID de processus du processus d'arrière-plan ?

  3. Comment obtenir l'ID de processus pour tuer un processus nohup ?

  4. Comment obtenir le PID par nom de processus ?

  5. Comment obtenir le PID parent d'un processus donné sous GNU/Linux à partir de la ligne de commande ?

Comment obtenir l'adresse IP externe dans un script shell ?

Comment exécuter des scripts Python à partir du shell

Comment trouver le nom du processus à partir de son PID

Comment exécuter une commande dans un script shell ?

Comment obtenir le code de sortie du processus généré dans le script shell attendu ?

Comment obtenir le pid du processus qui vient de démarrer