Що таке Unix Shell. Еволюція командних оболонок Linux. Як автоматизувати операції резервного копіювання «за розкладом»

Багато хто вважає, що зробити програму, якою користуватимуться мільйони, дуже важко. Однак за будь-яким, навіть найскладнішим продуктом завжди стоїть проста ідея. Одним із них є командна оболонка, або «шелл». У цій статті розповімо, як написати спрощену командну оболонку Unix на C.

Порада Не варто здавати або використовувати (навіть у зміненому вигляді) наведений нижче код як домашній проект у школі або вузі. Багато викладачів знають про оригінальну статтю та викриють вас в обмані.

Життєвий цикл командної оболонки

Оболонка виконує три основні операції за час свого існування:

  1. Ініціалізація: на цьому етапі вона читає та виконує свої файли конфігурації. Вони змінюють її поведінку.
  2. Інтерпретація: далі оболонка зчитує команди зі stdin і виконує їх.
  3. Завершення: після виконання основних команд вона виконує команди вимикання, звільняє пам'ять та завершує роботу.

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

Int main(int argc, char **argv) ( // Завантаження файлів конфігурації за їх наявності. // Запуск циклу команд. lsh_loop(); // Вимкнення / очищення пам'яті. return EXIT_SUCCESS; )

У прикладі вище можна побачити функцію lsh_loop() , яка циклічно інтерпретуватиме команди. Реалізацію розглянемо трохи нижче.

Базовий цикл командної оболонки

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

  1. Читання: зчитування команди із стандартних потоків.
  2. Парсинг: розпізнавання програми та аргументів у вхідному рядку.
  3. Виконання: запуск розпізнаної команди.

Ця ідея реалізована функції lsh_loop() :

Void lsh_loop(void) ( char *line; char **args; int status; do ( printf("> "); line = lsh_read_line(); args = lsh_split_line(line); status = lsh_execute(args); free(line) );free(args); )while (status);

Пройдемося за кодом. Перші кілька рядків – це просто оголошення. Цикл з постумовою зручніший для перевірки стану змінної, оскільки виконується перед перевіркою її значення. Всередині циклу виводиться запрошення введення, викликаються функції для читання вхідного рядка та розбиття рядка на аргументи, а потім виконуються аргументи. Далі звільняється пам'ять, виділена під рядок та аргументи. Варто звернути увагу, що у коді використовується змінна стани, що повертається до lsh_execute() і визначає, коли потрібно вийти з функції.

Читання рядка

Читання рядка зі стандартного потоку введення - це начебто просто, але в C це може викликати багато клопоту. Погано те, що ніхто не знає заздалегідь, скільки тексту користувач введе в командну оболонку. Не можна просто виділити блок та сподіватися, що користувачі не вийдуть за нього. Натомість потрібно перерозподіляти виділений блок пам'яті, якщо користувачі вийдуть за його межі. Це стандартне рішенняв C і саме воно буде використовуватися для реалізації lsh_read_line() .

#define LSH_RL_BUFSIZE 1024 char *lsh_read_line(void) ( int bufsize = LSH_RL_BUFSIZE; int position = 0; char *buffer = malloc(sizeof(char) * bufsize); int c; if (! : помилка виділення пам'яті\n"); exit(EXIT_FAILURE); ) while (1) ( // Читаємо символ c = getchar(); // При зустрічі з EOF замінюємо його нуль-термінатором і повертаємо буфер if (c == EOF || c == "\n") ( buffer = "\0"; return buffer; ) else ( buffer = c; ) position++; // Якщо ми перевищили буфер, перерозподіляємо блок пам'яті if (position >= bufsize) ( bufsize += LSH_RL_BUFSIZE; buffer = realloc(buffer, bufsize); if(!buffer)

У першій частині багато оголошень. Слід зазначити, що у коді використовується старий стиль C, саме оголошення змінних до основної частини коду. Основна частина функції знаходиться всередині, здавалося б, нескінченного циклу while(1) . У циклі символ зчитується і зберігається як int , а чи не char (EOF - це ціле число, а чи не символ, тому для перевірки використовуйте int). Якщо символ перекладу рядка або EOF, ми завершуємо поточний рядокі повертаємо її. У протилежному випадку символ додається до існуючого рядка.

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

Ті, хто знайомий з новими версіями стандартної бібліотеки C, можуть помітити, що stdio.h має функцію getline() , яка виконує більшу частину роботи, реалізованої в коді вище. Ця функція була розширенням GNU для бібліотеки C до 2008 року, а потім була додана до специфікації, тому більшість сучасних Unix-систем вже йдуть із нею в комплекті. З getline функція стає тривіальною:

Char *lsh_read_line(void) ( char *line = NULL; ssize_t bufsize = 0; // getline сама виділить пам'ять getline(&line, &bufsize, stdin); return line; )

Парсинг рядка

Тепер нам потрібно розпарсувати вхідний рядок до списку аргументів. Ми зробимо невелике спрощення та заборонимо користувачеві використовувати лапки та зворотну косу межу в аргументах командного рядка. Натомість для поділу аргументів ми просто використовуватимемо прогалини. Таким чином команда echo "ось повідомлення" буде викликати команду echo не з одним аргументом "ось повідомлення", а з двома: "ось" та "повідомлення".

Тепер все, що нам потрібно зробити - розбити рядок на частини, використовуючи пробіли як роздільники. Це означає, що ми можемо використовувати класичну функцію бібліотеки strtok .

#define LSH_TOK_BUFSIZE 64 #define LSH_TOK_DELIM " \t\r\n\a" char **lsh_split_line(char *line) ( int bufsize = LSH_TOK_BUFSIZE, position = 0; char **tokens = malloc(bufsize ); char *token; if (!tokens) ( fprintf(stderr, "lsh: помилка виділення пам'яті\n"); exit(EXIT_FAILURE); ) token = strtok(line, LSH_TOK_DELIM); while (token != NULL) ( tokens = token; position++; if (position >= bufsize) ( bufsize += LSH_TOK_BUFSIZE; tokens = realloc (tokens, bufsize * sizeof(char*)); \n"); exit(EXIT_FAILURE); ) ) token = strtok(NULL, LSH_TOK_DELIM); ) tokens = NULL; return tokens; )

Реалізація цієї функції підозріло нагадує lsh_read_line() , і це неспроста! Тут використовується та ж стратегія, тільки замість нуль-термінованого масиву символів ми використовуємо нуль-термінований масив покажчиків.

Ми починаємо розбиття, викликаючи strtok . Вона повертає покажчик перший шматок рядки (токен). Взагалі strtok() повертає покажчики на місця у рядку і поміщає нуль-термінатори наприкінці кожного токена. Ці покажчики ми зберігаємо у окремому масиві.

За потреби ми перерозподілимо масив покажчиків. Повторюємо процес доти, доки strtok не перестане повертати токени, і завершуємо масив токенів нуль-термінатором.

Тепер у нас є масив токенів, готових до виконання.

Як командні оболонки запускають процеси

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

У Unix є лише два способи запуску процесів. Перший (який не будемо брати до уваги) - це Init. Чи бачите, коли завантажується Unix-система, завантажується її ядро. Після завантаження та ініціалізації ядро ​​запускає лише один процес, який називається Init. Цей процес виконується протягом усього часу роботи комп'ютера, та керує завантаженням інших процесів, які необхідні для його роботи.

Оскільки інші процеси не Init , залишається лише одне практичний спосіб запуску процесів: системний виклик fork() . Коли ця функція викликається, операційна система робить дублікат процесу та запускає їх паралельно. Початковий процес називається «батьківським», а новий – «дочірнім». Дочірньому процесу fork() повертає 0 , а батькові - ідентифікатор процесу (PID) його дочірнього елемента. Таким чином, будь-який новий процесможна створити лише з копії існуючого.

Це може бути проблемою. Зазвичай, коли ви хочете запустити новий процес, вам не потрібна копія програми, що вже працює - ви хочете запустити іншу програму. Для цього потрібно використати системний виклик exec(). Він замінює поточну запущену програмуабсолютно новою. Це означає, що при викликі exec операційна система зупиняє процес, завантажує нову програму та запускає її на тому самому місці. виклик exec() не повертає процес, якщо немає помилки.

Завдяки цим двом системним викликам і можливий запуск більшості програм у Unix. Спершу існуючий процес роздвоюється на батьківський та дочірній, а потім дочірній процес використовує exec() для заміни себе новою програмою. Батьківський процес може продовжувати робити інші речі, а також стежити за своїми дочірніми елементами, використовуючи системний виклик wait().

Так, інформації чимало. Давайте подивимося на код запуску програми:

Int lsh_launch(char **args) ( pid_t pid, wpid; int status; pid = fork(); if (pid == 0) ( // Дочірній процес if (execvp(args, args) == -1) ( perror ("lsh"); ) exit(EXIT_FAILURE); ) else if (pid< 0) { // Ошибка при форкинге perror("lsh"); } else { // Родительский процесс do { wpid = waitpid(pid, &status, WUNTRACED); } while (!WIFEXITED(status) && !WIFSIGNALED(status)); } return 1; }

Ця функція приймає перелік аргументів, які ми створили раніше. Потім вона розгортає процес і зберігає значення, що повертається. Як тільки fork() повертає значення, ми отримуємо два паралельні процеси. Дочірньому процесу відповідає перша умова if (де pid == 0).

У дочірньому процесі ми хочемо запустити команду, задану користувачем. Тому ми використовуємо один із варіантів системного виклику exec, execvp. Різні варіанти exec роблять різні речі. Одні приймають змінну кількість рядкових аргументів, інші беруть список рядків, а треті дозволяють вказати оточення, у якому виконується процес. Цей конкретний варіант приймає ім'я програми та масив (також званий вектором, звідси "v") рядкових аргументів (першим має бути ім'я програми). "p" означає, що замість надання повного шляху до файлу програми для запуску ми вкажемо тільки її ім'я, а також операційній системі шукати її самостійно.

Якщо команда exec повертає -1 (або будь-яке інше значення), це означає, що виникла помилка. Таким чином, ми використовуємо perror для виведення повідомлення про помилку разом із ім'ям програми, щоб було зрозуміло, де сталася помилка. Потім ми завершуємо процес, але так, щоб програмна оболонка продовжувала працювати.

Друга умова (pid< 0) проверяет, произошла ли в процессе выполнения fork() ошибка. Если ошибка есть, мы выводим сообщение об этом на экран, но программа продолжает работать.

Третя умова означає, що виклик fork() виконано успішно. Там знаходиться батьківський процес. Ми знаємо, що нащадок збирається виконати процес, тож батько має дочекатися завершення команди. Ми використовуємо waitpid() для очікування зміни стану процесу. На жаль, waitpid() має багато опцій (наприклад, exec()). Процеси можуть змінювати свій стан безліччю способів, і всі стану означають, що процес завершився. Процес може завершитися звичайним шляхом (успішно або з кодом помилки), або бути зупинений сигналом. Таким чином, ми використовуємо макроси, що надаються waitpid() , щоб переконатися, що процес завершено. Потім функція повертає 1 як сигнал викликає функції, що вона може вивести запрошення введення.

Вбудовані функції оболонки

Можливо, ви помітили, що функція lsh_loop() викликає lsh_execute() , але ми назвали нашу функцію lsh_launch() . Це було навмисно! Справа в тому, що більшість команд, які виконує оболонка, є програмами – але не всі. Деякі з команд убудовані прямо в оболонку.

Причина досить проста. Якщо ви бажаєте змінити каталог, вам потрібно використовувати функцію chdir(). Справа в тому, що поточний каталог є властивістю процесу. Отже, скажімо, ви написали програму cd , яка змінює каталог. Вона просто змінює свій поточний каталог та завершується, але поточний каталог батьківського процесу не зміниться. Натомість процес оболонки повинен виконати chdir() , щоб оновити свій каталог. Потім, коли він запускає дочірні процеси, вони також успадковують цей каталог.

Аналогічно, програма з ім'ям exit не зможе вийти з командної оболонки, яка її викликала. Ця команда також має бути вбудована в оболонку. Крім того, більшість оболонок налаштовуються за допомогою конфігураційних сценаріїв, таких як ~/.bashrc . Ці сценарії використовують команди, які змінюють роботу оболонки. Самі ж команди можуть змінити роботу оболонки, якщо вони були реалізовані всередині самої оболонки.

Відповідно, має сенс додати деякі команди до оболонки. У цю оболонку ми додамо cd, exit та help. А ось і реалізація цих функцій:

/* Оголошення функцій для вбудованих команд оболонки: */ int lsh_cd(char **args); int lsh_help(char **args); int lsh_exit(char **args); /* Список вбудованих команд, за якими слідують відповідні функції */ char *builtin_str = ("cd", "help", "exit"); int (*builtin_func) (char **) = (&lsh_cd, &lsh_help, &lsh_exit); int lsh_num_builtins() ( return sizeof(builtin_str) / sizeof(char *); ) /* Реалізації вбудованих функцій */ int lsh_cd(char **args) ( if (args == NULL) ( fprintf(stderr, "lsh: очікується) аргумент для \"cd\"\n"); ) else ( if (chdir(args) != 0) ( perror("lsh"); ) ) return 1; ) ; printf("LSH Стівена Бреннана\n"); printf("Наберіть назву програми та її аргументи і натисніть enter.\n"); printf("Ось список вбудованих команд:\n"); for (i = 0; i< lsh_num_builtins(); i++) { printf(" %s\n", builtin_str[i]); } printf("Используйте команду man для получения информации по другим программам.\n"); return 1; } int lsh_exit(char **args) { return 0; }

Код складається із трьох частин. Перша частина містить попереднє оголошення функцій. Попереднє оголошення - це коли ви оголошує (але не визначаєте) щось, щоб можна було використовувати це ім'я до його визначення. lsh_help() - причина, через яку ми робимо це. Вона використовує масив вбудованих функцій, а масиви містять lsh_help() . Найпростіший спосіб розбити цей цикл залежностей – це попереднє оголошення.

Наступна частина є масив імен вбудованих команд, за якими слідує масив відповідних функцій. Це означає, що в майбутньому вбудовані команди можуть бути додані шляхом зміни цих масивів, а не великого оператора switch десь у коді. Якщо ви збентежені оголошенням builtin_func , все гаразд. Це масив покажчиків на функції (які приймають масив рядків та повертають int). Будь-яке оголошення, що включає вказівники на функції C, може стати дійсно складним.

Зрештою, йде реалізація кожної функції. Функція lsh_cd() спочатку перевіряє наявність другого аргументу і виводить повідомлення про помилку, якщо його немає. Потім вона викликає chdir(), перевіряє наявність помилок і завершує роботу. Функція довідки відображає інформаційне повідомлення та імена всіх вбудованих функцій. А функція виходу повертає 0 як сигнал для закінчення циклу команд.

Об'єднання вбудованих функцій та процесів

Останній відсутній фрагмент головоломки полягає в реалізації функції lsh_execute(), яка або запускає або вбудований, або інший процес.

Int lsh_execute(char **args) ( int i; if (args == NULL) ( // Була введена порожня команда. return 1; ) for (i = 0; i< lsh_num_builtins(); i++) { if (strcmp(args, builtin_str[i]) == 0) { return (*builtin_func[i])(args); } } return lsh_launch(args); }

Код перевіряє, чи команда вбудована. Якщо так, то запускає її, а інакше викликає lsh_launch() , щоб запустити процес.

Збираємо всі разом

Ось і весь код, який входить до командної оболонки. Якщо ви уважно читали статтю, то мали зрозуміти, як працює оболонка. Щоб випробувати оболонку (на Linux), потрібно скопіювати ці сегменти коду в файл main.c і скомпілювати його. Обов'язково увімкніть лише одну реалізацію lsh_read_line() . Вам потрібно буде включити такі заголовні файли:

  • #include
    • waitpid() і пов'язані макроси
  • #include
    • chdir()
    • fork()
    • exec()
    • pid_t
  • #include
    • malloc()
    • realloc()
    • free()
    • exit()
    • execvp()
    • EXIT_SUCCESS , EXIT_FAILURE
  • #include
    • fprintf()
    • printf()
    • stderr
    • getchar()
    • perror()
  • #include
    • strcmp()
    • strtok()

Щоб скомпілювати файл, введіть у терміналі gcc -o main main.c , а потім /main , щоб запустити.

Крім того, всі вихідні джерела доступні на GitHub .

Підбиваючи підсумки

Очевидно, що ця оболонка не є багатофункціональною. Деякі з її недоглядів:

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

Щоб розібратися у системних дзвінках, рекомендуємо звернутися до мануала: man 3p . Якщо ви не знаєте, який інтерфейс вам пропонують стандартна бібліотека C і Unix, радимо переглянути специфікацію POSIX, зокрема розділ 13.

Командна мова shell (у перекладі - раковина, шкаралупа) фактично є мова програмування дуже високого рівня. Цією мовою користувач здійснює керування комп'ютером. Зазвичай після входу в систему ви починаєте взаємодіяти з командною оболонкою. Ознакою те, що оболонка (shell) готова до прийому команд служить промптер, що видається нею на екран. У найпростішому випадку це один долар ($). Shell не є необхідною і єдиною командною мовою (хоча саме вона стандартизована в рамках POSIX – стандарту мобільних систем). Наприклад, чималу популярність користується мова cshell, є також kshell, bashell та інші. Більше того, кожен користувач може створити свій командна мова. Може одночасно на одному примірнику операційної системи працювати з різними командними мовами. shell – це одна з багатьох команд UNIX. Тобто набір команд оболонки "shell" входить команда "sh" - виклик інтерпретатора "shell". Перший "shell" викликається автоматично при вході в систему і видає на екран промтер. Після цього ви можете викликати виконання будь-які команди, зокрема і знову сам " shell " , який вам створить нову оболонку всередині колишньої. Так, наприклад, якщо ви підготуєте в редакторі файл "file_1":

Echo Hello!

то це буде звичайний текстовий файл, що містить команду "echo", яка при виконанні видає все написане правіше за неї на екран. Можна зробити файл "file_1", що виконується за допомогою команди "chmod 755 file_1". Але його можна виконати, викликавши явно команду "sh" ("shell"):

Sh file_1

Sh< file1

Файл можна виконати і у поточному екземплярі "shell". І тому існує специфічна команда "." (Точка), тобто.

File_1

Оскільки UNIX - система розрахована на багато користувачів, ви можете навіть на персональному комп'ютері працювати паралельно, скажімо, на 12-ти екранах (перехід з екрану на екран ALT/функціональна клавіша), маючи на кожному екрані нового (або одного і того ж) користувача зі своєю командною оболонкою. Можете і в графічному режимі X-Window також відкрити велику кількість вікон, а в кожному вікні може бути власний юзер зі власною командною оболонкою... Стрижневим елементом мови shell є команда.

Структури команд:

Команди в shell зазвичай мають такий формат:

<имя команды> <флаги> <аргумент(ы)>

Наприклад:

Ls -ls /usr/bin

Де ls - ім'я команди видачі вмісту директорія, -ls - прапори ("-" - ознака прапорів, l - довгий формат, s - об'єм файлів у блоках), /usr/bin - директорій, для якого виконується команда. Ця команда видасть на екран у довгому форматі вміст директорія /usr/bin, при цьому додасть інформацію про розмір кожного файлу в блоках.На жаль, така структура команди витримується далеко не завжди.Не завжди перед прапорами ставиться мінус, не завжди прапори йдуть одним словом. різноманітність і в поданні аргументів До числа команд, що мають екзотичні формати, належать і такі "ходові" команди, як сс - виклик компілятора мови С, tar - робота з архівами, dd - копіювання файлу з перетворенням, find - пошук файлів та ряд інших Як правило, перше слово shell сприймає як команду, тому в командному рядку

перше слово буде розшифроване shell як команда (конкатенації), яка видасть на екран файл з ім'ям "cat" (друге слово), що знаходиться в поточному директорії. Перенаправлення команд Стандартне введення (вхід) - "stdin" в ОС UNIX здійснюється з клавіатури терміналу, а стандартне виведення (вихід) - "stdout" спрямовано екран терміналу. Існує ще й стандартний файл діагностичних повідомлень - "stderr", про який буде трохи пізніше. Команда, яка може працювати зі стандартним входом та виходом, називається ФІЛЬТРОМ. Користувач має зручні засоби перенаправлення введення та виведення на інші файли (пристрої). Символи ">" та ">>" позначають перенаправлення виводу. ls >file_1 команда "ls" сформує список файлів поточного каталогу та помістить його у файл "file_1" (замість видачі на екран). Якщо файл "file_1" раніше існував, він буде затертий новим.

Pwd >>file_1

команда pwd сформує повне ім'я поточного каталогу і помістить їх у кінець файлу "file_1", тобто. ">>" додає файл, якщо він непустий. Символи<" и "<<" обозначают перенаправление ввода.

Wc-l

підрахує та видасть на екран число рядків у файлі file_1.

Ed file_2<

створить із використанням редактора файл "file_2", безпосередньо з терміналу. Закінчення введення визначається за символом, що стоїть правіше.<<" (т. е. "!"). То есть ввод будет закончен, когда первым в очередной строке будет "!". Можно сочетать перенаправления. Так

Wc-l file_4

Wc -l >file_4

виконуються однаково: підраховується число рядків файлу "file_3" і результат міститься у файл "file_4". Засіб, що поєднує стандартний вихід однієї команди зі стандартним входом іншої, називається конвеєром і позначається вертикальною рисою "|".

Ls | wc -l

Список файлів поточного каталогу буде спрямований на вхід команди "wc", яка на екран виведе число рядків каталогу. Конвеєром можна об'єднувати і більше двох команд, коли всі вони, можливо, крім першої та останньої - фільтри:

cat file_1 | grep-h result | sort | cat -b > file_2

Даний конвеєр із файлу "file_1" ("cat") вибере всі рядки, що містять слово "result" ("grep"), відсортує ("sort") отримані рядки, а потім пронумерує ("cat -b") і виведе результат у файл "file_2". Оскільки пристрої UNIX представлені спеціальними файлами, їх можна використовувати при перенаправленні. Спеціальні файли знаходяться у каталозі "/dev". Наприклад, "lp" - друк; "console" – консоль; "ttyi" - i-ий термінал; "null" - фіктивний (порожній) файл (пристрій). Тоді, наприклад,

Ls > /dev/lp

виведе вміст поточного каталогу на друк, а file_1< /dev/null обнулит файл "file_1".

Sort file_1 | tee /dev/lp | tail -20

У цьому випадку буде відсортовано файл "file_1" і передано на друк, а останніх 20 рядків також будуть видані на екран. Повернемося до перенаправлення виходу. Стандартні файли мають номери:

0 - stdin, 1 - stdout 2 - stderr. Якщо вам не бажано мати на екрані повідомлення про помилку, ви можете перенаправити його з екрана у вказаний вами файл (або взагалі "викинути", перенаправивши файл "порожнього пристрою" - /dev/null). Наприклад, під час виконання команди

Cat file_1 file_2

яка повинна видати на екран послідовно вміст файлів "file_1" та "file_2", видасть вам, наприклад, наступне

111111 222222 cat: f2: No such file or directory

де 111111 222222 - вміст файлу "file_1", а файл "file_2" відсутня, про що команда "cat" видала повідомлення до стандартного файлу діагностики, за замовчуванням, як і стандартний вихід, представлений екраном. Якщо вам не бажано таке повідомлення на екрані, його можна перенаправити у вказаний файл:

Cat file_1 file_2 2>f-err

повідомлення про помилки будуть надсилатися (про це говорить перенаправлення "2>") у файл "f-err". До речі, ви можете всю інформацію надсилати в один файл "ff", використовуючи в даному випадкуконструкцію

Cat file_1 file_2 >>ff 2>ff

Можна вказати не тільки який із стандартних файлів перенаправляти, а й у який стандартний файл здійснити перенаправлення.

Cat file_1 file_2 2>>ff 1>&2

Тут спочатку "stderr" перенаправляється (в режимі додавання) у файл "ff", а потім стандартний вихід перенаправляється на "stderr", яким на цей момент є файл "ff". Тобто результат буде аналогічним до попереднього. Конструкція "1>&2" - означає, що крім номера стандартного файлу, який перенаправити, необхідно попереду ставити "&"; вся конструкція пишеться без прогалин.<- закрывает стандартный ввод. >- Закриває стандартний висновок. Командні файли Для того, щоб текстовий файл можна використовувати як команду, існує кілька можливостей. Нехай за допомогою редактора створено файл з ім'ям "cmd", що містить один рядок такого вигляду:

Date; pwd; ls

Можна викликати shell як команду, що позначається "sh", і передати їй файл "cmd" як аргумент або як перенаправлений вхід, тобто.

$ sh cmd

$sh

В результаті виконання будь-якої з цих команд буде видано дату, потім ім'я поточного каталогу, а потім вміст каталогу. Цікавіший і зручний варіант роботи з командним файлом - це перетворити його на виконуваний, тобто. просто зробити його командою, що досягається зміною коду захисту. Для цього необхідно дозволити виконання цього файлу. Наприклад,

Chmod 711 cmd

зробить код захисту "rwx__x__x". Тоді простий виклик

призведе до виконання тих самих трьох команд. Результат буде той самий, якщо файл із вмістом

Date; pwd; ls

представлений у вигляді: date pwd ls тому що перехід на інший рядок також є роздільником у послідовності команд. Таким чином, файлами, що виконуються, можуть бути не тільки файли, отримані в результаті компіляції та складання, але й файли, написані мовою shell. Їхнє виконання відбувається в режимі інтерпретації за допомогою shell-інтерпретатора

Налагодження командних файлів

У SHELL використовуються два механізми налагодження командних файлів. Перший: set -v виводить рядки командного файлуу міру їхнього читання. Цей режим застосовується під час пошуку синтаксичних помилок. Для його використання не потрібно модифікувати командний файл, наприклад: sh -v proc... тут proc - ім'я командного файлу. Ключ -v може використовуватися разом з ключем -n, що запобігає виконання наступних за ним команд (команда set -n блокує термінал доти, доки не вводиться ознака кінця файлу EOF). Команда set -х виводить команди у міру їх виконання, причому на термінал виводяться рядки програми і місце змінних підставляються їх значення. Для скасування ключів -x і -v можна скористатися командою set – а для встановлення – привласнити відповідне значення макрозмінної. СЕРЕДОВИЩЕ SHELL (ЗМІННІ ТА ПАРАМЕТРИ) На мові shell можна писати командні файли і за допомогою команди "chmod" робити їх виконуваними. Після цього вони ні чим не відрізняються від інших команд UNIX.

Shell-змінні

Ім'я shell-змінної - це послідовність літер, цифр і підкреслень, що починається з літери. Значення shell-змінної - рядок символів. Те, що в shell всього два типи даних: рядок символів і текстовий файл, з одного боку, дозволяє легко залучати до програмування кінцевих користувачів, які ніколи раніше не займалися програмуванням, а з іншого боку, викликає якийсь внутрішній протест у багатьох програмістів, які звикли до істотно більшого розмаїття та більшої гнучкості мовних засобів. Однак цікаво спостерігати те, як висококласні програмісти, освоївшись з "правилами гри" shell, пишуть на ньому програми набагато швидше, ніж на Сі, але, що особливо цікаво, в ряді випадків ці програми працюють навіть швидше, ніж реалізовані на Сі. Ім'я змінної аналогічно традиційному ставлення до ідентифікатору, тобто. іменем може бути послідовність літер, цифр та підкреслень, що починається з літери або підкреслення. Для надання значень змінним може використовуватися оператор присвоєння "=".

Var_1=13 - "13" - це число, а рядок із двох цифр. var_2="ОС UNIX" - тут подвійні лапки (" ") необхідні, тому що в рядку є пробіл.

Можливі й інші способи надання значень shell-змінним. Так наприклад запис,

DAT=`date`

призводить до того, що спочатку виконується команда "date" (зворотні лапки говорять про те, що спочатку повинна бути виконана укладена в них команда), а результат її виконання замість видачі на стандартний вихід приписується як значення змінної, в даному випадку " DAT". Можна надати значення змінної і за допомогою команди "read", яка забезпечує прийом значення змінної з (клавіатури) дисплея в діалоговому режимі. Зазвичай команді "read" у командному файлі передує команда "echo", яка дозволяє попередньо видати повідомлення на екран. Наприклад:

Echo -n "Введіть тризначне число:" read x

При виконанні цього фрагмента командного файлу після виведення на екран повідомлення

Введіть тризначне число:

інтерпретатор зупиниться і чекатиме введення значення з клавіатури. Якщо ви ввели, скажімо, "753", то це і стане значенням змінної "x". Одна команда "read" може прочитати (привласнити) значення відразу кількох змінних. Якщо змінних у "read" більше, ніж їх введено (через прогалини), решті присвоюється порожній рядок. Якщо значень, що передаються більше, ніж змінних у команді "read", то зайві ігноруються. При зверненні до shell-змінної необхідно ставити символ "$" перед ім'ям. Так команди echo $var_2 echo var_2 видадуть на екран

ОС UNIX var_2 Екранування

Розглянемо докладніше прийоми екранування, які у shell. Як засоби екранування використовуються подвійні лапки (" "), одинарні лапки (" ") і бек-слеш (\). З прикладів очевидна їхня дія: Можна в одному рядку записувати кілька присвоювань.

X=22 y=33 z=$x A="$x" B="$x" C=\$x D="$x + $y + $z" E="$x + $y + $z " F=$x\ +\ $y\ +\ $z

(привласнення G=$x+$y не було б виконано через прогалини) Тоді

Echo A = $A B = $B C = $C echo D = $D E = $E F = $F eval echo evaluated A = $A eval echo evaluated B = $B eval echo evaluated C = $C

Видадуть на екран

A = 22 B = $ x C = $ x D = 22 + 33 + 22 E = $ x + $ y + $ z F = 22 + 33 + 22 evaluated A = 22 evaluated B = 22 evaluated C = 22

Наведемо приклади, пов'язані з екрануванням перекладу рядка. Нехай змінній "string" присвоєно значення "масиву" 2x3: abc def Звернемо увагу, що для запобігання присвоюванню зайвих прогалин другий рядок масиву розпочато з першої позиції наступного рядка: string="abc def" Тоді три варіанти запису змінної в команді "echo" echo $string echo "$string" echo "$string" дадуть відповідно три різні результати: abc def $string abc def а послідовність команд echo "str_1 str_2" > file_1 echo "str_1 str_2" > file_2 cat file_1 file_2 дасть видасть послідовно однакові файли file_1 і file_2: str_1 str_2 str_1 str_2 Зауважимо також, що бек-слеш (\) не лише екранує наступний за ним символ, що дозволяє використовувати спеціальні символи просто як символи, що представляють самі себе (він може екранувати і сам себе - \\), але в командному файлі бек-слеш дозволяє об'єднувати рядки в один (екранувати кінець рядка). Наприклад, наведений раніше приклад командного рядка:

cat file_1 | grep-h result | sort | cat -b > file_2

може бути записаний у командному файлі, скажімо, як

cat file_1 | grep-h\result | sort | cat -b > file_2

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

cat file_1 | grep-h result | sort | cat -b > file_2

Маніпуляції з shell-змінними Незважаючи на те, що shell-змінні в загальному випадку сприймаються як рядки, тобто "35" - це не число, а рядок із двох символів "3" та "5", у ряді випадків вони можуть інтерпретуватись інакше, наприклад, як цілі числа. Різноманітні можливості має команда "expr". Проілюструємо деякі з прикладів: Виконання командного файлу:

X=7 y=2 a=`expr $x + $y`; echo a=$a a=`expr $a + 1`; echo a=$a b=`expr $y - $x`; echo b=$b c=`expr $x "*" $y`; echo c=$c d=`expr $x / $y`; echo d=$d e=`expr $x % $y`; echo e=$e

видасть на екран

A=9 a=10 b=-5 c=14 d=3 e=1

Операція множення ("*") обов'язково має бути заекранована, оскільки в shell цей значок сприймається як спецсимвол, що означає, що на це місце може бути підставлена ​​будь-яка послідовність символів. З командою "expr" можливі не тільки (цілочисленні) арифметичні операції, а й строкові:

A = `expr "cocktail": "cock"`; echo $A B=`expr "cocktail" : "tail"` ; echo $B C=`expr "cocktail" : "cook"` ; echo $C D=`expr "cock" : "cocktail"` ; echo $D

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

4 0 0 0

Експорт змінних У ОС UNIX існує процес. Процес виникає тоді, коли запускається виконання якась команда. Наприклад, при наборі на клавіатурі "р У свою чергу "р" може породити інші процеси. Припустимо, що "р" викликає "р1" і "р2", які послідовно породжують відповідні процеси. У кожного процесу є своє середовище - безліч доступних йому змінних Наприклад, до запуску "р" вже існувало середовище, в якому вже були визначені деякі змінні. Запуск "р" породжує нове середовище; вже в ній будуть породжені "р1" і "р2". оголошено, тобто де їм присвоєно значення, для того щоб вони були доступні й іншим процесам, що породжуються, треба передати їх явним чином, для цього використовується вбудована команда "export".

Параметри

У командний файл можна передати параметри. У shell використовуються позиційні параметри (тобто істотна черговість їхнього прямування). У командному файлі відповідні параметрам змінні (аналогічно shell-змінним) починаються із символу "$", а далі слідує одна з цифр від 0 до 9: Нехай "examp-1" викликається з параметрами "cock" і "tail". Ці параметри потрапляють у нове середовище під стандартними іменами "1" та "2". У (стандартній) змінній з іменем "0" зберігатиметься ім'я викликаного розрахунку. При зверненні до параметрів перед цифрою ставиться символ долара "$" (як і при зверненні до змінних) $0 відповідає імені даного командного файлу; $1 перший по порядку параметр; $2 другий параметр і т.д. Оскільки кількість змінних, які можуть передаватися параметри, обмежена однією цифрою, тобто. 9-ю ("0", як уже зазначалося має особливий зміст), то для передачі більшого числаПараметри використовують спеціальну команду "shift". Своєрідний підхід до параметрів дає команда "set". Наприклад, фрагмент

Set a b з echo перший=$1 другий=$2 третій=$3

видасть на екран

Перший = a другий = b третій = c

тобто. команда "set" встановлює значення параметрів. Це дуже зручно. Наприклад, команда "date" видає на екран поточну дату, скажімо, "Mon May 01 12:15:10 2000", що складається з п'яти слів, тоді

Set `date` echo $1 $3 $5

видасть на екран

Mon 01 2000

Команда "set" дозволяє також здійснювати контроль за виконанням програми, наприклад: set -v на термінал виводяться рядки, що читаються shell. set +v скасовує попередній режим. set -x термінал виводяться команди перед виконанням. set +x скасовує попередній режим. Команда "set" без параметрів виводить на термінал стан програмного середовища.

Підстановки shell-інтерпретатора

Перед початком безпосередньої інтерпретації та виконання команд, що містяться в командних файлах, shell виконує різні види підстановок: 1. ПІДСТАВКА РЕЗУЛЬТАТІВ. Виконуються всі команди, укладені у зворотні лапки, і їхнє місце підставляється результат. 2. ПІДСТАНОВКА ЗНАЧЕНЬ ПАРАМЕТРІВ І ЗМІННИХ. Тобто слова, що починаються на "$", замінюються відповідними значеннями змінних та параметрів. 3. ІНТЕРПРЕТАЦІЯ ПРОБІЛІВ. Заекрановані прогалини ігноруються. 4. ГЕНЕРАЦІЯ ІМЕН ФАЙЛІВ. Перевіряються слова на наявність у них спецсимволів ("*", "?","") та виконуються відповідні генерації. Програмне середовище Кожен процес має середовище, в якому він виконується. Shell використовує низку змінних цього середовища. Якщо ви наберете команду "set" без параметрів, то на екран буде видано інформацію про ряд стандартних змінних, створених при вході в систему (і переданих далі всім вашим новим процесам "у спадок"), а також змінних, створених та експортованих вашими процесами. Конкретний вигляд і зміст інформації, що видається, значною мірою залежить від того, яка версія UNIX використовується і як інстальована система.

Результат виконання команди set без параметрів (не повний):

HOME=/root PATH=/usr/local/bin:/usr/bin:/bin:.:/usr/bin/X11: IFS= LOGNAME=sae MAIL=/var/spool/mail/sae PWD=/home/ sae/STUDY/SHELL PS1=$(PWD):" " PS2=> SHELL=/bin/bash

Прокоментуємо значення змінних. HOME=/root - це ім'я домашнього директорія, в якому користувач опиняється після входу до системи. Тобто, правильно набравши ім'я та пароль, я опинюся в директорії "/root". PATH=/bin:/usr/bin:.:/usr/local/bin:/usr/bin/X11 - ця змінна задає послідовність файлів, які переглядає "shell" у пошуках команди. Імена файлів поділяються тут двокрапками. Послідовність перегляду відповідає черговості проходження імен у стежці. Але спочатку пошук відбувається серед про вбудованих команд. До вбудованих команд входять найчастіше використовувані команди, наприклад "echo", "cd", "pwd", "date". Після цього система переглядає директорій "/bin", в якому можуть бути команди "sh", "cp", "mv", "ls" і т.п. Потім директорій "/usr/bin" з командами "cat", "сс", "expr", "nroff", "man" та багатьма іншими. Далі пошук відбувається у поточному директорії (".", чи інше позначення "порожньо", тобто.""), де швидше за все знаходяться написані вами команди. Після набору командного рядка та натискання "shell" (після виконання необхідних підстановок) розпізнає ім'я, що відповідає команді та здійснює її пошук у директоріях, перерахованих у PATH. Якщо команда розміщена поза цими директоріями, вона не буде знайдена. Якщо є кілька команд з однаковим ім'ям, то викликана буде та, яка розташована в директорії, що переглядається першим. PATH, як і інші змінні, можна легко змінювати, додаючи, переставляючи чи виключаючи директорії. IFS= (Внутрішній Розділ Полів) перераховує символи, які служать для поділу слів (полів). Такими є "пробіл", "табуляція" та "переклад рядка", тому тут ліворуч від присвоювання нічого не видно і зайнято два рядки. LOGNAME=root – ім'я входу ("ім'я" користувача). MAIL=/var/spool/mail/root - ім'я файлу, який надходить (електронна) пошта. PWD=/root - ім'я поточного директорія PS1=$(PWD):" " - вид промтера. В даному випадку в промптері видаватиметься ім'я поточного директорія двокрапка та пропуск. Тобто тут буде "/root:". PS2=> - цей промтер (тут ">") використовується як запрошення до продовження введення (у черговому рядку) незакінченої команди. Наприклад, наберіть дужку "(", що відкриває, і після натискання у наступному рядку ви побачите цей промптер. Якщо поки не знаєте, що далі робити, наберіть дужку "), що закриває, і він зникне. SHELL=/bin/sh – ця змінна вказує оболонку, яку використовує користувач. У разі використовується стандартний shell ( " sh " ). Вихідне середовище встановлюється автоматично під час входу до системи з використанням файлів типу "/etc/rc" та "/etc/.profile". Один із способів просто змінить середовище (наприклад, шлях пошуку команд, вид промтера, вид оболонки, колір екрану тощо) можна, розмістивши цю інформацію у своєму домашньому директорії в спеціалізованому файлі ".profile" ($(HOME)/. profile), надавши потрібні значення змінним середовища. Тобто викликати це файл редактор і написати, що забажаєте). Тоді при кожному вході в систему цей файл буде автоматично виконуватися і встановлювати нове середовище. Цей файл повинен ОБОВ'ЯЗКОВО розміщуватись у вашій ДОМАШНІЙ директорії (директорії входу). Слід пам'ятати, що імена файлів, що починаються з точки, взагалі мають особливий статус. Так, вони не видаються на екран простою командою "ls" – необхідно викликати цю команду з прапором "-a". До речі, і не знищуються командою "rm*". Сам інтерпретатор shellавтоматично надає значення наступним змінним (параметрам): ? значення, повернене останньою командою; $ номер процесу; ! номер фонового процесу;

  1. число позиційних параметрів, що передаються в shell;
  • перелік параметрів, як один рядок;

@ перелік параметрів, як сукупність слів; - Прапори, що передаються в shell. При зверненні до цих змінних (тобто при використанні в командному файлі - shell-програмі) слід попереду ставити "$". Важливу роль під час створення унікальних файлів грає спеціальна змінна "$$", значення якої відповідає номеру процесу, виконує даний розрахунок. Кожен новий розрахунок, що виконується комп'ютером, ініціює один або кілька процесів, які автоматично отримують номери по порядку. Тому, використовуючи номер процесу як ім'я файлу, можна бути впевненим, що кожен новий файл матиме нове ім'я (не запишеться на місце вже існуючого). Перевага є і основним недоліком такого методу іменування файлів. Невідомо, які імена будуть надані файлам. І, якщо в рамках даного процесу можна знайти файл "не дивлячись", тобто звернувшись до нього, використовуючи $$, то потім такі файли можна легко втратити. Це створює додаткові проблеми при налагодженні програм. Виклик інтерпретатора Після реєстрації користувача в системі (за допомогою команди login) викликається інтерпретатор мови SHELL. Якщо реєстраційний довідник користувача містить файл.profile, то перш ніж з терміналу буде прийнято хоча б одну команду, інтерпретатор виконує цей файл (мається на увазі, що файл.profile містить команди). При викликі можуть вказуватися такі ключі: -c рядок Команди зчитуються із заданого рядка. -s Команди читаються із стандартного файлу введення. Повідомлення інтерпретатора записуються в стандартний діагностичний файл. -i Інтерактивний режим роботи. Якщо першим символом параметра "0" є знак -, команди зчитуються з файла.profile.

ПРОГРАМНІ СТРУКТУРИ===

Як у будь-якій мові програмування у тексті мовою shell можуть бути коментарі. Для цього використовується символ "#". Все, що знаходиться в рядку (у командному файлі) ліворуч від цього символу, сприймається інтерпретатором як коментар. Наприклад,

# Це коментар.

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

Команда test ("")

Команда test перевіряє виконання певної умови. З використанням цієї (вбудованої) команди формуються оператори вибору та циклу мови shell. Два можливі формати команди:

Test умова

[ умова ]

ми будемо користуватися другим варіантом, тобто. замість того, щоб писати перед умовою слово "test", укладатимемо умову в дужки, що звичніше для програмістів. Насправді shell розпізнаватиме цю команду по відкритій дужці "[", як слову, відповідному команді "test". Між дужками та умовою, що міститься в них, обов'язково повинні бути прогалини. Пробіли повинні бути і між значеннями та символом порівняння або операції У shell використовуються умови різних "типів". УМОВИ ПЕРЕВІРКИ ФАЙЛІВ: -f file файл "file" є звичайним файлом; -d файл файл "file" - каталог; -з файлом "file" - спеціальний файл; -r file є дозвіл на читання файлу "file"; -w file є дозвіл на запис у файл "file"; -s файл файл "file" не порожній.

УМОВИ ПЕРЕВІРКИ РЯДОК: str1 = str2 рядки "str1" і "str2" збігаються; str1 != str2 рядки "str1" і "str2" не збігаються; -n str1 рядок "str1" існує (непустий); -z str1 рядок "str1" не існує (порожній). приклади.

X = "who is who"; export x; ["who is who" = "$x"]; echo $? 0 x = abc; export x; [abc = "$x"]; echo $? 0 x = abc; export x; [-n "$x"]; echo $? 0 x=""; export x; [-n "$x"]; echo $? 1

Крім того, існують два стандартних значенняумови, які можна використовувати замість умови (для цього не потрібні дужки). УМОВИ ПОРІВНЯННЯ ЦИХ ЧИСЕЛ: x -eq y "x" дорівнює "y", x -ne y "x" нерівно "y", x -gt y "x" більше "y", x -ge y "x" більше або одно "y", x -lt y "x" менше "y", x -le y "x" менше або дорівнює "y". СКЛАДНІ УМОВИ: Реалізуються за допомогою типових логічних операцій: ! (not) інвертує значення коду завершення. -o (or) відповідає логічному "АБО". -a(and) відповідає логічному "І".

Умовний оператор "if"

У випадку оператор "if" має структуру

If умова then список

Тут "elif" скорочений варіант від "else if" можна використовувати поруч із повним, тобто. допускається вкладення довільної кількості операторів " if " (як та інших операторів). Зрозуміло " список " у кожному разі має бути осмислений і допустимий у цьому контексті. Найусіченіша структура цього оператора

If умова then список fi

якщо виконано умову (зазвичай це кому отримано код завершення "0", то виконується "список", інакше він пропускається. Приклади. Нехай написаний "if-1"

If [ $1 -gt $2 ]

then pwd else echo $0: Hello!

Тоді виклик if-1 12 11 дасть /home/sae/STUDY/SHELL а if-1 12 13 дасть if-1: Hello!

Оператор дзвінка ("case")

Оператор вибору "case" має структуру:

Case рядок in

шаблон) список команд;; шаблон) список команд;; ... шаблон) список команд;;

