Чому $$ повертає той самий ідентифікатор, що і батьківський процес?


160

У мене проблеми з Башем, і я не знаю, чому.
Під оболонкою я ввожу:

echo $$    ## print 2433
(echo $$)  ## also print 2433
(./getpid) ## print 2602

"getpid" - програма C для отримання поточного pid, наприклад:

   int main() {
    printf("%d", (int)getpid());
    return 0;
   }

Що мене бентежить, це те, що:

  1. Я думаю, що "(команда)" - це підпроцес (я прав?), І я думаю, що його pid повинен відрізнятися від його батьківського pid, але вони однакові, чому ...
  2. коли я використовую свою програму, щоб показати pid між круглими дужками, pid, який вона показує, відрізняється, чи правильно?
  3. "$$" щось на зразок макросу?

Можеш допомогти мені?


8
Зауважте, що getpidвін відображав би інший ідентифікатор процесу, навіть якщо він не запускався в підпакеті.
чепнер

1
@Marian echo $$ $BASHPID ; ( echo $$ $BASHPID )демонструє, що це робить. Круглі дужки створюють нижню частину корпусу. Висловлювання можуть змінювати змінні значення, і батьківська оболонка не повинна бачити цих змін. Це реалізується як fork()операція.
Бен

Відповіді:


223

$$визначено, щоб повернути ідентифікатор процесу батьківського підзагорта; зі сторінки чоловіка в розділі "Спеціальні параметри":

$ Розширюється на ідентифікатор процесу оболонки. У підпакеті () він розширюється на ідентифікатор процесу поточної оболонки, а не на нижню.

У bash4 можна отримати ідентифікатор процесу дитини BASHPID.

~ $ echo $$
17601
~ $ ( echo $$; echo $BASHPID )
17601
17634

16
"батьків" трохи вводить в оману (принаймні, це було для мене), це насправді оболонка "верхнього рівня". Наприклад: echo $$; (echo $$; (echo $$))три рази повторює той самий під
Мартін Буладур

1
Правильно; Я мав би сказати, що значення успадковується від батьківської оболонки (яка успадкувала його значення від свого батьківського і т.д.). Оболонка верхнього рівня встановлює її спочатку, а не успадковує її від батьківського процесу (не оболонки).
чепнер

$ Expands to the process ID of the shellце тхо? echo $просто перегукується з буквальним $.
Олександр Міллз

@AlexanderMills Ну, так; $одне не є розширенням параметра. Сторінка man посилається на назву спеціального параметра, який є $; це не стверджує, що $одне лише розширюється.
чепнер

Гаразд, я, чесно кажучи, не маю поняття, що це означає, але echo $BASHPIDпрацює у програмах 4 та 5 (але не версії 3.2.57 на MacOS)
Олександр Міллз

81

Ви можете скористатися одним із наступних.

  • $! - PID останнього фонового процесу.
  • kill -0 $PID перевіряє, чи все ще працює.
  • $$ PID поточної оболонки.

2
Чи не повинна бути друга куля, kill -0 $!якщо ми говоримо про фонові процеси? PIDза замовчуванням не встановлено нічого.
Ісаак Фріман

26
  1. В дужках викликують передплату в Bash . Оскільки це лише нижня оболонка, вона може мати той самий PID - залежить від впровадження.
  2. Програма C, яку ви викликаєте, - це окремий процес, у якого є свій унікальний PID - неважливо, знаходиться він у нижній частині або ні.
  3. $$є псевдонімом Bash до поточного PID сценарію . Дивіться відмінності між $$і $BASHPIDтут , і праворуч вище додаткової змінної, $BASH_SUBSHELLяка містить рівень вкладення.

4

Спробуйте, getppid()якщо ви хочете, щоб ваша програма C надрукувала PID вашої оболонки.


2

Якщо ви запитували, як отримати PID відомої команди, він би нагадував щось подібне:

Якщо ви видали команду нижче, # команда була ***

dd, якщо = / dev / diskx of = / dev / disky


Тоді ви будете використовувати:

PIDs=$(ps | grep dd | grep if | cut -b 1-5)

Що тут відбувається - це передавання в поле всіх необхідних унікальних символів, і це поле може бути повторене за допомогою

echo $ PID


2

це єдиний універсальний спосіб отримати правильний pid

pid=$(cut -d' ' -f4 < /proc/self/stat)

той же приємно працював для підп

SUB(){
    pid=$(cut -d' ' -f4 < /proc/self/stat)
    echo "$$ != $pid"
}

echo "pid = $$"

(SUB)

перевірити вихід

pid = 8099
8099 != 8100

Хороша ідея, але хіба це не допоможе вам розіграти вилку, яку оболонка запустила, щоб захопити вихід вирізу? Якщо я запускаю його двічі, один раз з echo $ (...) і один раз без, то я отримую різні відповіді.
Мартін
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.