В чем разница между ./ и sh для запуска скрипта?

59

Я написал простой скрипт. Когда я запускаю sh <myscriptname.sh> , я получил правильный результат, но когда я запускаю ./<myscriptname.sh> , я получил ошибку.

В чем разница между тем, когда я делаю sh и ./ ?

    
задан mr_eclair 23.01.2011 в 16:16
источник

6 ответов

59

Когда вы запускаете любой скрипт, передавая имя файла программе интерпретатора скриптов, вы запускаете программу-интерпретатор со скриптом в качестве аргумента, переданного в него. Например, это будет выглядеть как «sh» с аргументом «filename.sh». Переводчик sh открывает файл.

С другой стороны, если вы запускаете сам сценарий, система обращается к указанной программе интерпретатора и передает содержимое скриптов. В этом случае процесс выглядит как «filename.sh» без аргументов.

Вы должны убедиться, что у вас есть линия привязки:

#!/bin/bash
# bash script here

Строка bang - это самая первая строка в скрипте и начинается с тех же двух символов #! , это то, что система читает, когда пытается выполнить скрипт, а затем проходит система сценарий к программе сразу после. Обратите внимание, что эта строка не имеет ничего общего с 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 и делает его исполняемым, может сэкономить много горя для людей, пытающихся использовать ваш скрипт. Затем эти программы становятся доступными для пользователей all на вашем компьютере.

Это также хорошо для идентификации. Если вы перейдете в программу top , сценарий, запущенный без линии привязки, будет иметь имя интерпретатора, то есть bash , perl или python . Но если скрипт запускается с правильными разрешениями, то отображается имя скрипта.

Примечание. . Если вы хотите распространять скрипт, доступный для всех, создайте man-страницу и пакет deb для ее установки. Нам нужно уменьшить количество случайных скриптов в Интернете и увеличить количество deb, которые можно удалить.

    
ответ дан Martin Owens -doctormo- 23.01.2011 в 16:31
источник
31

Краткая версия:

  • sh - интерпретатор командной строки (тире).
    Запуск sh my_script делает dash интерпретирует скрипт.

  • ./ пытается выяснить, какой интерпретатор использовать, посмотрев на первую строку. Например. #!/bin/bash или даже #!/bin/ruby (как показано на выполнение ruby my_script ).

ответ дан Stefano Palazzo 23.01.2011 в 16:44
3

Есть три основные причины, по которым вы можете получить сообщение об ошибке:

  • файл не является исполняемым
    запустите 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> .

    
ответ дан Mikel 03.02.2011 в 23:03
2

Разница, которую вы делаете,

  • с sh , вы запускаете программу, которая будет интерпретировать строки в вашем скрипте так же, как вы бы набрали их в интерактивной подсказке терминала,

  • с ./ вы делаете ярлык, предполагая, что скрипт находится прямо здесь, в текущем каталоге, в котором вы сидите. И он будет исполняемым (поскольку, например, вы выпустили chmod +x myscript.sh ), сохранение вы неоценимое время для будущих времен: -)

ответ дан meduz 23.01.2011 в 23:13
0

И ответ заключается в том, что sh - это имя для очень популярной оболочки. Но устарели и заменены другими. В настоящее время sh связан с другими оболочками, установленными на машине. например У меня есть баш. Запуск любой оболочки из sh обычно вызывает некоторый режим совместимости с оригинальным поведением «shell».

Итак, решение довольно простое. Посмотрите, что находится за командой sh (ls -al / bin / sh), и поставьте #! / Bin / whatever_you_find_there в качестве первой строки (или если в вашем скрипте есть что-то подобное).

И, альтернативно, может быть какая-то ошибка в самом скрипте. Подобно зависимости, которая встречается sh, но не интерпретатором, который фактически используется.

    
ответ дан przemo_li 23.01.2011 в 18:09
0
mkdir ~/bin ; cp myscript.sh ~/bin/

echo "export PATH="$PATH:/home/$USER/bin" >> ~/.profile ; source ~/.profile ; 

Не /usr/sbin , это для несущественных административных инструментов, /usr/local/bin - лучший выбор, если вы не хотите иметь ~/bin/ , но избегаете sudo столько же, сколько возможно, целесообразно.

    
ответ дан Joey1978 24.01.2011 в 08:25