Часто виникає плутанина між форксуванням процесу та виконанням.
Коли ви робите підказки bash
оболонки.
$ sh -c 'exec env ps'
Процес P1 видачі цього $
підказка в даний час працює bash
кодом. Цей bash
код розщеплює новий процес P2, який виконує, /bin/sh
який потім виконує /usr/bin/env
, який потім виконує /bin/ps
.
Таким чином , P2 , в свою чергу виконується код bash
, sh
, env
і ps
.
ps
(або будь-яка інша команда, як скрипт, яку ми б замість цього використали тут) не може знати, що вона виконується env
командою.
Все, що він може зробити, - це з’ясувати, що таке його ідентифікатор батьківського процесу, який у цьому випадку буде P1 або 1
якщо P1 загинув в інтервалі, або в Linux інший процес, який був призначений як підреактор замість 1
.
Потім він може запитувати систему для того, яку команду цей процес виконує в даний момент (як, наприклад, readlink /proc/<pid>/exe
в Linux) або які аргументи, де передано останню команду, яку вона виконувала (наприклад, з ps -o args= -p <pid>
).
Якщо ви хочете, щоб ваш скрипт знав, на що він викликав, надійним способом було б дозволити заявнику сказати це. Це можна зробити, наприклад, за допомогою змінної середовища. Наприклад, script1
можна записати так:
#! /bin/sh -
INVOKER=$0 script2 &
І script2
:
#! /bin/sh -
printf '%s\n' "I was invoked by $INVOKER"
# and in this case, we'll probably find the parent process is 1
# (if not now, at least one second later) as script1 exited just after
# invoking script2:
ps -fp "$$"
sleep 1
ps -fp "$$"
exit
$INVOKER
( як правило ) міститиме шлях до script1
. У деяких випадках це може бути відносний шлях, і шлях буде відносно поточного робочого каталогу на початок часу script1
. Тож якщо script1
змінити поточний робочий каталог перед викликом script2
, script2
отримає неправильну інформацію щодо того, що його викликало. Тому може бути бажано переконатися, що він $INVOKER
містить абсолютний шлях (бажано збереження базового імені), наприклад, написавши script1
:
#! /bin/sh -
mypath=$(
mydir=$(dirname -- "$0") &&
cd -P -- "$mydir" &&
pwd -P) && mypath=$mypath/$(basename -- "$0") || mypath=$0
... some code possibly changing the current working directory
INVOKER=$mypath script2
В оболонках POSIX $PPID
міститиметься під батьківського процесу, який виконував оболонку під час ініціалізації цієї оболонки. Після цього, як видно вище, батьківський процес може змінитися, якщо процес ідентифікації $PPID
загине.
zsh
в zsh/system
модулі, може запитувати поточний батьківський під поточної (під-) оболонки за допомогою $sysparams[ppid]
. В оболонках POSIX ви можете отримати поточний ppid процесу, який виконував інтерпретатор (якщо припустити, що він все ще працює) ps -o ppid= -p "$$"
. З bash
, ви можете отримати ppid поточної (під-) оболонки за допомогою ps -o ppid= -p "$BASHPID"
.