Шебанг
Для прикладу, створимо файл із розширенням .php
, та напишемо програму яка виводить в термінал теперішню дату.
$ echo "<?php print date(\"D M j G:i:s T Y\") . \"\n\";" > pdate.php
Команда echo
виводить текст на стандартний пристрій виводу в stdout, зазвичай це термінал, але через
опцію >
ми перенаправляємо stdout echo
в stdin файлу pdate.php
.
Якщо встановлений інтерпретатор php
, запустити програму можна так:
$ php pdate.php
Sun May 29 19:12:41 EEST 2022
Програму можна оптимізувати, постійно вказувати інтерпретатор(програма виконання) і шлях до файлу
злегка роздратовує, тому спочатку дізнаємось де знаходиться інтерпретатор php
:
$ which php
/usr/bin/php
Команда which
використовується для пошуку виконуваних файлів та
показує шлях, де знаходиться вказаний файл на файловій системі.
Додамо #!/usr/bin/php
в першому рядку файлу pdate.php
, після цього файл виглядає:
$ cat pdate.php
#!/usr/bin/php
<?php print date("D M j G:i:s T Y") . "\n";
Запускаємо скрипт як винонуваний файл:
$ ./pdate.php
bash: ./pdate.php: Permission denied
Хм…. відмовлено в доступі.. Перевіримо права
$ ls -l ./pdate.php
-rw-rw-r-- 1 vkykalo vkykalo 59 мая 29 19:33 ./pdate.php
Бачимо, що файл pdate.php
не є виконувальним тому ./pdate.php
не запрацює, тому зробимо наступне:
$ chmod a+x pdate.php
Цей додатковий крок означає наступне, “комп’ютер, зроби мій файл pdate.php
виконувальним” і запустимо ще раз файл
./pdate.php
$ ./pdate.php
Sun May 29 21:04:01 EEST 2022
Працює, для лаконічності приберемо зайве розширення файлу .php
$ mv pdate.php pdate
Запускаємо програму як винувальний файл ./pdate
$ ./pdate
Sun May 29 21:16:49 EEST 2022
Насправді ми ніякої функціональності не додали в нашу програму, проте більше не потрібно вказувати виконавчу програму для запуску скрипту, за нас зробив це Шебанг.
Зробимо ще одну оптимізацію, замінимо шебанг #!/usr/bin/php
на #!/usr/bin/env php
, щоб програма мала наступний
текст файлу:
$ cat pdate
#!/usr/bin/env php
<?php print date("D M j G:i:s T Y") . "\n";
Фактично, нічого не змінилося. Проте питання, для чого були зміни?
Основна ідея – це кросплатформеність.
Не має гарантії, що на різних unix
системах, програми, що виконуються, будуть лежати по шляху, який вказаний в shebang
.
Іншими словами, на різних дистрибутивах linux шлях до інтерпретатора php
може бути різний, а утиліта /usr/bin/env
займається пошуком виконувальних програм.
Використання env
дозволяє знизити цей ризик за рахунок запуску команди, на основі даних зі змінною середовища $PATH
.
Утиліті /usr/bin/env
передаємо ту утиліту яку хочемо запустити (php
, python2
, python3
…) і вона сама знайде і запустить
необхідну версію вам інтерпретатора.
Шлях до php
інтерпретатора не на всіх дистрибутивах linux буде мати /usr/bin/php
.
Шебанг(#!
) - це просто шлях до програми в типовій unix
системі, яка має назву середовище.
Перший рядок просто нам говорить, є #!/usr/bin/env php
, знайди мені php
інтерпретатор у своєму
середовищі env
та запусти файл.
Відтепер для користувача цієї програми не буде важливо знати, а на якій мові програмування написаний скрипт.
Приклад на python3
$ echo "print('hello world')" > test.py
$ python3 test.py
hello world
Додаємо шебанг #!/usr/bin/env python3
та змінюємо режим chmod a+x test.py
і
робимо ренейм mv test.py test
Після цього робимо запуск
$ ./test
hello world
Створюємо власну утиліту
Більшість команд, які ми використовуємо в терміналі(pwd
, ls
, cat
, rm
, cp
, echo
…) знаходяться в каталозі
/usr/bin/
, проте не тільки там знаходяться виконувальні програми.
Коли ми набираємо будь-яку команду в терміналі, linux перевіряє змінну середовища $PATH
, в якій знаходяться каталоги в яких
необхідно здійснити пошук до виконувальної команди.
$ echo $PATH
/home/vkykalo/.nvm/versions/node/v10.24.1/bin:/home/vkykalo/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
Якщо ми хочемо написати власну утиліту, її необхідно перемістити в одну із каталогів, але кращою практикою для цього являється
каталог ~/.local/bin
, або ~/.bashrc
Зробимо нашу програму pdate
глобальною утилітою як інші команди (ls
,echo
..).
Нагадаємо код програми та права на файл.
vkykalo@vkykalo-HP-ProBook-455R-G6:~$ ls -la pdate
-rwxrwxr-x 1 vkykalo vkykalo 63 июн 7 23:57 pdate
vkykalo@vkykalo-HP-ProBook-455R-G6:~$ cat pdate
#!/usr/bin/env php
<?php print date("D M j G:i:s T Y") . "\n";
Переносимо файл
$ mv pdate ~/.local/bin
Ось і все! Можемо користуватися командою pdate
.
vkykalo@vkykalo-HP-ProBook-455R-G6:~/workspace/github$ pdate
Wed Jun 8 0:04:22 EEST 2022
vkykalo@vkykalo-HP-ProBook-455R-G6:~/workspace/github$ ls
aws-lambda-python Browser.java index.php pdf-JODConverter static-blog-page test.php
pdate
файлу немає в каталозі, проте все працює.
Висновок
shebang
економить наш час тим, що пишемо менше boilerplate code, також можемо створювати власні утиліти.