Часто возникает путаница между процессом разветвления и выполнением.
Когда вы делаете по приглашению 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 другого процесса , который был назначен в качестве subreaper вместо 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будет содержаться pid родительского процесса, который выполнил оболочку во время инициализации этой оболочки. После этого, как видно выше, родительский процесс может измениться, если процесс id $PPIDумирает.
zshв zsh/systemмодуле, может запросить текущий родительский pid текущей (под) оболочки с помощью $sysparams[ppid]. В оболочках POSIX вы можете получить текущий ppid процесса, который выполнил интерпретатор (при условии, что он все еще выполняется) ps -o ppid= -p "$$". С помощью bashвы можете получить ppid текущей (под) оболочки с помощью ps -o ppid= -p "$BASHPID".