Тут "case" "in" та "esac" - службові слова. "Рядок" (це може бути і один символ) порівнюється з "шаблоном". Потім виконується "список команд" вибраного рядка. Незвично виглядають наприкінці рядків вибору ";;", але написати тут ";" було б помилкою. Для кожної альтернативи може бути виконано кілька команд. Якщо ці команди будуть записані в один рядок, символ ";" використовуватиметься як роздільник команд. Зазвичай останній рядок вибору має шаблон "*", що у структурі "case" означає "будь-яке значення". Цей рядок вибирається, якщо не відбувся збіг значення змінної (тут $z) з жодним із раніше записаних шаблонів, обмежених дужкою ")". Значення відображаються у порядку запису.

Оператор циклу з перерахуванням ("for")

Оператор циклу "for" має структуру:

For ім'я

do список команд done де "for" - службове слово визначає тип циклу, "do" і "done" - службові слова, що виділяють тіло циклу. Нехай команда "lsort" представлена ​​командним файлом

For i in file_1 file_2 file_3 do proc_sort $i done

У цьому вся прикладі ім'я " i " грає роль параметра циклу. Це ім'я можна розглядати як shell-змінну, якій послідовно надаються перераховані значення (i=file_1, i=file_2, i=file_3), і виконується в циклі команда "proc_sort". Найчастіше використовується форма "for i in *", що означає "для всіх файлів поточного каталогу". Нехай "proc_sort" у свою чергу представляється командним файлом

