Как запустить скрипт оболочки на консоли 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

Hashbang сообщает ядру, какую программу запустить (в этом случае команда запускается /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, hashbang может иметь один аргумент . В этом случае мы используем bashв качестве аргумента envпрограмму. Это означает, что у нас нет места для передачи аргументов bash. Так что нет способа преобразовать что-то вроде #!/bin/bash -exuэтой схемы. Вы должны будете поставить set -exuпосле hashbang вместо этого.

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

lhunath
источник
66
Спасибо, что нашли время написать хороший ответ на простой вопрос.
PA
5
Если бы я использовал в zshкачестве своей оболочки, я бы использовал hashbang #! /usr/bin/env zsh?
stefmikhail
6
@stefmikhail: Неважно, какой интерпретатор оболочки вы используете для вызова скрипта, вы должны использовать, #! /usr/bin/env zshесли (и только если) код внутри скрипта должен выполняться оболочкой Z.
Johnsyweb
1
+1 за объяснение. Я склонен забывать, но знание значения команды поможет мне вспомнить.
красавица Надар
2
@Carpetsmoker Это правильно и не ограничивается хэшбэнгом. Скрипты bash всегда должны использовать окончания строк UNIX, иначе к последнему аргументу каждой команды будет добавлен \ r, как и в имени команды hashbang.
июня
80

Чтобы запустить shell-скрипт '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 между кругами.
PA
10

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

. /path/to/script.sh

или

source /path/to/script.sh

Обратите внимание, что /path/to/script.shможет быть относительным, например, . bin/script.shзапускает script.shв binкаталоге в текущем каталоге.

Чес. Owens
источник
7
Будьте очень осторожны при поиске или расстановке точек с относительными путями. Вы всегда должны начинать их с ./ Если вы этого не сделаете, а относительный путь не содержит косых черт, вы будете искать что-то в PATH, ДО чего-то в текущем каталоге! Очень опасно для злоупотреблений.
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 запустит его.

benwiggy
источник
0

Небольшое дополнение, чтобы запустить интерпретатор из той же папки, все еще используя #! Hashbang в скриптах.

В качестве примера, исполняемый файл php7.2, скопированный из / usr / bin, находится в папке в сценарии приветствия .

#!./php7.2
<?php

echo "Hello!"; 

Чтобы запустить это:

./hello

Которые ведут себя так же, как:

./php7.2 hello
NVRM
источник