Ожидание работы и концепция оболочки

Встроенная команда Bash ‘wait’ помогает мне понимать скрипты Bash как язык

Я просматривал исходный код основного скрипта в bash- проект http-monitoring, который недавно был опубликован на сайте социальных новостей. Общая идея заключалась в том, что он запускал несколько фоновых веб-запросов для параллельного выполнения и в конечном итоге составлял отчет о доступности различных веб-сайтов. Красиво, аккуратно и просто.

В основной части скрипта проекта srvmon я увидел следующее:

  # Выполняйте проверки параллельно для ключа в "$ {! urls [@]}" do value = $ {urls [$ key]} if [["$ (jobs | wc -  l) "-ge $ {maxConcurrentCurls}]];  then # выполнить 12 команд curl при максимальном параллельном ожидании -n fi doRequest "$ key" "$ value" & donewait  

Я заметил использование wait в этих двух местах и ​​был заинтригован; хотя я мог догадаться, что он делает, мне хотелось узнать больше. Немного покопавшись и поразмыслив над этим, меня поразило, что wait помогает мне лучше понять происхождение сценариев оболочки и почему его часто неправильно понимают.

Встроенная функция wait

Во-первых, что такое wait ? Ну, это (обычно) встроенная команда, то есть команда, встроенная в сам исполняемый файл оболочки, а не существующая как отдельная программа. Описание заголовка таково: wait «ожидает завершения задания и возвращает статус выхода». В статье в Википедии о нем отмечается, что он является встроенным, поскольку « должен знать таблицу заданий текущей среды выполнения оболочки », что имеет смысл с учетом его назначения.

Хотя в приведенном выше фрагменте кода есть несколько примеров, я подумал, что потрачу кофе на написание небольшого исследовательского скрипта под названием jobwait , чтобы почувствовать, как ждать может работать. Вот он:

  #!/Usr/bin/env bashlog () {echo "$ (date +% H:%  M:% S) $ * "} createjob () {local time = $ 1 local message = $ 2 (sleep" $ time "&& log" $ message ") & log" created job '$ message' ($ {time} s)  PID = $! "} Main () {createjob 10 medium createjob 15 long createjob 5 short log" jobs created "wait -n && log" a job has completed "wait && log" all jobs are finished "} main" $ @ "  

При запуске этого скрипта был получен следующий результат — обратите внимание на время для каждой записи журнала, которое показывает, когда была выпущена каждая запись журнала:

 ;./jobwait09: 03: 11 создано задание «среднее» (10 с) PID = 7267909: 03: 11 создано задание «длинное» (15 с) PID = 7268209: 03: 11 создано задание «короткое» (5 с) PID = 7268509: 03:  Создано 11 рабочих мест 09: 03: 16 short09: 03: 16 работа завершена09: 03: 21 medium09: 03: 26 long09: 03: 26 все работы завершены;  

Теперь ничего неожиданного в этом нет; тем не менее, было довольно приятно видеть, как все происходит в том порядке, в котором они происходили. Обратите внимание, что wait также возвращает статус завершения задания, и с использованием && я игнорирую это здесь на свой страх и риск, но это всего лишь тестовый сценарий .

Параметр -n заставляет wait ждать завершения следующего задания, каким бы оно ни было. Итак, здесь мы видим, что запись журнала «задание завершено» создается, как только завершается одно из заданий — в данном случае «короткое».

оболочка как командная среда

Теперь мы знаем, что может делать wait , я бы тоже хотел немного подумать о том, что он представляет .

Недавно мой обучающийся радар обнаружил различные разговоры, в которых мне казалось, что люди неправильно понимают, что такое сценарии оболочки. Это также появилось в этом месяце в ветке Lobster, где пользователь «pm» действительно помог мне понять, что разочаровывает в обсуждении «Bash против реального языка программирования».

Оболочка это как REPL для вашей операционной системы, интерактивная среда, в которой вы можете общаться с ней — управлять ресурсами, выполнять программы и так далее. В этом смысле язык этого разговора должен быть простым и иметь минимальный шум. Вам нужно просто ввести что-то, и это произойдет.