Cat $1 | sort | tee /dev/lp > $(1)_sorted

тобто. послідовно сортуються зазначені файли, результати сортування виводяться на друк ("/dev/lp") і направляються у файли file_1_sorted file_2_sorted та file_3_sorted

Оператор циклу із справжньою умовою ("while")

Структура "while", що також забезпечує виконання розрахунків, краще тоді, коли невідомий заздалегідь точний список значень параметрів або цей список повинен бути отриманий в результаті обчислень в циклі. Оператор циклу "while" має структуру:

While умова

do список команд done де "while" - службове слово, що визначає тип циклу з істинною умовою. Список команд у тілі циклу (між "do" і "done") повторюється доти, доки зберігається істинність умови (тобто код завершення останньої команди у тілі циклу дорівнює "0") або цикл не буде перерваний зсередини спеціальними командами ( "break", "continue" або "exit"). При першому вході в цикл умова повинна виконуватись. Команда "break [n]" дозволяє виходити із циклу. Якщо "n" відсутня, це еквівалентно "break 1". "n" вказує кількість вкладених циклів, з яких треба вийти, наприклад, "break 3" - вихід із трьох вкладених циклів. На відміну від команди "break" команда "continue [n]" лише припиняє виконання поточного циклу та повертає на ПОЧАТОК циклу. Вона також може бути параметром. Наприклад, "continue 2" означає вихід початку другого (якщо рахувати з глибини) вкладеного циклу. Команда "exit [n]" дозволяє вийти взагалі із процедури з кодом повернення "0" або "n" (якщо параметр "n" вказано). Ця команда може використовуватися у циклах. Навіть у лінійній послідовності команд вона може бути корисною при налагодженні, щоб припинити виконання (поточного) розрахунку в заданій точці.

