Чи підтримує bash розгалуження, подібне до fork C ()?


25

У мене є сценарій, який я хотів би розщедрити в один момент, щоб дві копії одного сценарію працювали.

Наприклад, я хотів би існувати наступний сценарій bash:

echo $$
do_fork()
echo $$

Якби цей сценарій bash справді існував, очікуваний результат буде:

<ProcessA PID>
<ProcessB PID>
<ProcessA PID>

або

<ProcessA PID>
<ProcessA PID>
<ProcessB PID>

Чи є щось, що я можу поставити замість "do_fork ()", щоб отримати такий вид виводу, або змусити скрипт bash зробити C-подібну виделку?

Відповіді:


23

Так. Розпилювання написано &:

echo child & echo parent

Що може вас бентежити, це те, що $$це не PID процесу оболонки, це PID початкового процесу оболонки. Сенс зробити це таким чином полягає в тому, що $$це унікальний ідентифікатор для конкретного екземпляра скрипта оболонки: він не змінюється під час виконання сценарію, і відрізняється від $$будь-якого іншого одночасно запущеного сценарію. Один із способів отримати власне PID процесу оболонки - це sh -c 'echo $PPID'.

Контрольний потік в оболонці не такий, як C. Якщо в C ви б написали

first(); fork(); second(); third();

то еквівалент оболонки є

after_fork () { second; third; }
first; after_fork & after_fork

Проста форма оболонки first; child & parentвідповідає звичайній ідіомі С

first(); if (fork()) parent(); else child();

&і $$існувати і вести себе таким чином у кожній оболонці в стилі Борна та в (t) csh. $PPIDне існувало в оригінальній оболонці Борна, але знаходиться в POSIX (так що це в золі, bash, ksh, zsh,…).


3
Але це в основному "fork + exec", а не лише fork.
mattdm

@mattdm: А? &є виделкою, жодного виконавця не бере участь. Fork + exec - це запуск зовнішньої команди.
Жил 'ТАК - перестань бути злим'

@mattdm: А, я думаю, я бачу, до чого потрапляє Кори. Немає exec, але обидві мови мають різний потік управління.
Жил 'ТАК - перестань бути злим'

1
@Gilles: Оператор керування bash &запускає підшару, в якій виконується дана команда. Fork + exec. Ви не можете просто поставити &без попередньої команди для виконання.
mattdm

5
Що ж, якби "Форкінг написано &" було справжнім твердженням, ви могли б поставити &на рядок самі по собі. Але ти не можеш. Це не означає "вила тут". Це означає "виконати попередню команду у фоновому режимі в нижній частині".
mattdm

10

Так, це називається допоміжною оболонкою . Код оболонки всередині дужок запускається як підшкірна оболонка (вилка). Однак перша оболонка зазвичай чекає, коли дитина заповниться. Ви можете зробити його асинхронним за допомогою &термінатора. Дивіться це в дії з чимось подібним:

#!/bin/bash

(sleep 2; echo "subsh 1")&
echo "topsh"

$ bash subsh.sh


5
В дужках створюється підзаголовок, але це fork + wait. &вила одна. Якщо ви хочете виконати більше одного конвеєра в дочірньому процесі, достатньо скористатися дужками (які виконують групування без створення дочірнього процесу):{ sleep 2; echo child; } &
Жил 'SO- перестань бути злим'

6

Існує не рідний баш (або, наскільки мені відомо, будь-який інший типовий * nix shell) спосіб цього зробити. Існує багато способів нерестувати роздвоєні процеси, які роблять щось інше асинхронно, але я не думаю, що є щось, що відповідає точній семантиці виклику системи fork ().

Типовим підходом було б, щоб ваш сценарій вищого рівня породив помічників, які виконують лише ту роботу, яку ви хочете. Якщо ви зробите $0 $@ &чи що завгодно, ви почнете спочатку знову і вам потрібно якось це зрозуміти.

Я насправді починаю думати про кілька розумних способів, за допомогою яких можна зробити саме це….

Але , перш ніж мій мозок занадто захопиться цим, я думаю, що досить хорошим правилом є: якщо ти намагаєшся написати щось в оболонці, і воно заповниться розумними хитрощами, і ти хочеш отримати більше мовних особливостей, час переключитися до реальної мови програмування .


2
Хоча ваш погляд добре сприйнятий - синтаксис баша може бути важким, і йому не вистачає більш елегантних структур даних та особливостей Perl або Python, bash настільки ж реальний, як він потрапляє у свою область . Це мова, що залежить від домену, і я б заперечував навіть краще (більш лаконічний, простіший), ніж, наприклад, Python у багатьох випадках. Чи можете ви керувати простором систем і не знаєте Python? Так. Чи можете ви це зробити, і не знаєте лизати баш [програмування]? Я б не хотів намагатися. Після 30 років програмування оболонок я кажу вам, що це так реально, як це стає. І так, я кажу на Python. Але не слід плутати молодих людей.
Майк S

2
Але це технічно мені більше подобається ця відповідь. Сказати, що "&" - це відповідь на запитання користувача, "вилка в один момент, щоб дві копії одного сценарію працювали", на мій погляд, заплутано. Що "&" робить, відповідно до посібника з bash, це "... виконує команду [задану] у фоновому режимі в нижній частині". Вона повинна припинити команду, і вона включає вилку (технічно, в Linux, клон ()), але в цей момент дві копії одного і того ж сценарію не запущені.
Майк S
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.