3.3 Урок 1
Сертифікат: |
Linux Essentials |
---|---|
Версія: |
1.6 |
Розділ: |
3 Потужність командного рядку |
Тема: |
3.3 Перетворення команд у скрипт |
Урок: |
1 з 2 |
Вступ
Поки що ми вчилися виконувати команди з оболонки, але ми також можемо вводити команди у файл, а потім налаштовувати цей файл як виконуваний. Коли файл виконується, ці команди виконуються одна за одною. Ці виконувані файли називаються скриптами, і вони є надзвичайно важливим інструментом для будь-якого системного адміністратора Linux. По суті, ми можемо вважати Bash як оболонкою, так і мовою програмування.
Виведення друку
Почнемо з демонстрації команди, яку ви, можливо, бачили в попередніх уроках: echo
виведе аргумент на стандартний вихід.
$ echo "Hello World!" Hello World!
Тепер ми будемо використовувати перенаправлення до файлу, щоб надіслати цю команду до нового файлу під назвою new_script
.
$ echo 'echo "Hello World!"' > new_script $ cat new_script echo "Hello World!"
Файл new_script
тепер містить ту саму команду, що й раніше.
Як зробити скрипт виконуваним
Продемонструємо деякі кроки, необхідні для того, щоб цей файл виконувався так, як ми очікуємо. Першою спробою користувача може бути просто введення імені сценарію, як він міг би ввести ім’я будь-якої іншої команди:
$ new_script /bin/bash: new_script: command not found
Ми можемо з упевненістю припустити, що new_script
існує у нашому поточному місці, але зауважте, що повідомлення про помилку не повідомляє нам, що файл не існує, воно повідомляє нам, що команда не існує. Було б корисно обговорити, як Linux обробляє команди та виконувані файли.
Команди та PATH
Наприклад, коли ми вводимо команду ls
в оболонку, ми виконуємо файл під назвою ls
, який існує в нашій файловій системі. Ви можете перевірити це, використовуючи which
:
$ which ls /bin/ls
Ви б швидко втомилися, якби кожного разу вводили абсолютний шлях до ls
щоразу, коли ми хочемо переглянути вміст каталогу, тому Bash має змінну environment, що містить усі каталоги, де ми можемо знайти команди, які ми хочемо запустити. Ви можете переглянути вміст цієї змінної за допомогою команди echo
.
$ echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
Кожне з цих місць є місцем, де оболонка очікує знайти команду, в змінній вони розділені двокрапками (:
). Ви помітите, що /bin
присутній, але можна з упевненістю припустити, що це не наше поточне місцезнаходження. Оболонка шукатиме new_script
у кожному з цих каталогів, але не знайде його і, отже, видасть помилку, яку ми бачили вище.
Є три рішення цієї проблеми: ми можемо перемістити new_script
в один із каталогів PATH
, ми можемо додати наш поточний каталог до PATH
, або ми можемо змінити спосіб виклику сценарію. Останнє рішення є найпростішим, воно просто вимагає від нас вказати поточне розташування під час виклику сценарію за допомогою крапки та косої риски (./
).
$ ./new_script /bin/bash: ./new_script: Permission denied
Повідомлення про помилку змінилося, що вказує на те, що ми досягли певного прогресу.
Дозволи на виконання
Перше дослідження, яке користувач повинен зробити в цьому випадку, це використати ls -l
, щоб переглянути інформацію про файл:
$ ls -l new_script -rw-rw-r-- 1 user user 20 Apr 30 12:12 new_script
Ми бачимо, що дозволи для цього файлу встановлені на 664
за замовчуванням. Ми ще не встановили для цього файлу права на виконання.
$ chmod +x new_script $ ls -l new_script -rwxrwxr-x 1 user user 20 Apr 30 12:12 new_script
Ця команда надала дозволи на виконання всім користувачам. Майте на увазі, що це може становити загрозу безпеці, але зараз це прийнятний рівень дозволу.
$ ./new_script Hello World!
Тепер ми можемо виконати наш скрипт.
Визначення інтерпретатора
Як ми продемонстрували, ми змогли просто ввести текст у файл, встановити його як виконуваний файл і запустити. new_script
функціонально все ще є звичайним текстовим файлом, але нам вдалося отримати його інтерпретацію за допомогою Bash. Але що, якщо він написаний на Perl або Python?
Дуже добре вказувати тип інтерпретатора, який ми хочемо використовувати, у першому рядку сценарію. Цей рядок називається bang line або частіше shebang. Він вказує системі, як ми хочемо, щоб цей файл був виконаний. Оскільки ми вивчаємо Bash, ми будемо використовувати абсолютний шлях до нашого виконуваного файлу Bash, знову використовуючи which
:
$ which bash /bin/bash
Наш shebang починається зі знака хешу та знака оклику, за яким слідує абсолютний шлях. Давайте відкриємо new_script
у текстовому редакторі та вставимо shebang. Також скористаємося можливістю, щоб вставити коментар до нашого сценарію. Коментарі ігноруються інтерпретатором. Вони написані для інших користувачів, які бажають зрозуміти ваш сценарій.
#!/bin/bash # This is our first comment. It is also good practice to document all scripts.. echo "Hello World!"
Ми також внесемо одну додаткову зміну до назви файлу: ми збережемо цей файл як new_script.sh
. Суфікс файлу ".sh" жодним чином не змінює виконання файлу. Існує домовленість, що сценарії bash позначаються .sh
або .bash
, щоб їх було легше ідентифікувати, так само, як сценарії Python зазвичай ідентифікуються за допомогою суфікса .py
.
Звичайні текстові редактори
Користувачам Linux часто доводиться працювати в середовищі, де графічні текстові редактори недоступні. Тому дуже рекомендується розвинути базові навички редагування текстових файлів з командного рядка. Два найпоширеніших текстових редактора – це vi
та nano
.
vi
vi
– це популярний текстовий редактор, який за замовчуванням встановлений майже в кожній існуючій системі Linux. vi
породив клон під назвою vi IMproved або vim
, який додає деякі функції, але підтримує інтерфейс vi
. Хоча робота з vi
складна для нового користувача, редактор популярний і його дуже полюбляють користувачі, які вивчають багато його функцій.
Найважливіша відмінність між vi
та такими програмами, як Блокнот, полягає в тому, що vi
має три різні режими. Під час запуску клавіші H, J, K і L використовуються для навігації, а не для введення. У цьому режимі навігації ви можете натиснути I, щоб увійти в режим вставки. Після цього ви можете вводити текст в звичайному режимі. Щоб вийти з режиму вставки, натисніть Esc, щоб повернутися до режиму навігації. У режимі навігації ви можете натиснути :, щоб увійти в командний режим. У цьому режимі ви можете використовувати опції збереження, видалення, виходу або зміни.
Хоча vi
потребує часу на його вивчення, різні режими можуть з часом дозволити досвідченому користувачеві стати більш ефективним, ніж з іншими редакторами.
nano
nano
— це новіший інструмент, створений так, щоб бути простим і легшим у використанні, ніж vi
. nano
не має різних режимів. Натомість користувач під час запуску може почати вводити текст і використовує Ctrl для доступу до інструментів, перелічених у нижній частині екрана.
[ Welcome to nano. For basic help, type Ctrl+G. ] ^G Get Help ^O Write Out ^W Where Is ^K Cut Text ^J Justify ^C Cur Pos M-U Undo ^X Exit ^R Read File ^\ Replace ^U Uncut Text ^T To Spell ^_ Go To Line M-E Redo
Текстові редактори – це питання особистих уподобань, і редактор, який ви виберете, не матиме жодного відношення до цього уроку. Але знайомство з одним або кількома текстовими редакторами окупиться в майбутньому.
Змінні
Змінні є важливою частиною будь-якої мови програмування, і Bash нічим не відрізняється. Коли ви починаєте новий сеанс з терміналу, оболонка вже встановлює деякі змінні для вас. Прикладом цього є змінна PATH
. Ми називаємо ці змінні змінними середовища, оскільки вони зазвичай визначають характеристики середовища оболонки. Ви можете змінювати та додавати змінні середовища, але зараз давайте зосередимося на встановленні змінних у нашому скрипті.
Ми змінимо наш сценарій, щоб він виглядав так:
#!/bin/bash # Це наш перший коментар. Також корисно коментувати всі сценарії. username=Carol echo "Hello $username!"
У цьому випадку ми створили змінну під назвою username
і призначили їй значення Carol
. Зауважте, що між ім’ям змінної, знаком рівності та присвоєним значенням немає пробілів.
У наступному рядку ми використали команду echo
зі змінною, але перед назвою змінної є знак долара ($
). Це важливо, оскільки це вказує оболонці, що ми хочемо розглядати username
як змінну, а не просто звичайне слово. Використовуючи $username
в нашій команді, ми вказуємо, що ми хочемо виконати підстановку, замінюючи ім’я змінної на значення, призначене цій змінній.
Виконуючи новий скрипт, ми отримуємо такий результат:
$ ./new_script.sh Hello Carol!
-
Назви змінних мають містити лише буквено-цифрові символи або підкреслення та є чутливими до регістру.
Username
таusername
розглядатимуться як різні змінні. -
Підстановка змінної також може мати формат
${username}
, з додаванням{ }
. Це також прийнятно. -
Змінні в Bash мають неявний тип і вважаються стрічками. Це означає, що виконання математичних функцій у Bash складніше, ніж це було б в інших мовах програмування, таких як C/C++.:
#!/bin/bash # Це наш перший коментар. Також корисно коментувати всі сценарії. username=Carol x=2 y=4 z=$x+$y echo "Hello $username!" echo "$x + $y" echo "$z"
$ ./new_script.sh Hello Carol! 2 + 4 2+4
Використання лапок зі змінними
Давайте внесемо наступні зміни до значення нашої змінної username
:
#!/bin/bash # Це наш перший коментар. Також корисно коментувати всі сценарії. username=Carol Smith echo "Hello $username!"
Запуск цього скрипту дасть нам помилку:
$ ./new_script.sh ./new_script.sh: line 5: Smith: command not found Hello !
Майте на увазі, що Bash є інтерпретатором, і як такий він інтерпретує наш сценарій рядок за рядком. У цьому випадку він правильно інтерпретує username=Carol
як встановлення змінної username
зі значенням Carol
. Але потім він інтерпретує пробіл як кінець цього призначення, а Smith
як назву команди. Щоб пробіл і ім’я Smith
були частиною нового значення нашої змінної, ми візьмемо це ім’я у подвійні лапки ("
).
#!/bin/bash # Це наш перший коментар. Також корисно коментувати всі сценарії. username="Carol Smith" echo "Hello $username!"
$ ./new_script.sh Hello Carol Smith!
Одна важлива річ, яку слід зазначити в Bash, полягає в тому, що подвійні та одинарні лапки ('
) поводяться дуже по-різному. Подвійні лапки вважаються “слабкими”, оскільки вони дозволяють інтерпретатору виконувати заміну в лапках. Одинарні лапки вважаються “сильними”, оскільки вони запобігають будь-якій заміні. Розглянемо наступний приклад:
#!/bin/bash # Це наш перший коментар. Також корисно коментувати всі сценарії. username="Carol Smith" echo "Hello $username!" echo 'Hello $username!'
$ ./new_script.sh Hello Carol Smith! Hello $username!
У другій команді echo
інтерпретатору заборонено замінити $username
на Carol Smith
, тому вихід сприймається буквально.
Аргументи
Ви вже знайомі з використанням аргументів у основних утилітах Linux. Наприклад, rm testfile
містить як команду rm
, так і один аргумент testfile
. Аргументи можуть передаватися сценарію під час виконання, і вони змінюють поведінку сценарію. Вони легко реалізуються.
#!/bin/bash # Це наш перший коментар. Також корисно коментувати всі сценарії. username=$1 echo "Hello $username!"
Замість того, щоб призначати значення username
безпосередньо всередині сценарію, ми призначаємо йому значення нової змінної $1
. Це відноситься до значення першого аргументу.
$ ./new_script.sh Carol Hello Carol!
Перші дев’ять аргументів обробляються таким самим чином. Є способи обробки більш ніж дев’яти аргументів, але це виходить за рамки цього уроку. Ми продемонструємо приклад, використовуючи лише два аргументи:
#!/bin/bash # Це наш перший коментар. Також корисно коментувати всі сценарії. username1=$1 username2=$2 echo "Hello $username1 and $username2!"
$ ./new_script.sh Carol Dave Hello Carol and Dave!
Під час використання аргументів дуже важливо враховувати наступне: у наведеному вище прикладі є два аргументи Carol
та Dave
, призначені для $1
та $2
відповідно. Наприклад, якщо другий аргумент відсутній, оболонка не видає помилку. Значення $2
буде просто null або взагалі нічого.
$ ./new_script.sh Carol Hello Carol and !
У нашому випадку було б гарною ідеєю ввести деяку логіку до нашого сценарію, щоб різні умови впливали на вихід, який ми хочемо надрукувати. Ми почнемо з введення іншої корисної змінної, а потім перейдемо до створення операторів if.
Повернення кількості аргументів
Хоча такі змінні, як $1
і $2
, містять значення позиційних аргументів, інша змінна $#
містить кількість аргументів.
#!/bin/bash # Це наш перший коментар. Також корисно коментувати всі сценарії. username=$1 echo "Hello $username!" echo "Number of arguments: $#."
$ ./new_script.sh Carol Dave Hello Carol! Number of arguments: 2.
Умовна логіка
Використання умовної логіки в програмуванні – широка тема, і вона не буде детально розглянута в цьому уроці. Ми зосередимося на синтаксисі умов у Bash, який відрізняється від більшості інших мов програмування.
Розглянемо, чого ж ми сподіваємося досягти. У нас є простий скрипт, який повинен мати можливість надрукувати привітання одному користувачеві. Якщо є що-небудь, крім повідомлення для одного користувача, ми повинні надрукувати повідомлення про помилку.
-
Умова, яку ми тестуємо, — це кількість користувачів, яка міститься у змінній
$#
. Ми хотіли б знати, чи є значення$#
1
. -
Якщо умова true, ми виконаємо дію, щоб привітати користувача.
-
Якщо умова false, ми надрукуємо повідомлення про помилку.
Тепер, коли логіка зрозуміла, ми зосередимося на синтаксисі, необхідному для реалізації цієї логіки.
#!/bin/bash # Простий скрипт для привітання одного користувача. if [ $# -eq 1 ] then username=$1 echo "Hello $username!" else echo "Please enter only one argument." fi echo "Number of arguments: $#."
Умовна логіка міститься між if
і fi
. Умова для перевірки розташована між квадратними дужками [ ]
, а дія, яку потрібно виконати, якщо умова буде істинною, вказана після then
. Зверніть увагу на пробіли між квадратними дужками та логіку, яка між ними міститься. Пропуск цього пробілу призведе до помилок.
Цей сценарій виведе наше привітання, або повідомлення про помилку. Але він завжди друкуватиме рядок Number of arguments
(Кількість аргументів).
$ ./new_script.sh Please enter only one argument. Number of arguments: 0. $ ./new_script.sh Carol Hello Carol! Number of arguments: 1.
Зверніть увагу на оператор "if". Ми використали -eq
для числового порівняння. У цьому випадку ми перевіряємо, що значення $#
дорівнює одиниці. Інші порівняння, які ми можемо провести:
-ne
-
Не дорівнює
-gt
-
Більше ніж
-ge
-
Більше ніж або дорівнює
-lt
-
Менше ніж
-le
-
Менше ніж або дорівнює
Вправи до посібника
-
Користувач вводить у свою оболонку наступне:
$ PATH=~/scripts $ ls Command 'ls' is available in '/bin/ls' The command could not be located because '/bin' is not included in the PATH environment variable. ls: command not found
-
Що зробив користувач?
-
Яка команда поєднає поточне значення
PATH
з новим каталогом~/scripts
?
-
-
Розглянемо наступний сценарій. Зверніть увагу, що він використовує
elif
для перевірки другої умови:> /!bin/bash > fruit1 = Apples > fruit2 = Oranges if [ $1 -lt $# ] then echo "This is like comparing $fruit1 and $fruit2!" > elif [$1 -gt $2 ] then > echo '$fruit1 win!' else > echo "Fruit2 win!" > done
-
Рядки, позначені
>
, містять помилки. Виправте помилки.
-
-
Яким буде результат у наступних ситуаціях?
$ ./guided1.sh 3 0
$ ./guided1.sh 2 4
$ ./guided1.sh 0 1
Дослідницькі вправи
-
Напишіть простий скрипт, який перевірить, чи передано точно два аргументи. Якщо так, надрукуйте аргументи у зворотному порядку. Розглянемо цей приклад (примітка: ваш код може виглядати інакше, але він повинен привести до того ж результату):
if [ $1 == $number ] then echo "True!" fi
-
Цей код правильний, але це не порівняння чисел. Використовуйте пошук в Інтернеті, щоб дізнатися, чим цей код відрізняється від використання
-eq
. -
Існує змінна середовища, яка друкуватиме поточний каталог. Використовуйте
env
, щоб дізнатися ім’я цієї змінної. -
Використовуючи те, що ви дізналися з питань 2 і 3, напишіть короткий сценарій, який приймає аргумент. Якщо передано аргумент, перевірте, чи відповідає цей аргумент імені поточного каталогу. Якщо так, надрукуйте
yes
. В іншому випадку надрукуйтеno
.
Підсумки
У цьому уроці ви дізналися:
-
Як створювати та виконувати прості сценарії.
-
Як використовувати shebang для визначення інтерпретатора.
-
Як встановити та використовувати змінні всередині сценаріїв.
-
Як обробляти аргументи в скриптах.
-
Як побудувати оператори
if
. -
Як порівнювати числа за допомогою числових операторів.
Команди, які використовуються у вправах:
echo
-
Друкує рядок у стандартному виведенні.
env
-
Друкує всі змінні середовища у стандартному виведенні.
which
-
Друкує абсолютний шлях команди.
chmod
-
Змінює права доступу до файлу.
Спеціальні змінні, які використовуються у вправах:
$1, $2, … $9
-
Містять позиційні аргументи, передані скрипту.
$#
-
Містить кількість аргументів, переданих скрипту.
$PATH
-
Містить каталоги з виконуваними файлами, які використовуються системою.
Оператори, які використовуються у вправах:
-ne
-
Не дорівнює
-gt
-
Більше ніж
-ge
-
Більше ніж або дорівнює
-lt
-
Менше ніж
-le
-
Менше ніж або дорівнює
Відповіді до вправ посібника
-
Користувач вводить у свою оболонку наступне:
$ PATH=~/scripts $ ls Command 'ls' is available in '/bin/ls' The command could not be located because '/bin' is not included in the PATH environment variable. ls: command not found
-
Що зробив користувач?
Користувач перезаписав вміст PATH каталогом
~/scripts
. Командуls
більше не можна знайти, оскільки вона не міститься в PATH. Зауважте, що ця зміна впливає лише на поточний сеанс, вихід із системи поверне її значення зі скасуваннями змін. -
Яка команда поєднає поточне значення
PATH
з новим каталогом~/scripts
?PATH=$PATH:~/scripts
-
-
Розглянемо наступний сценарій. Зверніть увагу, що він використовує
elif
для перевірки другої умови:> /!bin/bash > fruit1 = Apples > fruit2 = Oranges if [ $1 -lt $# ] then echo "This is like comparing $fruit1 and $fruit2!" > elif [$1 -gt $2 ] then > echo '$fruit1 win!' else > echo "Fruit2 win!" > done
-
Рядки, позначені
>
, містять помилки. Виправте помилки.#!/bin/bash fruit1=Apples fruit2=Oranges if [ $1 -lt $# ] then echo "This is like comparing $fruit1 and $fruit2!" elif [ $1 -gt $2 ] then echo "$fruit1 win!" else echo "$fruit2 win!" fi
-
-
Яким буде результат у наступних ситуаціях?
$ ./guided1.sh 3 0
Apples win!
$ ./guided1.sh 2 4
Oranges win!
$ ./guided1.sh 0 1
This is like comparing Apples and Oranges!
Відповіді до дослідницьких вправ
-
Напишіть простий скрипт, який перевірить, чи передано точно два аргументи. Якщо так, надрукуйте аргументи у зворотному порядку. Розглянемо цей приклад (примітка: ваш код може виглядати інакше, але він повинен привести до того ж результату):
if [ $1 == $number ] then echo "True!" fi
#!/bin/bash if [ $# -ne 2 ] then echo "Error" else echo "$2 $1" fi
-
Цей код правильний, але це не порівняння чисел. Використовуйте пошук в Інтернеті, щоб дізнатися, чим цей код відрізняється від використання
-eq
.Використання
==
порівняє рядки. Тобто, якщо символи обох змінних точно збігаються, то умова істинна.abc == abc
true
abc == ABC
false
1 == 1
true
1+1 == 2
false
Порівняння рядків призводить до несподіваної поведінки, якщо ви тестуєте числа.
-
Існує змінна середовища, яка друкуватиме поточний каталог. Використовуйте
env
, щоб дізнатися ім’я цієї змінної.PWD
-
Використовуючи те, що ви дізналися з питань 2 і 3, напишіть короткий сценарій, який приймає аргумент. Якщо передано аргумент, перевірте, чи відповідає цей аргумент імені поточного каталогу. Якщо так, надрукуйте
yes
. В іншому випадку надрукуйтеno
.#!/bin/bash if [ "$1" == "$PWD" ] then echo "yes" else echo "no" fi