Оператор циклу з помилковою умовою ("until")

Оператор циклу "until" має структуру:

Until умова

do список команд done де "until" - службове слово, що визначає тип циклу з помилковою умовою. Список команд у тілі циклу (між "do" і "done") повторюється до того часу, поки зберігається хибність умови чи цикл перерваний зсередини спеціальними командами ("break", "continue" чи "exit"). При першому вході в цикл умова не повинна виконуватись. Відмінність від оператора "while" у тому, що умова циклу перевіряється на хибність (на ненульовий код завершення останньої команди тіла циклу) перевіряється ПІСЛЯ кожного (зокрема і першого!) виконання команд тіла циклу. приклад.

Until false do

read x if [ $ x = 5 ] then echo enough ; break else echo some more fi

Тут програма з нескінченним цикломчекає на введення слів (повторюючи на екрані фразу "some more"), поки не буде введено "5". Після цього видається "enough" та команда "break" припиняє виконання циклу.

Порожній оператор

Порожній оператор має формат

:

Нічого не робить. Повертає значення "0".

Функції у shell

Функція дозволяє підготувати список команд shell для подальшого виконання. Опис функції має вигляд:

Ім'я() ( список команд )

після чого звернення до функції відбувається на ім'я. Під час виконання функції не створюється нового процесу. Вона виконується серед відповідного процесу. Аргументи функції стають її позиційними параметрами; Ім'я функції – її нульовий параметр. Перервати виконання функції можна оператором "return [n]", де (необов'язкове) "n" - код повернення.

Обробка переривань (trap)

Буває необхідно захистити виконання програми від переривання. Найчастіше доводиться зустрічатися з наступними перериваннями, що відповідають сигналам: 0 вихід з інтерпретатора, 1 відбій (відключення віддаленого абонента), 2 переривання від , 9 знищення (не перехоплюється), 15 закінчення виконання. Для захисту від переривань існує команда "trap", яка має формат:

Trap "список команд" сигнали

Якщо в системі виникнуть переривання, чиї сигнали перераховані через пробіл у "сигнали", то буде виконано "список команд", після чого (якщо у списку команд не було виконано команду "exit") керування повернеться в точку переривання і продовжиться виконання командного файлу. Наприклад, якщо перед припиненням переривання виконання якогось командного файлу необхідно видалити файли в "/tmp", то це може бути виконано командою "trap":

Trap "rm /tmp/* ; exit 1" 1 2 15

яка передує іншим командам файлу. Тут після видалення файлів буде здійснено вихід "exit" з командного файлу.

    Операційні системи сімейства Linux, як і будь-які інші ОС, припускають наявність інтерфейсу взаємодії між компонентами комп'ютерної системи і кінцевим користувачем, тобто наявність програмного рівня, який забезпечує введення команд та параметрів для отримання бажаних результатів. Такий програмний рівеньотримав назву "оболонка"або, англійською мовою - shell.

Що таке оболонка?

Командна оболонка ( shell) забезпечує взаємодію між користувачем та середовищем операційної системи Linux. Вона є спеціалізованою програмним продуктом, який забезпечує виконання команд та отримання результатів їх виконання, або, якщо зовсім спрощено, оболонка - це програма, яка призначена для забезпечення виконання інших програм за бажанням користувача. Прикладом оболонки може бути, наприклад, інтерпретатор команд command.comопераційної системи MS DOS, або оболонка bashопераційних систем Unix/ Linux.

Всі оболонки мають схожі функції та властивості, відповідно до їх основного призначення - виконувати команди користувача та відображати результати їх виконання:

Інтерпретація командного рядка.

Доступ до команд та результатів їх виконання.

Підтримка змінних, спеціальних символів та зарезервованих слів.

Обробка файлів, операцій стандартного введеннята висновку.

Реалізація спеціальної мови програмування оболонки.

    Для операційних систем сімейства Unix / Linux можливе використання кількох різних оболонок, що відрізняються властивостями та методами взаємодії із системою. Найбільш поширеними оболонками є

sh- оболонка Bourne , класична оболонкадля ОС Unix

bashоболонка Bourne Again(GNU Bourne-Again SHell). Мабуть, найбільш поширена на даний момент оболонка в середовищі ОС сімейства Linux.

ksh- оболонка Korn, розроблена як розвиток оболонки Bourneз історією командного рядка та можливістю редагування команд.

csh- оболонка C, що використовує синтаксис популярної мови програмування C

tcsh- версія оболонки Cз інтерактивним редагуванням командного рядка.

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

    У процесі завантаження операційних систем сімейства Linux після завантаження ядра системи виконується перехід в інтерактивний режим – режим взаємодії користувача та операційної системи. В ОС Linux, першим процесом, що запускається в ході завантаження, є програма ініціалізації initяка зчитує вміст конфігураційного файлу /etc/inittab, визначає перелік та характеристики терміналів, що є в системі, та викликає програму інтерактивного входу getty, що відображає запрошення для введення імені користувача. Після введення імені користувача та пароля, програма gettyвикликає програму login, яка перевіряє достовірність облікового запису, виконує перехід у домашній каталог користувача і передає управління програмі початкового запуску сеансу, якою зазвичай використовується програма оболонки користувача, конкретний різновид якої визначається вмістом файлу /etc/passwdдля цього облікового запису. Наприклад:

user1:x:508:511::/home/user1:/bin/sh
interbase:x:510:511::/home/interbase:/bin/csh
apb:x:511:513:apb:/home/apb:/bin/bash

Як видно із вмісту файлу /etc/passwdдля користувача user1буде запущено оболонку sh(оболонка Bourne), для користувача interbase- оболонка csh(оболонка C) та для користувача apb- оболонка bash(Bourne Again). Після старту оболонки на екран виводиться запрошення до введення команд (зазвичай у вигляді знака долара $ , якщо робота виконується в контексті облікового запису звичайного користувача, або фунта # , якщо оболонка використовується під обліковим записом привілейованого користувача ( root).

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

За допомогою команди exitвиконаною користувачем

При отриманні процесом оболонки сигналу kill, відправленого ядром, наприклад, при перезавантаженні системи.

Інтерпретація командного рядка.

    Введення користувача у відповідь на запрошення оболонки зазвичай називають командним рядкомабо командою. Команда Linux - це рядок символів з імені команди та аргументів, розділених пробілами. Аргументи надають команді Додаткові параметри, Що визначають її поведінку Найчастіше як аргументи використовуються опціїі іменафайлів та каталогів. Наприклад, командний рядок

ls -l file01 file02

Містить команду ls , опцію -l та два імені файлів file01 file02 .

При використанні кількох опцій їх можна об'єднувати. Наприклад, варіанти наступних команд ідентичні:

Ls -l -d
ls -ld

Команди, що є частиною оболонки, називаються вбудованими. До таких команд відносяться, наприклад, cd, if, case тощо. Природно, вбудовані команди можуть відрізнятися для різних варіантів оболонок. Крім вбудованих команд, можливе використання програмних модулів, що представляють окремі виконувані файли, або файлів скриптівабо сценаріїв- звичайних текстових файлів, що містять рядки, що послідовно виконуються, з командами оболонки. Деякі скрипти (сценарії) можуть виконуватися процесами Linux, наприклад, планувальником завдань cron. Планувальник завдань, зазвичай, призначений для автоматичного виконання завдань адміністрування системи за розкладом. Завдання cronє команди або скрипти і виконуються автоматично, без будь-якого втручання людини і можуть виконуватися в контексті різних облікових записів користувачів. У разі, коли завдання планувальника передбачає виконання будь-якого скрипту, виникає проблема вибору оболонки, яка має бути запущена як дочірній процес cronдля обробки команд із файлу скрипта - адже оболонка може бути будь-якою, а синтаксис скрипта, як правило, передбачає використання конкретної оболонки, під яку він написаний. Для усунення цієї проблеми, в ОС сімейства Linux прийнято в першому рядку скрипту вказувати різновид оболонки, необхідної для його виконання, у вигляді:

#!/bin/bash- для оболонки bash

#!/bin/sh- для оболонки sh

Знак # є ознакою коментаря і такі символи не інтерпретуються як команда. Такий прийом дозволяє вказати, яка оболонка повинна бути використана для обробки наступного вмісту файлу. Якщо ж скрипт не містить запис, який явно визначає необхідну оболонку, то будуть використані налаштування з облікового запису, в контексті якого виконується даний скрипт. У цьому випадку можлива ситуація, коли скрипт, написаний для оболонки, наприклад, tchбуде переданий для виконання в оболонку bashщо призведе до неможливості його виконання.

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

/etc/profile- встановлює змінні лише командних оболонок. Може запускати будь-які скрипти в оболонках, сумісних із Bourne shell.

/etc/bash.bashrc- встановлює змінні лише інтерактивних оболонок. Він також запускає bash-скрипти.

/etc/environment- Використовується модулем PAM-env. У цьому файлі можна вказувати лише пари ім'я = значення.

Кожен із цих файлів має свої особливості застосування, тому слід уважно вибирати той, який підходить для ваших цілей. Наприклад, якщо потрібно додати користувальницький каталог ~/binу змінну PATHдля всіх користувачів, помістіть наступний код в один з системних файлівініціалізації оточення (/etc/profile або /etc/bash.bashrc):

# Якщо ідентифікатор ID користувача більше або дорівнює 1000, існує каталог ~/bin, і він

#не був раніше доданий до змінної PATH,

# виконати експорт ~/bin у змінну $PATH.

If [[ $UID -ge 1000 && -d $HOME/bin && -z $(echo $PATH | grep -o $HOME/bin)

Export PATH=$HOME/bin:$(PATH)

Як правило, в операційних системах Linux, ідентифікатор користувача менше 1000 або менше 500 використовується для службових облікових записів. У даному прикладі, змінна оточення буде встановлена ​​для всіх локальних користувачівсистеми з ідентифікатором 1000 і більше.

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

- ~/.bash_profile, ~/.bash_loginі т.п. - Файли ініціалізації командної оболонки з домашнього каталогу користувача.

- ~/.profile- файл ініціалізації профілю користувача. Використовується багатьма оболонками визначення змінних середовища.

~/.pam_environment- Користувальницький аналог файлу /etc/environment, який використовується модулем PAM-env.

Наприклад, щоб додати каталог користувача ~/bin у шляху пошуку виконуваних файлів, заданих змінною PATHнаприклад, у файл ~/.profileпомістити рядок:

export PATH="$(PATH):/home/користувач/bin"

Щоб встановити змінні оточення для графічних додатків, використовується вміст файлів налаштування графічного середовища користувачів ~/.xinitrc

Набагато частіше значення змінних оточення задаються для поточного сеансукористувача. Наприклад, для додавання користувача каталогу ~/binу шляху пошуку виконуваних файлів:

export PATH=~/bin:$PATH

Нове значення змінної PATHдіятиме лише до завершення поточного сеансу користувача.

Для перегляду змінної можна використовувати команду echo $змінна, наприклад:

echo $PATH

В даний час, найпоширенішою оболонкою, як уже згадувалося вище, є bash. Викликано це, насамперед тим, що оболонка bashє sh- сумісною командною оболонкою, до якої додано корисні можливості з оболонок Korn shell ( ksh) та C shell ( csh). Оболонка bashможе без будь-якої модифікації виконувати більшість скриптів, написаних під мову програмування оболонки shі максимально намагається наблизитися до стандарту POSIX, що призвело до появи множини поліпшень, причому як для програмування, так і використання в інтерактивному режимі. У сучасній реалізації bashє режим редагування командного рядка, необмежений розмірісторії команд, засоби управління завданнями, можливість використання псевдонімів, великий перелік вбудованих команд, функції командної оболонки тощо. В цілому, bashнайбільшою мірою відповідає потребам середньостатистичного користувача, що й зробило її найбільш використовуваною серед Linux.

При запуску bashбез параметрів командного рядка оболонка запускається в інтерактивному режимі, відображаючи на екрані запрошення до введення команд. Інтерактивна оболонка зазвичай читає дані з терміналу користувача і пише дані в цей термінал, стандартним пристроємвведення є клавіатура, а стандартним пристроєм виведення – дисплей. Користувач вводить команди на клавіатурі, а результат виконання відображається на дисплеї.

  • Tutorial

Навіщо та для кого стаття?

Спочатку це була пам'ятка для студентів, які починають працювати з unix-подібними системами. Іншими словами, стаття розрахована на тих, хто не має попереднього досвіду роботи в UNIX-овому командному рядку, але з тих чи інших причин хоче або повинен навчитися ефективно з нею взаємодіяти.

Тут не буде переказу манів (документації), і стаття ніяк не скасовує та не замінює їхнього читання. Натомість я розповім про головні речі (команда, прийоми та принципи), які треба усвідомити з самого початку роботи в unix shell-і, щоб робота відбувалася ефективно і приємно.

Стаття стосується повноцінних unix-подібних оточень, з повнофункціональним шеллом (переважно zsh або bash) і досить широким набором стандартних програм.

Що таке шелл

Shell (шелл, він же "командний рядок", він же CLI, він же "консоль", він же "термінал", він же "чорне віконце з білими літерами") - це текстовий інтерфейс спілкування з операційною системою (ну, суворо кажучи, це програма, яка такий інтерфейс забезпечує, але сьогодні це відмінність несуттєво).

В цілому робота через шелл виглядає так: користувач (тобто ви) з клавіатури вводить команду, натискає Enter, система виконує команду, пише на екран результат виконання, і знову чекає на введення наступної команди.

Типовий вигляд шеллу:

Шелл – це основний спосіб для взаємодії з усіма Unix-подібними серверними системами.

Де зустрічаються системи із командним рядком?

Де вас може чекати unix-овий шелл, популярні варіанти:
  • MacOS (Bash);
  • віддалений доступ на сервер для роботи або для особистого веб-проекту;
  • домашній файл-сервер із віддаленим доступом;
  • Ubuntu, PC-BSD на ноутбуці/десктопі - unix-подібні системи сьогодні прості у встановленні та використанні.

Які завдання розумно розв'язувати шеллом?

Природні завдання, для яких придатний шелл, корисний і незамінний:
  • інтерактивна робота у терміналі:
    • виконання компіляції; запуск завдань через make;
    • порівняння текстових файлів;
    • швидкий ad-hoc аналіз даних (кількість унікальних ip у лозі, розподіл записів по годинах/хвилинах тощо);
    • разові масові дії (прибити багато процесів; якщо працюєте із системою контролю версій – ревертнути чи зарезолвити купу файлів);
    • діагностика того, що відбувається в системі (семафори, локи, процеси, дескриптори, місце на диску тощо);
  • скриптування:
    • настановні скрипти, виконання яких не можна розраховувати на наявність інших інтерпретаторів - це для новачків;
    • функції для кастомізації інтерактивного шелла (що впливають на запрошення, що змінюють каталог, що встановлюють змінні оточення) – теж не зовсім для новачків;
    • одноразові скрипти типу масового перекодування файлів;
    • makefile-и.

Абсолютно перші кроки

Починаємо роботу: увійти та вийти

Переконайтеся, що знаєте, як запустити шелл і як з нього вийти.

Якщо ви працюєте за машиною, на якій встановлено Ubuntu, вам потрібно запустити програму Terminal. Після закінчення роботи можна просто закрити вікно.

На MacOS – теж запустити Terminal.

Для доступу до віддаленому серверу- скористатися ssh (якщо локально у вас MacOS, Ubuntu чи інша unix-like система) чи putty (якщо у вас Windows).

Хто я де я?

Виконайте такі команди:
  • hostname - виводить ім'я машини (сервера), де ви зараз перебуваєте;
  • whoami - виводить ваш логін (ваше ім'я у системі);
  • tree -d / |less - псевдографічне зображення дерева каталогів на машині; вихід з перегортання - q;
  • pwd - виводить каталог, у якому ви зараз перебуваєте; у командному рядку ви не можете бути просто так, ви обов'язково знаходитесь в якомусь каталозі (=поточний каталог, робочий каталог). Ймовірно, поточний робочий каталог виводиться у запрошенні (prompt).
  • ls - список файлів у поточному каталозі; ls /home - список файлів у вказаному каталозі;

Історія команд (history)

Важлива властивість повноцінного командного рядка – історія команд.

Виконайте кілька команд: hostname, ls, pwd, whoami. Тепер натисніть клавішу "вгору". У рядку введення з'явилася попередня команда. Клавішами "вгору" і "вниз" можна переміщатися вперед і назад з історії. Коли догортаєте hostname , натисніть Enter - команда виконається ще раз.

Команди з історії можна не просто виконувати повторно, а ще й редагувати. Дістайте історію до команди ls , додайте до неї ключ -l (вийшло ls -l перед мінусом пробіл є, а після - ні). Натисніть Enter – виконається модифікована команда.

Перегортання історії, редагування та повторне виконання команд - найтиповіші дії при роботі в командному рядку, звикайте.

Copy-paste

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

Прекрасною особливістю тексту є те, що його можна копіювати та вставляти, це вірно і для командного рядка.

Спробуйте виконати команду date +"%y-%m-%d, %A"
Чи ви вводили її цілком руками або скопіювали зі статті? Переконайтеся, що ви можете скопіювати її, вставити в термінал і виконати.

Після того, як навчитеся користуватися man, переконайтеся, що можете скопіювати і виконати приклади команд з довідки. Для перевірки знайдіть у довідці за програмою date розділ EXAMPLES, скопіюйте і виконайте перший наведений приклад (про всяк випадок: знак долара не є частиною команди , це умовне зображення запрошення до введення).

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

Ключі та опції

При дослідженні історії команд ви вже зіткнулися з тим, що у команди ls є Крайній мірідва варіанти. Якщо викликати її просто так, вона виводить простий список:

Akira@latitude-e7240: ~/shell-survival-quide> ls Makefile shell-first-steps.md shell-first-steps.pdf shell-survival-quide.md shell-survival-quide.pdf
Якщо додати ключ -l , до кожного файлу виводиться докладна інформація:

Akira@latitude-e7240: ~/shell-survival-quide> ls -l total 332 -rw-rw-r-- 1 akira akira 198 Feb 13 11:48 Makefile -rw-rw-r-- 1 akira akira 15107 Feb 14 22:26 shell-first-steps.md -rw-rw-r-- 1 akira akira 146226 Feb 13 11:49 shell-first-steps.pdf -rw-rw-r-- 1 akira akira 16626 Feb 13 11 :45 shell-survival-quide.md -rw-rw-r-- 1 akira akira 146203 Feb 13 11:35 shell-survival-quide.pdf
Це дуже типова ситуація: якщо до команди додавати спеціальні модифікатори (ключі, опції, параметри), поведінка команди змінюється. Порівняйте: tree / і tree -d / , hostname і hostname -f.

Крім того, команди можуть приймати як параметри імена файлів, каталогів або просто текстові рядки. Спробуйте:

Ls -ld /home ls -l /home grep root /etc/passwd

man

man - довідка за командами та програмами, доступними на вашій машині, а також за системними викликами та стандартною бібліотекою C.

Спробуйте: man grep, man atoi, man chdir, man man.

Перегортання вперед і назад робиться кнопками "вгору", "вниз", "PageUp", "PageDown", вихід з перегляду довідки - кнопкою q. Пошук певного тексту у довідковій статті: натисніть / (прямий слєш), введіть текст для пошуку, натисніть Enter. Переміщення до наступних входів - клавіша n.

Усі довідкові статті поділяються на категорії. Найважливіші:

  • 1 - виконувані програми та шульні команди (wc, ls, pwd і т.п.);
  • 2 - системні виклики(fork, dup2 і т.п.)
  • 3 - бібліотечні функції (printf, scanf, cos, exec).
Вказувати, з якої категорії треба показати довідку, потрібно у випадках збігів імен. Наприклад, man 3 printf описує функцію зі стандартної бібліотеки C, а man 1 printf - консольну програму з таким самим ім'ям.

Переглянути всі доступні на машині довідкові статті можна за допомогою команди man -k . (Точка - теж частина комади).

less

Коли у невеликому вікні терміналу треба переглянути дуже довгий текст(вміст якогось файлу, довгий man тощо) використовують спеціальні програми-«пейджери» (від слова page/сторінка, тобто посторінкові листатели). Найпопулярніший листівник - less, і саме він забезпечує вам перегортання, коли ви читаєте man-и.

Спробуйте та порівняйте поведінку:

Cat /etc/bash.bashrc cat /etc/bash.bashrc |less

Можна передати файл до прогортання відразу в параметрах:

Less /etc/bash.bashrc

Перегортання вгору та вниз – кнопки «вгору», «вниз», «PageUp», «PageDown», вихід – кнопка q . Пошук певного тексту: натисніть / (прямий слєш), введіть текст для пошуку, натисніть Enter. Переміщення до наступних входів - клавіша n. (Дізнаєтеся інструкцію про man? Нічого дивного, для виведення довідки теж використовується less.)

Права

З будь-яким файлом чи каталогом пов'язаний набір «прав»: декларація про читання файлу, декларація про запис файл, право виконувати файл. Усі користувачі поділяються на три категорії: власник файлу, група власника файлу, решта користувачів.

Переглянути права на файл можна за допомогою ls-l. Наприклад:

> ls -l Makefile -rw-r--r-- 1 akira students 198 Feb 13 11:48 Makefile
Цей висновок означає, що власнику (akira) можна читати і писати файл, групі (students) – тільки читати, всім іншим користувачам – теж тільки читати.

Якщо при роботі ви отримуєте повідомлення permission denied , це означає, що у вас недостатньо правий об'єкт, з яким ви хотіли працювати.

Докладніше читайте в man chmod.

STDIN, STDOUT, конвеєри (пайпи)

З кожною програмою, що виконується, пов'язані 3 стандартних потокуданих: потік вхідних даних STDIN, потік вихідних даних STDOUT, потік для виведення помилок STDERR.

Запустіть програму wc, введіть текст Good day today, натисніть Enter, введіть текст good day, натисніть Enter, натисніть Ctrl+d. Програма wc покаже статистику за кількістю літер, слів та рядків у вашому тексті та завершиться:

> wc good day today good day 2 5 24
У цьому випадку ви подали в STDIN програми дворядковий текст, а в STDOUT отримали три числа.

Тепер запустіть команду head -n3 /etc/passwd , має бути приблизно так:

> head -n3 /etc/passwd root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x: 2:2:bin:/bin:/usr/sbin/nologin
У цьому випадку програма head нічого не читала зі STDIN, а в STDOUT написала три рядки.

Можна уявити так: програма - це труба, у якому втікає STDIN , а витікає STDOUT .

Найважливіша властивість юніксового командного рядка полягає в тому, що програми-«труби» можна з'єднувати між собою: вихід (STDOUT) однієї програми передавати як вхідні дані (STDIN) іншій програмі.

Така конструкція зі з'єднаних програм називається англійською pipe (труба), російською - конвеєр або пайп.

Об'єднання програм на конвеєр робиться символом | (вертикальна характеристика)

Виконайте команду head -n3 /etc/passwd |wc , вийде приблизно таке:

> head -n3 /etc/passwd |wc 3 3 117
Сталося ось що: програма head видала в STDOUT три рядки тексту, які одразу ж потрапили на вхід програмі wc , яка підрахувала кількість символів, слів і рядків в отриманому тексті.

У конвеєр можна поєднувати скільки завгодно програм. Наприклад, можна додати до попереднього конвеєра ще одну програму wc, яка підрахує, скільки слів і літер було у висновку першої wc:

> head -n3 /etc/passwd |wc |wc 1 3 24

Складання конвеєрів (пайпів) - дуже часта справа під час роботи у командному рядку. Приклад того, як це робиться на практиці, читайте в розділі «Упорядкування конвеєра-однострочника».

Перенаправлення введення-виведення

Висновок (STDOUT) програми можна не лише передати іншій програмі за конвеєром, але й просто записати у файл. Таке перенаправлення здійснюється за допомогою > (знак «більше»):

Date > /tmp/today.txt
В результаті виконання цієї команди на диску з'явиться файл /tmp/today.txt. Перегляньте його вміст за допомогою cat /tmp/today.txt

Якщо файл з такою назвою вже існував, його старий вміст буде знищено. Якщо файл не існував, його буде створено. Каталог, у якому створюється файл, має існувати до виконання команди.

Якщо потрібно не перезаписати файл, а додати висновок у його кінець, використовуйте >>:

Date >> /tmp/today.txt
Перевірте, чи записано у файлі.

Крім того, програмі можна замість STDIN передати будь-який файл. Спробуйте:

Wc

Що робити, коли щось незрозуміло

Якщо ви стикаєтеся з поведінкою системи, яку не розумієте, або хочете досягти певного результату, але не знаєте, як саме, раджу діяти в наступному порядку (до речі, це стосується не тільки шеллів):
  • наскільки можливо чітко сформулюйте питання чи завдання – немає нічого складнішого, ніж вирішувати «те, не знаю що»;
  • пригадайте, чи ви вже стикалися з такою ж або подібною проблемою - у цьому випадку варто спробувати рішення, яке спрацювало минулого разу;
  • почитайте відповідні man-и (якщо розумієте, які man-и підходять у вашому випадку) - можливо, ви знайдете відповідні приклади використання команд, потрібні опції або посилання на інші команди;
  • подумайте: чи не можна трохи змінити завдання? - можливо, трохи змінивши умови, ви отримаєте завдання, яке вже вмієте вирішувати;
  • задайте своє чітко сформульоване питання у пошуковій системі - можливо, відповідь знайдеться на Stack Overflow або на інших сайтах;
Якщо нічого з перерахованого не допомогло - зверніться за порадою до викладача, досвідченого колеги чи товариша. І не бійтеся ставити «дурні» питання – не соромно не знати, соромно не питати.

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

Методи роботи

Копіювати-і-вставити- з man-ів, зі статей на StackOverflow і т.п. Командний рядок складається з тексту, користуйтеся цим: копіюйте та використовуйте приклади команд, записуйте вдалі знахідки на згадку, публікуйте їх у твіттерах та блогах.

Витягти з історії попередню команду, додати до конвеєра ще одну команду, запустити, повторити.Див. також розділ «Упорядкування конвеєра-однострочника».

Базові команди

  • перехід до іншого каталогу: cd;
  • перегляд вмісту файлів: саt, less, head, tail;
  • маніпуляції з файлами: cp, mv, rm;
  • перегляд вмісту каталогів: ls, ls -l, ls -lS;
  • структура каталогів: tree , tree -d (можна передати як параметр каталог);
  • пошук файлів: find. -name ...;

Аналітика

  • wc, wc-l;
  • sort -k - сортування за вказаним полем;
  • sort -n - числове соритровка;
  • diff – порівняння файлів;
  • grep, grep-v, grep-w, grep "\ ", grep -E - пошук тексту;
  • uniq , uniq -c - Унікалізація рядків;
  • awk - у варіанті awk "(print $1)", щоб залишити тільки перше поле з кожного рядка, $1 можна міняти на $2, $3 і т.д.;

Діагностика системи

  • ps axuww - інформація про процеси (запущені програми), що працюють на машині;
  • top - інтерактивний перегляд найбільш ресурсомістких процесів;
  • df - зайняте та вільне місце на диску;
  • du – сумарний розмір файлів у каталозі (рекурсивно з підкаталогами);
  • strace , ktrace – які системні виклики виконує процес;
  • lsof – які файли використовує процес;
  • netstat -na , netstat -nap - які порти та сокети відкриті в системі.

Деяких програм у вас може бути, їх треба встановити додатково. Крім того, деякі опції цих програм доступні лише привілейованим користувачам (root "у").

Масове та напівавтоматичне виконання

Спочатку пропускайте цей розділ, ці команди і конструкції знадобляться вам тоді, коли дістанетеся до нескладного шовкового скриптингу.
  • test - перевірка умов;
  • while read - цикл за рядками STDIN;
  • xargs - підстановка рядків із STDIN у параметри зазначеної програми;
  • seq – генерація послідовностей натуральних чисел;
  • () - об'єднати виведення кількох команд;
  • ; - Виконати одне за одним;
  • && - виконати за умови успішного завершення першої команди;
  • || - Виконати за умови невдалого завершення першої команди;
  • tee - продублювати виведення програми в STDOUT і файл на диску.

Різне

  • date – поточна дата;
  • curl - завантажує документ за вказаним url і пише результат на STDOUT;
  • touch – оновити дату модифікації файлу;
  • kill - надіслати процесу сигнал;
  • true - нічого не робить, повертає істину, корисна для організації вічних циклів;
  • sudo - виконати команду від імені root а.

Складання конвеєра-однорядника

Давайте розглянемо приклад реального завдання: потрібно прибити всі процеси task-6-server, запущені від імені користувача.

Крок 1.
Зрозуміти, яка програма видає приблизно потрібні дані, хоча б не в чистому вигляді. Для нашого завдання варто отримати список усіх процесів у системі: ps axuww. Запустити.

Крок 2
Подивитися на отримані дані очима, вигадати фільтр, який викине частину непотрібних даних. Часто це grep або grep-v. Кнопками «Вгору» витягти з історії попередню команду, приписати до неї вигаданий фільтр, запустити.

Ps axuww | grep `whoami`
- Тільки процеси поточного користувача.

Крок 3
Повторювати пункт 2, доки не вийдуть чисті дані.

"
- всі процеси з потрібним ім'ям (плюс, можливо, зайві на зразок vim task-6-server.c і т.п.),

Ps axuww | grep `whoami` | grep "\ | | grep -v vim ps axuww | grep `whoami` | grep "\ " | grep -v vim | grep -v less
- Тільки процеси з потрібним ім'ям

Ps axuww | grep `whoami` | grep "\ grep -v vim |grep -v less |awk "(print $2)"

Pid-и потрібних процесів, п. 3 виконаний

Крок 4.
Застосувати відповідний фінальний обробник. Клавішами «Вгору» витягуємо з історії попередню команду та додаємо обробку, яка завершить вирішення завдання:

  • |wc -l щоб порахувати кількість процесів;
  • >pids щоб записати pid-и файл;
  • | xargs kill -9 вбити процеси.

Завдання для тренування

Хочете попрактикуватися в нових вміннях? Спробуйте виконати такі завдання:
  • отримайте список усіх файлів та каталогів у вашому домашньому каталозі;
  • отримайте список всіх man-статей із категорії 2 (системні виклики);
  • порахуйте, скільки разів у man-і за програмою grep зустрічається слово grep;
  • порахуйте, скільки процесів запущено в даний момент від імені користувача root;
  • знайдіть, яка команда зустрічається у максимальній кількості категорій довідки (man);
  • підрахуйте скільки разів зустрічається слово var на сторінці ya.ru .
Підказка: вам знадобиться find, grep-o, awk "(print $1)", регулярні вирази в grep, curl-s.

Що вивчати далі?

Якщо командний рядок починає вам подобається, не зупиняйтеся, продовжуйте вдосконалювати свої навички.

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

  • find зі складними опціями
  • apropos
  • locate
  • telnet
  • netcat
  • tcpdump
  • rsync
  • screen
  • zgrep, zless
  • visudo
  • crontab -e
  • sendmail
Крім того, з часом варто освоїти якусь скриптову мову, наприклад, perl або python, або навіть їх обидва.

Кому це треба?

А чи варто взагалі вивчати сьогодні командний рядок та шовальний скриптинг? Виразно стоїть. Наведу лише кілька прикладів із вимог Facebook до кандидатів, які хочуть вступити на роботу до FB.
  • Tutorial

Навіщо та для кого стаття?

Спочатку це була пам'ятка для студентів, які починають працювати з unix-подібними системами. Іншими словами, стаття розрахована на тих, хто не має попереднього досвіду роботи в UNIX-овому командному рядку, але з тих чи інших причин хоче або повинен навчитися ефективно з нею взаємодіяти.

Тут не буде переказу манів (документації), і стаття ніяк не скасовує та не замінює їхнього читання. Натомість я розповім про головні речі (команда, прийоми та принципи), які треба усвідомити з самого початку роботи в unix shell-і, щоб робота відбувалася ефективно і приємно.

Стаття стосується повноцінних unix-подібних оточень, з повнофункціональним шеллом (переважно zsh або bash) і досить широким набором стандартних програм.

Що таке шелл

Shell (шелл, він же "командний рядок", він же CLI, він же "консоль", він же "термінал", він же "чорне віконце з білими літерами") - це текстовий інтерфейс спілкування з операційною системою (ну, суворо кажучи, це програма, яка такий інтерфейс забезпечує, але сьогодні це відмінність несуттєво).

В цілому робота через шелл виглядає так: користувач (тобто ви) з клавіатури вводить команду, натискає Enter, система виконує команду, пише на екран результат виконання, і знову чекає на введення наступної команди.

Типовий вигляд шеллу:

Шелл – це основний спосіб для взаємодії з усіма Unix-подібними серверними системами.

Де зустрічаються системи із командним рядком?

Де вас може чекати unix-овий шелл, популярні варіанти:
  • MacOS (Bash);
  • віддалений доступ на сервер для роботи або для особистого веб-проекту;
  • домашній файл-сервер із віддаленим доступом;
  • Ubuntu, PC-BSD на ноутбуці/десктопі - unix-подібні системи сьогодні прості у встановленні та використанні.

Які завдання розумно розв'язувати шеллом?

Природні завдання, для яких придатний шелл, корисний і незамінний:
  • інтерактивна робота у терміналі:
    • виконання компіляції; запуск завдань через make;
    • порівняння текстових файлів;
    • швидкий ad-hoc аналіз даних (кількість унікальних ip у лозі, розподіл записів по годинах/хвилинах тощо);
    • разові масові дії (прибити багато процесів; якщо працюєте із системою контролю версій – ревертнути чи зарезолвити купу файлів);
    • діагностика того, що відбувається в системі (семафори, локи, процеси, дескриптори, місце на диску тощо);
  • скриптування:
    • настановні скрипти, виконання яких не можна розраховувати на наявність інших інтерпретаторів - це для новачків;
    • функції для кастомізації інтерактивного шелла (що впливають на запрошення, що змінюють каталог, що встановлюють змінні оточення) – теж не зовсім для новачків;
    • одноразові скрипти типу масового перекодування файлів;
    • makefile-и.

Абсолютно перші кроки

Починаємо роботу: увійти та вийти

Переконайтеся, що знаєте, як запустити шелл і як з нього вийти.

Якщо ви працюєте за машиною, на якій встановлено Ubuntu, вам потрібно запустити програму Terminal. Після закінчення роботи можна просто закрити вікно.

На MacOS – теж запустити Terminal.

Для доступу до віддаленого сервера – скористатися ssh (якщо локально у вас MacOS, Ubuntu або інша unix-like система) або putty (якщо у вас Windows).

Хто я де я?

Виконайте такі команди:
  • hostname - виводить ім'я машини (сервера), де ви зараз перебуваєте;
  • whoami - виводить ваш логін (ваше ім'я у системі);
  • tree -d / |less - псевдографічне зображення дерева каталогів на машині; вихід з перегортання - q;
  • pwd - виводить каталог, у якому ви зараз перебуваєте; у командному рядку ви не можете бути просто так, ви обов'язково знаходитесь в якомусь каталозі (=поточний каталог, робочий каталог). Ймовірно, поточний робочий каталог виводиться у запрошенні (prompt).
  • ls – список файлів у поточному каталозі; ls /home - список файлів у вказаному каталозі;

Історія команд (history)

Важлива властивість повноцінного командного рядка – історія команд.

Виконайте кілька команд: hostname, ls, pwd, whoami. Тепер натисніть клавішу "вгору". У рядку введення з'явилася попередня команда. Клавішами "вгору" і "вниз" можна переміщатися вперед і назад з історії. Коли догортаєте hostname , натисніть Enter - команда виконається ще раз.

Команди з історії можна не просто виконувати повторно, а ще й редагувати. Дістайте історію до команди ls , додайте до неї ключ -l (вийшло ls -l перед мінусом пробіл є, а після - ні). Натисніть Enter – виконається модифікована команда.

Перегортання історії, редагування та повторне виконання команд - найтиповіші дії при роботі в командному рядку, звикайте.

Copy-paste

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

Прекрасною особливістю тексту є те, що його можна копіювати та вставляти, це вірно і для командного рядка.

Спробуйте виконати команду date +"%y-%m-%d, %A"
Чи ви вводили її цілком руками або скопіювали зі статті? Переконайтеся, що ви можете скопіювати її, вставити в термінал і виконати.

Після того, як навчитеся користуватися man, переконайтеся, що можете скопіювати і виконати приклади команд з довідки. Для перевірки знайдіть у довідці за програмою date розділ EXAMPLES, скопіюйте і виконайте перший наведений приклад (про всяк випадок: знак долара не є частиною команди , це умовне зображення запрошення до введення).

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

Ключі та опції

При дослідженні історії команд ви вже зіткнулися з тим, що команда ls має принаймні два варіанти. Якщо викликати її просто так, вона виводить простий список:

Akira@latitude-e7240: ~/shell-survival-quide> ls Makefile shell-first-steps.md shell-first-steps.pdf shell-survival-quide.md shell-survival-quide.pdf
Якщо додати ключ -l , до кожного файлу виводиться докладна інформація:

Akira@latitude-e7240: ~/shell-survival-quide> ls -l total 332 -rw-rw-r-- 1 akira akira 198 Feb 13 11:48 Makefile -rw-rw-r-- 1 akira akira 15107 Feb 14 22:26 shell-first-steps.md -rw-rw-r-- 1 akira akira 146226 Feb 13 11:49 shell-first-steps.pdf -rw-rw-r-- 1 akira akira 16626 Feb 13 11 :45 shell-survival-quide.md -rw-rw-r-- 1 akira akira 146203 Feb 13 11:35 shell-survival-quide.pdf
Це дуже типова ситуація: якщо до виклику команди додавати спеціальні модифікатори (ключ, опції, параметри), поведінка команди змінюється. Порівняйте: tree / і tree -d / , hostname і hostname -f.

Крім того, команди можуть приймати як параметри імена файлів, каталогів або просто текстові рядки. Спробуйте:

Ls -ld /home ls -l /home grep root /etc/passwd

man

man - довідка за командами та програмами, доступними на вашій машині, а також за системними викликами та стандартною бібліотекою C.

Спробуйте: man grep, man atoi, man chdir, man man.

Перегортання вперед і назад робиться кнопками "вгору", "вниз", "PageUp", "PageDown", вихід з перегляду довідки - кнопкою q. Пошук певного тексту у довідковій статті: натисніть / (прямий слєш), введіть текст для пошуку, натисніть Enter. Переміщення до наступних входів - клавіша n.

Усі довідкові статті поділяються на категорії. Найважливіші:

  • 1 - виконувані програми та шульні команди (wc, ls, pwd і т.п.);
  • 2 - системні виклики (fork, dup2 і т.п.)
  • 3 - бібліотечні функції (printf, scanf, cos, exec).
Вказувати, з якої категорії треба показати довідку, потрібно у випадках збігів імен. Наприклад, man 3 printf описує функцію зі стандартної бібліотеки C, а man 1 printf - консольну програму з таким самим ім'ям.

Переглянути всі доступні на машині довідкові статті можна за допомогою команди man -k . (Точка - теж частина комади).

less

Коли у невеликому вікні терміналу треба переглянути дуже довгий текст (вміст якогось файлу, довгий man тощо) використовують спеціальні програми-«пейджери» (від слова page/сторінка, тобто посторінкові листатели). Найпопулярніший листівник - less, і саме він забезпечує вам перегортання, коли ви читаєте man-и.

Спробуйте та порівняйте поведінку:

Cat /etc/bash.bashrc cat /etc/bash.bashrc |less

Можна передати файл до прогортання відразу в параметрах:

Less /etc/bash.bashrc

Перегортання вгору та вниз – кнопки «вгору», «вниз», «PageUp», «PageDown», вихід – кнопка q . Пошук певного тексту: натисніть / (прямий слєш), введіть текст для пошуку, натисніть Enter. Переміщення до наступних входів - клавіша n. (Дізнаєтеся інструкцію про man? Нічого дивного, для виведення довідки теж використовується less.)

Права

З будь-яким файлом чи каталогом пов'язаний набір «прав»: декларація про читання файлу, декларація про запис файл, право виконувати файл. Усі користувачі поділяються на три категорії: власник файлу, група власника файлу, решта користувачів.

Переглянути права на файл можна за допомогою ls-l. Наприклад:

> ls -l Makefile -rw-r--r-- 1 akira students 198 Feb 13 11:48 Makefile
Цей висновок означає, що власнику (akira) можна читати і писати файл, групі (students) – тільки читати, всім іншим користувачам – теж тільки читати.

Якщо при роботі ви отримуєте повідомлення permission denied , це означає, що у вас недостатньо правий об'єкт, з яким ви хотіли працювати.

Докладніше читайте в man chmod.

STDIN, STDOUT, конвеєри (пайпи)

З кожною програмою, що виконується, пов'язані 3 стандартних потоку даних: потік вхідних даних STDIN , потік вихідних даних STDOUT , потік для виведення помилок STDERR .

Запустіть програму wc, введіть текст Good day today, натисніть Enter, введіть текст good day, натисніть Enter, натисніть Ctrl+d. Програма wc покаже статистику за кількістю літер, слів та рядків у вашому тексті та завершиться:

> wc good day today good day 2 5 24
У цьому випадку ви подали в STDIN програми дворядковий текст, а в STDOUT отримали три числа.

Тепер запустіть команду head -n3 /etc/passwd , має бути приблизно так:

> head -n3 /etc/passwd root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x: 2:2:bin:/bin:/usr/sbin/nologin
У цьому випадку програма head нічого не читала зі STDIN, а в STDOUT написала три рядки.

Можна уявити так: програма - це труба, у якому втікає STDIN , а витікає STDOUT .

Найважливіша властивість юніксового командного рядка полягає в тому, що програми-«труби» можна з'єднувати між собою: вихід (STDOUT) однієї програми передавати як вхідні дані (STDIN) іншій програмі.

Така конструкція зі з'єднаних програм називається англійською pipe (труба), російською - конвеєр або пайп.

Об'єднання програм на конвеєр робиться символом | (вертикальна характеристика)

Виконайте команду head -n3 /etc/passwd |wc , вийде приблизно таке:

> head -n3 /etc/passwd |wc 3 3 117
Сталося ось що: програма head видала в STDOUT три рядки тексту, які одразу ж потрапили на вхід програмі wc , яка підрахувала кількість символів, слів і рядків в отриманому тексті.

У конвеєр можна поєднувати скільки завгодно програм. Наприклад, можна додати до попереднього конвеєра ще одну програму wc, яка підрахує, скільки слів і літер було у висновку першої wc:

> head -n3 /etc/passwd |wc |wc 1 3 24

Складання конвеєрів (пайпів) - дуже часта справа під час роботи у командному рядку. Приклад того, як це робиться на практиці, читайте в розділі «Упорядкування конвеєра-однострочника».

Перенаправлення введення-виведення

Висновок (STDOUT) програми можна не лише передати іншій програмі за конвеєром, але й просто записати у файл. Таке перенаправлення здійснюється за допомогою > (знак «більше»):

Date > /tmp/today.txt
В результаті виконання цієї команди на диску з'явиться файл /tmp/today.txt. Перегляньте його вміст за допомогою cat /tmp/today.txt

Якщо файл з такою назвою вже існував, його старий вміст буде знищено. Якщо файл не існував, його буде створено. Каталог, у якому створюється файл, має існувати до виконання команди.

Якщо потрібно не перезаписати файл, а додати висновок у його кінець, використовуйте >>:

Date >> /tmp/today.txt
Перевірте, чи записано у файлі.

Крім того, програмі можна замість STDIN передати будь-який файл. Спробуйте:

Wc

Що робити, коли щось незрозуміло

Якщо ви стикаєтеся з поведінкою системи, яку не розумієте, або хочете досягти певного результату, але не знаєте, як саме, раджу діяти в наступному порядку (до речі, це стосується не тільки шеллів):
  • наскільки можливо чітко сформулюйте питання чи завдання – немає нічого складнішого, ніж вирішувати «те, не знаю що»;
  • пригадайте, чи ви вже стикалися з такою ж або подібною проблемою - у цьому випадку варто спробувати рішення, яке спрацювало минулого разу;
  • почитайте відповідні man-и (якщо розумієте, які man-и підходять у вашому випадку) - можливо, ви знайдете відповідні приклади використання команд, потрібні опції або посилання на інші команди;
  • подумайте: чи не можна трохи змінити завдання? - можливо, трохи змінивши умови, ви отримаєте завдання, яке вже вмієте вирішувати;
  • задайте своє чітко сформульоване питання у пошуковій системі - можливо, відповідь знайдеться на Stack Overflow або на інших сайтах;
Якщо нічого з перерахованого не допомогло - зверніться за порадою до викладача, досвідченого колеги чи товариша. І не бійтеся ставити «дурні» питання – не соромно не знати, соромно не питати.

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

Методи роботи

Копіювати-і-вставити- з man-ів, зі статей на StackOverflow і т.п. Командний рядок складається з тексту, користуйтеся цим: копіюйте та використовуйте приклади команд, записуйте вдалі знахідки на згадку, публікуйте їх у твіттерах та блогах.

Витягти з історії попередню команду, додати до конвеєра ще одну команду, запустити, повторити.Див. також розділ «Упорядкування конвеєра-однострочника».

Базові команди

  • перехід до іншого каталогу: cd;
  • перегляд вмісту файлів: саt, less, head, tail;
  • маніпуляції з файлами: cp, mv, rm;
  • перегляд вмісту каталогів: ls, ls -l, ls -lS;
  • структура каталогів: tree , tree -d (можна передати як параметр каталог);
  • пошук файлів: find. -name ...;

Аналітика

  • wc, wc-l;
  • sort -k - сортування за вказаним полем;
  • sort -n - числове соритровка;
  • diff – порівняння файлів;
  • grep, grep-v, grep-w, grep "\ ", grep -E - пошук тексту;
  • uniq , uniq -c - Унікалізація рядків;
  • awk - у варіанті awk "(print $1)", щоб залишити тільки перше поле з кожного рядка, $1 можна міняти на $2, $3 і т.д.;

Діагностика системи

  • ps axuww - інформація про процеси (запущені програми), що працюють на машині;
  • top - інтерактивний перегляд найбільш ресурсомістких процесів;
  • df - зайняте та вільне місце на диску;
  • du – сумарний розмір файлів у каталозі (рекурсивно з підкаталогами);
  • strace , ktrace – які системні виклики виконує процес;
  • lsof – які файли використовує процес;
  • netstat -na , netstat -nap - які порти та сокети відкриті в системі.

Деяких програм у вас може бути, їх треба встановити додатково. Крім того, деякі опції цих програм доступні лише привілейованим користувачам (root "у").

Масове та напівавтоматичне виконання

Спочатку пропускайте цей розділ, ці команди і конструкції знадобляться вам тоді, коли дістанетеся до нескладного шовкового скриптингу.
  • test - перевірка умов;
  • while read - цикл за рядками STDIN;
  • xargs - підстановка рядків із STDIN у параметри зазначеної програми;
  • seq – генерація послідовностей натуральних чисел;
  • () - об'єднати виведення кількох команд;
  • ; - Виконати одне за одним;
  • && - виконати за умови успішного завершення першої команди;
  • || - Виконати за умови невдалого завершення першої команди;
  • tee - продублювати виведення програми в STDOUT і файл на диску.

Різне

  • date – поточна дата;
  • curl - завантажує документ за вказаним url і пише результат на STDOUT;
  • touch – оновити дату модифікації файлу;
  • kill - надіслати процесу сигнал;
  • true - нічого не робить, повертає істину, корисна для організації вічних циклів;
  • sudo - виконати команду від імені root а.

Складання конвеєра-однорядника

Давайте розглянемо приклад реального завдання: потрібно прибити всі процеси task-6-server, запущені від імені користувача.

Крок 1.
Зрозуміти, яка програма видає приблизно потрібні дані, хоча б не в чистому вигляді. Для нашого завдання варто отримати список усіх процесів у системі: ps axuww. Запустити.

Крок 2
Подивитися на отримані дані очима, вигадати фільтр, який викине частину непотрібних даних. Часто це grep або grep-v. Кнопками «Вгору» витягти з історії попередню команду, приписати до неї вигаданий фільтр, запустити.

Ps axuww | grep `whoami`
- Тільки процеси поточного користувача.

Крок 3
Повторювати пункт 2, доки не вийдуть чисті дані.

"
- всі процеси з потрібним ім'ям (плюс, можливо, зайві на зразок vim task-6-server.c і т.п.),

Ps axuww | grep `whoami` | grep "\ | | grep -v vim ps axuww | grep `whoami` | grep "\ " | grep -v vim | grep -v less
- Тільки процеси з потрібним ім'ям

Ps axuww | grep `whoami` | grep "\ grep -v vim |grep -v less |awk "(print $2)"

Pid-и потрібних процесів, п. 3 виконаний

Крок 4.
Застосувати відповідний фінальний обробник. Клавішами «Вгору» витягуємо з історії попередню команду та додаємо обробку, яка завершить вирішення завдання:

  • |wc -l щоб порахувати кількість процесів;
  • >pids щоб записати pid-и файл;
  • | xargs kill -9 вбити процеси.

Завдання для тренування

Хочете попрактикуватися в нових вміннях? Спробуйте виконати такі завдання:
  • отримайте список усіх файлів та каталогів у вашому домашньому каталозі;
  • отримайте список всіх man-статей із категорії 2 (системні виклики);
  • порахуйте, скільки разів у man-і за програмою grep зустрічається слово grep;
  • порахуйте, скільки процесів запущено в даний момент від імені користувача root;
  • знайдіть, яка команда зустрічається у максимальній кількості категорій довідки (man);
  • підрахуйте скільки разів зустрічається слово var на сторінці ya.ru .
Підказка: вам знадобиться find, grep-o, awk "(print $1)", регулярні вирази в grep, curl-s.

Що вивчати далі?

Якщо командний рядок починає вам подобається, не зупиняйтеся, продовжуйте вдосконалювати свої навички.

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

  • find зі складними опціями
  • apropos
  • locate
  • telnet
  • netcat
  • tcpdump
  • rsync
  • screen
  • zgrep, zless
  • visudo
  • crontab -e
  • sendmail
Крім того, з часом варто освоїти якусь скриптову мову, наприклад, perl або python, або навіть їх обидва.

Кому це треба?

А чи варто взагалі вивчати сьогодні командний рядок та шовальний скриптинг? Виразно стоїть. Наведу лише кілька прикладів із вимог Facebook до кандидатів, які хочуть вступити на роботу до FB.