Нтерпретатор команд shell

Організація інтерфейсу з користувачем зазвичай не користується особливою увагою в курсах ОС. Причина цього в тому, що питання інтерфейсу досить далекі від кола проблем, що стосуються інших основних підсистем ОС.

Однак при вивченні UNIX можна обійти стороною таку цікаву і розвинену частину системи, як інтерпретатор команд, частіше званий просто шелл (shell).

Шелл не є частиною ядра UNIX, за своїм статусом це звичайна прикладна програма, що виділяється тільки своїм призначенням, яке полягає у виконанні команд користувача, що задаються або в інтерактивному (діалоговому) режимі, або у вигляді командних файлів, званих також шелл-скриптами. Існують різні варіанти шелла, які, співпадаючи в основному, пропонують дещо різні додаткові можливості.

Набір можливостей, що надаються будь-яким інтерпретатором команд UNIX, настільки широкий, що може бути предметом вивчення в окремому курсі. Тут буде дано тільки мінімальне уявлення про принципи роботи шелла. Більш придатною формою вивчення шелла є лабораторні роботи.

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

Базовою конструкцією мови команд UNIX (мови shell) є проста команда. Вона складається з імені команди і, можливо, параметрів, розділених пробілами. Ім'я команди - це зазвичай ім'я виконуваного файлу (або двійковій програми, або шелл-скрипта).

Більшість команд UNIX виводять результат своєї роботи в текстовому вигляді на стандартний вивід. Як і в MS-DOS, це фактично означає висновок у файл або пристрій, чий хендл дорівнює 1. За замовчуванням це означає, що результати виводяться на керуючий термінал користувача. Однак стандартний вивід легко може бути перенаправлений в файл або на пристрій. Для цього в команді використовуються символи '>' і '>>'.

Багато команд використовують також стандартний ввід (хендл 0), який за замовчуванням означає дані, що вводяться з клавіатури терміналу. Ознакою кінця введення служить комбінація Ctrl + D. Стандартний ввід також може бути перенаправлений для читання даних з файлу або з пристрою (за допомогою символу '<'), або навіть безпосередньо з тексту команди.

Як правило, стандартний висновок команд UNIX має якомога більш регулярну структуру. Наприклад, команда перегляду каталогу ls-l видає в кожному рядку інформацію про одному файлі, без загального заголовка і без підсумкових даних. Дуже часто виведення команди виглядає як таблиця, стовпці якої розділені знаками табуляції. Це полегшує подальшу обробку виведених даних наступними командами. З тих же міркувань команди не видають зайвих повідомлень типу «Команда успішно виконана», хоча можуть видавати повідомлення про помилки.

Для виконання команди шелл запускає окремий процес. У результаті виконання команди виробляється код завершення процесу, який може потім бути проаналізований. Нульове значення коду зазвичай означає нормальне завершення, значення, більше нуля - помилку.

Складова команда складається з простих команд, з'єднаних у вигляді конвеєра або списку.

Конвеєр означає паралельне виконання кількох команд з передачею даних по мірі їх обробки від однієї команди до наступної, як на заводському конвеєрі. Запис конвеєра складається з декількох команд, розділених знаками '|'. Для виконання конвеєра шелл запускає одночасно працюють процеси для кожної команди, при цьому стандартний вивід кожної команди перенаправляється на стандартний ввід наступної. Фактично для такого перенаправлення використовується механізм програмних каналів, описаний в п. 4.6.3. Перед запуском конвеєра шелл створює необхідну кількість каналів, а при запуску кожного процесу пов'язує його стандартні хендл 0 і 1 з відповідними каналами, як показано на рис. 4-4.

 

Рис. 1‑19

 

Список означає послідовне виконання команд. Він складається з декількох команд, розділених знаками ';', '&&' або '| |'. Якщо дві команди розділені знаком ';', то наступна команда запускається після завершення попередньої. Якщо команди розділені знаком '&&', то наступна буде виконуватися тільки в тому випадку, якщо код завершення попередньої дорівнює 0 (нормальне завершення). Навпаки, знак '| |' означає, що наступна команда буде виконуватися тільки в тому випадку, якщо код завершення попередньої не дорівнює 0 (завершення з помилкою).

Якщо запис команди закінчується символом '&', то шелл запускає процес її виконання у фоновому режимі, тобто не чекає завершення процесу, а переходить до наступної команді. При цьому фоновий процес продовжує працювати паралельно з Шеллі і запускаються їм іншими командами. Фоновий процес не має доступу до терміналу.

Як при інтерактивній роботі, так і при виконанні скриптів можуть визначатися і використовуватися змінні, що мають строкові значення. Ряд змінних визначається системою, наприклад, PATH містить список каталогів, в яких шелл шукає команди, а HOME - «домашній» каталог поточного користувача. Для отримання значення змінної перед її ім'ям записується символ '$'. У скриптах можна також використовувати значення параметрів, з якими був викликаний скрипт, від $ 1 до $ 9.

Шелл, як і будь-яка мова програмування, містить набір операторів управління порядком виконання команд, таких як if, case, while, until, for, break і деякі інші. Логічні вирази, використовувані в операторах управління, будуються на основі кодів завершення команд, при цьому спеціальна команда test дозволяє перевірити різноманітні умови, такі, як існування та тип вказаного файлу, рівність чи нерівність строкових і числових виразів і т.п.

Швидкість виконання шелл-скриптів у багато разів менше, ніж швидкість компілювати програми на C або іншою мовою, однак шелл дозволяє різко спростити вирішення багатьох практичних завдань, пов'язаних з управлінням операційною системою, обробкою текстових файлів і т.п. Це досягається за рахунок того, що шелл-скрипти дозволяють використовувати «великі блоки»: складати нові програми шляхом витонченого комбінування вже наявних програм-утиліт, набір яких у будь-якій сучасній версії UNIX досить великий.