Я написал простой сценарий. Когда я бегу sh <myscriptname.sh>
, я получаю правильный вывод, но когда я бегу ./<myscriptname.sh>
, я получаю ошибку.
Какая разница между тем, когда я делаю sh
и ./
?
Я написал простой сценарий. Когда я бегу sh <myscriptname.sh>
, я получаю правильный вывод, но когда я бегу ./<myscriptname.sh>
, я получаю ошибку.
Какая разница между тем, когда я делаю sh
и ./
?
Ответы:
Когда вы запускаете любой сценарий, передавая имя файла программе-интерпретатору сценария, вы запускаете программу-интерпретатор со сценарием в качестве аргумента, переданного ему. Например, это будет выглядеть как процесс 'sh' с аргументом 'filename.sh'. sh
Интерпретатор открывает файл.
С другой стороны, если вы запускаете сам скрипт, система вызывает указанную программу интерпретатора и передает содержимое скриптов. В этом случае процесс выглядит как «filename.sh» без аргументов.
Вы должны убедиться, что у вас есть линия взрыва:
#!/bin/bash
# bash script here
Строка взрыва - это самая первая строка в скрипте, которая начинается с тех же двух символов #!
, это то, что система читает, когда она пытается выполнить скрипт, а затем система сразу передает скрипт в программу. Обратите внимание, что эта строка не имеет ничего общего с bash и работает так же хорошо для python и perl, хотя они очень разные языки. Вы могли бы использовать, #!/usr/bin/python
например, а затем следовать за ним с кодом Python.
Как только у вас есть ваш скрипт, убедитесь, что вы установили права на выполнение:
chmod a+x filename.sh
Затем вы можете запустить скрипт как собственный процесс:
./filename.sh
Или поместите файл в известное место с хорошим именем программы, как /usr/sbin
и запустить из любого места:
sudo cp filename.sh /usr/sbin/program-name
program-name
И это действительно практическое преимущество использования линии взрыва с правильными разрешениями - все дело в развертывании . Пользователям очень сложно запустить скрипт, если они должны помнить, с какой программой запускать скрипт. Не забывайте указывать полный путь к скрипту каждый раз, когда они захотят его запустить. Где , как положить его в /usr/local/bin
, например, и сделать его исполняемым, можно сэкономить очень много горя для людей , которые пытаются использовать ваш сценарий. Эти программы затем становятся доступными для всех пользователей на вашем компьютере.
Это также хорошо для идентификации. Если вы войдете в top
программу, сценарий, запускаемый без строки взрыва, будет иметь только имя интерпретатора, т. Е. bash
, perl
Или python
. Но если скрипт запускается с нужными разрешениями, то отображается имя скрипта.
Примечание. Если вы хотите распространять сценарий, доступный для всех, создайте страницу руководства и пакет deb для его установки. Нам нужно уменьшить количество случайных скриптов в сети и увеличить количество дэбов, которые можно удалить.
bash
нет sh
.
PATH
.
/usr/local/bin
Вероятно, лучше /usr/sbin
- это означает, что программа является локальной для этой машины, а не частью дистрибутива.
Краткая версия:
sh
интерпретатор командной строки (тире)
Запуск sh my_script
заставляет dash интерпретировать скрипт.
./
пытается выяснить, какой интерпретатор использовать, посмотрев на первую строку. Например #!/bin/bash
, или даже #!/bin/ruby
(в отличие от бега ruby my_script
).
./
что находит, это метод выполнения системы, который просматривает первые два байта файла.
sh
и файл содержит sha-bang, означает ли это, что sha-bang будет проигнорирован или откроет оболочку, в которой также есть sh
ссылки, а затем, возможно, какую-нибудь другую оболочку или что она делает :)?
Разница в том, что
с sh
, вы запускаете программу, которая будет интерпретировать строки в вашем скрипте так же, как вы бы набрали их в интерактивной подсказке терминала,
когда ./
вы делаете ярлык, предполагая, что скрипт находится прямо здесь, в текущем каталоге, в котором вы сидите, и он будет исполняемым (потому что, например, вы его выпустили chmod +x myscript.sh
), сохраняя ваше бесценное время на будущее :-)
sh
файлом не обязательно должен быть исполняемый файл.
Есть три основные причины, по которым вы можете получить ошибку:
chmod +x <myscriptname.sh>
чтобы исправитьnoexec
") /usr/local/bin
#!
линия ошибки #!/bin/sh
или#!/bin/bash
Если ваша первая строка выглядит правильно, но все еще не работает, убедитесь, что в файле нет окончаний строки DOS.
Ошибка будет выглядеть примерно так:
$ ./myscript.sh
bash: ./myscript.sh: /bin/bash^M: bad interpreter: No such file or directory
Вы можете это исправить, выполнив dos2unix <myscriptname.sh>
, или если у вас нет этого
perl -p -i -e 's/\r\n$/\n/' <myscriptname.sh>
.
И ответ таков: sh - это имя очень популярной оболочки. Но устаревшие и заменены другими. В настоящее время sh связан с другими оболочками, установленными на машине. например, я поместил Баш там. Запуск любой оболочки из sh обычно вызывает некоторый режим «совместимости» с оригинальным поведением «оболочки».
Так что решение довольно простое. Посмотрите, что стоит за командой sh (ls -al / bin / sh), и поместите #! / Bin / what_you_find_there в качестве первой строки (или, если в вашем скрипте есть что-то подобное, отредактируйте ее).
И наоборот, в самом скрипте может быть какая-то ошибка. Как и зависимость, которую встречает sh, но не интерпретатор, который фактически используется.
mkdir ~/bin ; cp myscript.sh ~/bin/
echo "export PATH="$PATH:/home/$USER/bin" >> ~/.profile ; source ~/.profile ;
Не /usr/sbin
, это для ненужных административных инструментов, /usr/local/bin
это лучший выбор, если вы не хотите иметь ~/bin/
, но sudo
желательно избегать как можно больше.
~/.profile
уже есть код для добавления ~/bin
, если он существует, в PATH
. С другой стороны, не помещайте расширения в сценарии.
ls ~/bin/|wc -l = 428
) Я положил много вещей там;)
/bin
и /usr/bin
вы увидите, что они не используют расширения.