Более того, вы хотите указать значения с минимальными усилиями. Запустите программу, которая оперирует словом, или списком слов, или файлом, или списком файлов — вы же не хотите возиться с необходимостью цитировать эти слова в базовом регистре. И возможности, которые REPL предоставляет, чтобы вы могли в полной мере использовать ресурсы и программы, с которыми вы работаете, очень важны. Я думаю о конвейере Unix и перенаправлении ввода-вывода как о двух отличных примерах этого.

Эта ссылка на Unix напоминает мне замечательную статью, написанную в 1976 году одним из отцов Unix, Кеном Томпсоном. Это КОМАНДНЫЙ ЯЗЫК UNIX, который доступен в Интернет-архиве, но также в этом прекрасном репозитории стал более удобным для использования в различных форматах. Эта статья якобы является первой из когда-либо написанных о оболочке Unix, и ее приятно читать. В нем есть красиво простое введение в подоболочки, конвейеры и перенаправление ввода-вывода.

Возможно, более тонко, то, что мы знаем как источник сценариев оболочки сегодня, упоминается в названии статьи как «командный язык» ”, И вот что это такое. В этой статье много цитат, но я выберу здесь только одну, которая поможет мне подумать о том, что такое оболочка (и, косвенно, ее язык):

« Оболочка и выполняемые ею команды образуют язык выражений… [который] легко расширяется

Итак, этот REPL, наш интерфейс к операционной системе и ее ресурсам, — это командная среда, и наше прямое взаимодействие с ней осуществляется через командный язык, который был разработан, чтобы выразить наши намерения максимально простым и последовательным способом.

Вот еще одна цитата из раздела «ОБОЛОЧКА КАК КОМАНДА»:

« Оболочка — это просто еще одна команда, и, перенаправляя ее стандартный ввод, можно выполнять команды из файлов. »

Естественный переход к написанию сценариев

Итак, именно на этом этапе этого размышления мы начинаем переходить от REPL, где взаимодействие прямое… к набору команд, которые можно сохранить в файле и передается в оболочку, что, я думаю, можно рассматривать как косвенное взаимодействие.

Это, конечно, переход к сценариям, как к преднамеренным коллекциям элементов командного языка. И именно здесь wait имеет большой смысл; возможно, его можно было бы использовать в интерактивном режиме, но мне он кажется более полезным как способ заставить некоторые вещи приостанавливаться, пока другие вещи завершаются, в непрямом режиме … в автоматическом режиме выполнения командного языка. Создание сценариев.

Переход от прямого использования командного языка (включая синтаксис, который позволяет нам объединять программы в конвейеры и управлять вводом и выводом) к написанию сценариев, таким образом, очень тонкий и кажется мне нравится естественный вывод. И функции, которые делают командную среду и ее язык настолько полезными в контексте прямого взаимодействия в REPL, — это именно те функции, которые доступны и для написания сценариев.

Для меня это суть сценариев оболочки и объясняет, почему это так. Хотя имеет смысл писать отдельные программы на любом подходящем языке — и, конечно же, следить за тем, чтобы эти программы вели себя предсказуемым и полезным образом в контексте командной среды, особенно в отношении STDIN, STDOUT и STDERR, — это абсолютно не дает у меня есть какой-либо смысл предлагать заменить сам сценарий оболочки на «современный язык» (что бы это ни значило).

Чтобы повторить (намеренно абсурдную) концепцию, упомянутую ранее в ветке лобстеров, попробуйте заменив вашу оболочку на REPL «современного языка», например, на Node.js или Python, и вы увидите, как упадет ваша производительность. Попробуйте использовать ресурсы операционной системы, выполнить программы и отфильтровать их вывод или отправить фоновые задания (и дождитесь их завершения, прежде чем продолжить) — и вы скоро разорветесь.

Оболочка такая, какая есть не зря. Я доволен этим.

Оцените статью
techsly.ru
Добавить комментарий