Як запустити скрипт оболонки на консолі Unix або терміналі Mac?


507

Я знаю це, забудь і знову його вивчи. Час його записати.


15
написання потягу на нагороду аж до станції репутації
— DivideByZer0,

не збираюся подавати заяву, щоб просто помилуватися на цю приголомшливу помилку!
— BRHSM

Відповіді:


942

Для запуску невиконаного shсценарію використовуйте:

sh myscript

Для запуску невиконаного bashсценарію використовуйте:

bash myscript

Запустити виконуваний файл (який є будь-яким файлом з дозволом на виконання); ви просто вкажіть його своїм шляхом:

/foo/bar
/bin/bar
./bar

Щоб зробити сценарій виконуваним, надайте йому необхідний дозвіл:

chmod +x bar
./bar

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

#! /usr/bin/env bash

Хешбанг повідомляє ядро, яку програму запустити (у цьому випадку команда /usr/bin/envвиконується з аргументом bash). Потім сценарій передається програмі (як другий аргумент) разом з усіма аргументами, які ви дали сценарію, як наступні аргументи.

Це означає, що кожен виконуваний сценарій повинен мати хешбанг . Якщо цього немає, ви не повідомляєте ядро, що воно таке , і тому ядро ​​не знає, яку програму використовувати для його інтерпретації. Це може бути bash, perl, python, sh, або що - то ще. (Насправді ядро ​​часто використовує оболонку користувача за замовчуванням для інтерпретації файлу, що дуже небезпечно, оскільки воно може бути зовсім не правильним інтерпретатором, або можливо, зможе проаналізувати його частину, але з тонкими поведінковими відмінностями, такими як відмінок між shі bash).

Примітка о /usr/bin/env

Найчастіше ви побачите хеш-чубок на зразок такого:

#!/bin/bash

Результат полягає в тому, що ядро ​​запустить програму /bin/bashдля інтерпретації сценарію. На жаль, bashне завжди постачається за замовчуванням, і він не завжди доступний у /bin. У той час як на машинах Linux це зазвичай є, існує ряд інших машин POSIX, де розміщуються bashв різних місцях, наприклад, /usr/xpg/bin/bashабо /usr/local/bin/bash.

Щоб написати портативний скрипт bash, ми не можемо розраховувати на жорстке кодування місця розташування bashпрограми. POSIX вже має механізм для вирішення , що: PATH. Ідея полягає в тому, що ви встановлюєте свої програми в одному з каталогів, які є, PATHі система повинна мати змогу знайти вашу програму, коли ви хочете запустити її по імені.

На жаль, ви не можете просто зробити це:

#!bash

Ядро не буде (дехто може) PATHшукати вас. Існує програма, яка може здійснити PATHпошук для вас, хоча вона називається env. На щастя, майже у всіх системах встановлена envпрограма /usr/bin. Тож ми починаємо envвикористовувати жорстко закодований шлях, який потім здійснює PATHпошук bashі запускає його, щоб він міг інтерпретувати ваш сценарій:

#!/usr/bin/env bash

Цей підхід має один недолік: Згідно з POSIX, хешбанг може мати один аргумент . У цьому випадку ми використовуємо bashяк аргумент envпрограмі. Це означає, що нам не залишається місця для передачі аргументів bash. Тому немає можливості перетворити щось подібне #!/bin/bash -exuдо цієї схеми. set -exuЗамість цього вам доведеться поставити хешбанг.

Цей підхід також має ще одну перевагу: деякі системи можуть поставлятися з пристроєм /bin/bash, але користувачеві це може не сподобатися, він може виявити, що він баггі чи застарів, і, можливо, його встановили bashдесь ще. Це часто трапляється в OS X (Macs), де Apple надсилає застарілі, /bin/bashа користувачі встановлюють сучасні програми, /usr/local/bin/bashвикористовуючи щось на зразок Homebrew. Коли ви використовуєте envпідхід, який здійснює PATHпошук, ви враховуєте перевагу користувача та використовуєте його переважний баш над тим, з яким постачається його система.


66
Дякую, що знайшли час, щоб написати хорошу відповідь на просте запитання.
— ПА

5
Якщо я використовую zshяк свою оболонку, чи використовую я hashbang #! /usr/bin/env zsh?
— stefmikhail

6
@stefmikhail: Не має значення, який інтерпретатор оболонки ви використовуєте для виклику сценарію, ви повинні використовувати, #! /usr/bin/env zshякщо (і лише якщо) код всередині сценарію повинен виконуватись оболонкою Z.
— Johnsyweb

1
+1 для пояснення. я схильний забувати, але знання значення команди допоможе мені згадати.
— Ангелін Надар

2
@Carpetsmoker Це правильно і не обмежується хашбангом. сценарії bash завжди повинні використовувати закінчення рядків UNIX, інакше останній аргумент кожної команди буде доданий до нього, як і ім'я команди hashbang.
— lhunath

80

Щоб запустити скрипт оболонки 'file.sh':

sh file.sh

bash file.sh

Іншим варіантом є встановлення дозволу на виконання за допомогою команди chmod:

chmod +x file.sh

Тепер запустіть .sh файл таким чином:

./file.sh

16

Для оболонки бурна:

sh myscript.sh

Для баш:

bash myscript.sh

Дякую за відповідь на це цілком очевидне запитання. Для такого хлопця Mac, як я, легко забути старі команди Unix між колами.
— ПА

10

Якщо ви хочете, щоб сценарій запускався в поточній оболонці (наприклад, ви хочете, щоб він міг впливати на ваш каталог або оточення), слід сказати:

. /path/to/script.sh

або

source /path/to/script.sh

Зверніть увагу , що /path/to/script.shможе бути відносним, наприклад , . bin/script.shбіжить script.shв binдиректорії в поточній директорії.


7
Будьте дуже обережні, коли ви шукаєте джерела або додаєте їх до релевантних імен. Ви завжди повинні починати їх з. Дуже небезпечно для зловживань.
— lhunath

0

Спочатку дайте дозвіл на виконання: -
chmod +x script_name

  1. Якщо скрипт не виконується: -
    для запуску файлу скрипту sh: -
    sh script_name
    для запуску файлу скриптів bash: -
    bash script_name
  2. Якщо сценарій виконується: -
    ./script_name

ПРИМІТКА . -Ви можете перевірити, чи файл виконується чи ні, використовуючи "ls -a"


0

Розширення файлу .command призначено для Terminal.app. Подвійне клацання на будь-якому .command-файлі виконає його.


0

Невелике доповнення, щоб запустити інтерпретатора з тієї ж папки, все ще використовуючи #! Hashbang у скриптах.

Наприклад, виконуваний файл php7.2, скопійований з / usr / bin, знаходиться у папці разом із привітальним сценарієм.

#!./php7.2
<?php

echo "Hello!"; 

Щоб запустити його:

./hello

Які поводяться так само, як:

./php7.2 hello
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.