Получить pid текущей подоболочки
Я пытаюсь получить pid текущей исполняемой подсели, но $$
возвращает родительский pid:
#!/usr/bin/sh
x() {
echo "I am a subshell x echo 1 and my pid is $$"
}
y() {
echo "I am a subshell y echo 1 and my pid is $$"
}
echo "I am the parent shell and my pid is $$"
x &
echo "Just launched x and the pid is $! "
y &
echo "Just launched y and the pid is $! "
wait
Выход
I am the parent shell and my pid is 3107
Just launched x and the pid is 3108
I am a subshell x echo 1 and my pid is 3107
Just launched y and the pid is 3109
I am a subshell y echo 1 and my pid is 3107
Как вы можете видеть выше, когда я запускаю $$
из функции, которую я создал, она не отображает PID, как при я $!
из родительской оболочки.
Ответы
Ответ 1
Современный bash
Если вы используете bash v4 или выше, PID подоболочки доступен в $BASHPID
. Например:
$ echo $$ $BASHPID ; ( echo $$ $BASHPID )
32326 32326
32326 1519
В основной оболочке $BASHPID
совпадает с $$
. В подоболочке он обновляется до PID подповерхности.
Старый bash (версия 3.x или ранее)
Перед версией 4 вам понадобится обходной путь:
$ echo $$; ( : ; bash -c 'echo $PPID' )
11364
30279
(Совет шляпы: kubanczyk)
Почему двоеточие?
Обратите внимание, что без двоеточия рабочий процесс работает не:
$ echo $$; ( bash -c 'echo $PPID' )
11364
11364
Похоже, что в приведенном выше примере подоболочка никогда не создается, и, следовательно, второй оператор возвращает PID основной оболочки. В отличие от этого, если мы помещаем два выражения внутри парнеров, создается подоболочка, и выход будет таким, какой мы ожидаем. Это верно, даже если другое выражение представляет собой просто двоеточие, :
. В оболочке :
не работает: ничего не делает. Однако в нашем случае мы вынуждаем создание подоболочки, которой достаточно, чтобы выполнить то, что мы хотим.
тир
В debian-подобных системах dash
является оболочкой по умолчанию (/bin/sh
). Подход PPID
работает для dash
, но с еще одним завихрением:
$ echo $$; ( dash -c 'echo $PPID' )
5791
5791
$ echo $$; ( : ; dash -c 'echo $PPID' )
5791
5791
$ echo $$; ( dash -c 'echo $PPID'; : )
5791
20961
С dash
, поместив команду :
до того, как команда не будет достаточной, но поместив ее после нее.
POSIX
PPID
включен в спецификацию POSIX.
Портативность
mklement0 сообщает, что следующее работает как с bash
, dash
, и zsh
, но не ksh
:
echo $$; (sh -c 'echo $PPID' && :)
Ответ 2
Выход правильный.
Здесь из справочной страницы bash.
Специальные параметры
В оболочке рассматриваются несколько параметров. К этим параметрам можно отнести только ссылки; присвоение им не разрешено.
*
Расширяется до позиционных параметров, начиная с одного. Когда расширение происходит в двойных кавычках, оно расширяется до одного слова со значением каждого параметр, разделенный первым символом специальной переменной IFS. То есть "$*"
эквивалентно "$1c$2c..."
, где c - первый символ значение переменной IFS. Если IFS не задано, параметры разделяются пробелами. Если IFS равно null, параметры объединяются без промежуточных разделителей.
@
Расширяется до позиционных параметров, начиная с одного. Когда расширение происходит в двойных кавычках, каждый параметр расширяется до отдельного слова. Что is, "[email protected]"
эквивалентно "$1" "$2" ...
Если двойное кавычное разложение происходит внутри слова, разложение первого параметра соединяется с начальной частью исходного слова, а разложение последнего параметра соединяется с последняя часть исходного слова. Когда нет позиционного параметры, "[email protected]"
и [email protected]
расширяются до нуля (т.е. удаляются).
#
Расширяется до числа позиционных параметров в десятичном формате.
?
Расширяется до статуса выхода последнего выполненного переднего плана.
-
Расширяется до текущих флажков опций, как указано при вызове, с помощью встроенной команды set или тех, которые установлены самой оболочкой (например, опция -i
).
$
Расширяется до идентификатора процесса оболочки. В подтесте ()
она расширяется до идентификатора процесса текущей оболочки, а не подоболочки.
!
Расширяется до идентификатора процесса последней выполненной фоновой (асинхронной) команды.
Чтобы получить PID внутри подоболочки, вы можете использовать BASHPID. Это переменная bash только env.
Ваш новый script будет выглядеть следующим образом.
#!/bin/bash
x() {
echo "I am a subshell x echo 1 and my pid is $BASHPID"
}
y() {
eval echo "I am a subshell y echo 1 and my pid is $BASHPID"
}
echo "I am the parent shell and my pid is $$"
x &
echo "Just launched x and the pid is $! "
y &
echo "Just launched y and the pid is $! "
wait
Ответ 3
@John1024 ответ отличный, но там есть небольшая проблема.
когда команда запускается как (...), команда запускается в новом подпроцессе, поэтому
( : ; bash -c 'echo $PPID' )
вернет process_id из (...) , не идентификатор процесса функции, который вызывает (...)
если вам нужна функция process_id, вы можете просто запустить:
$SHELL -c 'echo $PPID'
и process_id будет передан в stderr
если вы хотите получить функцию process_id из переменной, вы можете запустить:
$SHELL -c 'echo $PPID' | read -s func_pid
тогда вы можете получить pid из переменной $ {func_pid}
примечание: не запускайте эту команду в (...), иначе она вернет process_id of (...)
Ответ 4
Окружающая среда:
SUSE Linux Enterprise Server 10 SP2 (i586)
GNU bash, версия 3.1.17 (1) -release (i586-suse-linux)
Copyright (C) 2005 Free Software Foundation, Inc.
#!/usr/bin/sh
x() {
mypid=$(awk 'BEGIN {print PROCINFO["ppid"] ; exit}')
echo "I am a subshell x echo 1 and my pid is $mypid"
}
y() {
mypid=$(awk 'BEGIN {print PROCINFO["ppid"] ; exit}')
echo "I am a subshell y echo 1 and my pid is $mypid"
}
echo "I am the parent shell and my pid is $$"
x &
echo "Just launched x and the pid is $! "
y &
echo "Just launched y and the pid is $! "
wait
Результат:
I am the parent shell and my pid is 27645
Just launched x and the pid is 27646
Just launched y and the pid is 27647
I am a subshell y echo 1 and my pid is 27647
I am a subshell x echo 1 and my pid is 27646
Ответ 5
Если вы используете Linux-kernel, вы можете использовать функцию Linux-kernel /proc/self
для этого:
В простейшем виде: cd -P/proc/self && basename "${PWD}"
Чтобы сохранить переменные PWD
и OLDPWD
: PWD_BACKUP="${PWD}";OLDPWD_BACKUP="${OLDPWD}";cd -P/proc/self && basename "${PWD}";cd "${PWD_BACKUP}";OLDPWD="${OLDPWD_BACKUP}"
Например:
$ cd -P /proc/self && basename "${PWD}"
26758
$ (cd -P /proc/self && basename "${PWD}")
26959
$ (cd -P /proc/self && basename "${PWD}")
26961
$
Ответ 6
Лучше использовать $(exec sh -c 'echo $PPID')
а не уловки, показанные в ответе John1024 (эти уловки не работают в современных оболочках в настоящее время, когда я пишу свой ответ).
Посмотрите этот вопрос: https://unix.stackexchange.com/info/484442/how-can-i-get-the-pid-of-a-subshell