Як запустити скрипт оболонки на консолі 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.