.sh указав расширение?


12

Почему некоторые системы будут запускать .shфайл, просто указав имя файла без расширения, а другие требуют имени плюс расширение? В моем случае я пытаюсь написать серию команд, следуя этим инструкциям .

Я сейчас указываю расширение, но .shпредпочтение отдается запуску команд без него .


4
Использование .shв качестве расширения во многих случаях считается плохой практикой: это противоречит тому, как называются другие команды (вы не запускаете ls.elf), оно часто вводит в заблуждение (если вы foo.shначинаете с #!/bin/bash, то при запуске sh foo.shон запускается с другим интерпретатором, чем он создан для ), и если вы переписываете foo.shего в программу Python, использование этого расширения означает, что вам нужно выбирать между сохранением вводящего в заблуждение названия и переписыванием каждой вызывающей его программы.
Чарльз Даффи

2
... где это лучшая практика оболочки библиотека, а не команды с +xнабором - где foo.shнаходится библиотека , которая может быть получена в любой POSIX оболочку, foo.bashможет быть получена в Баш, foo.kshв KSH и т.д.
Charles Duffy

Ответы:


39

Вы в замешательстве. .shРасширение лишь намек на человек, и не имеет абсолютно никакого влияния на то, как система обрабатывает файл. Unix / Linux не сделал Secrets.pdf.exeошибку Windows .

Вот что происходит, когда вы печатаете foo:

  1. Перенаправление для STDIN, STDOUTи STDERRустанавливаются.

  2. Оболочка проверяет свою внутреннюю хеш-таблицу, чтобы узнать, знает ли она уже $PATHзапись foo. Если ничего не существует, оболочка выполняет поиск в каталогах $PATH, ища файл с именем foo, для которого установлен бит «Выполнить» в правах доступа к файлу. Первые fooпобеды.

  3. Если первые два байта файла foo- #!следующая строка, это имя интерпретатора для запуска. Таким образом, #!/bin/bashвводится Bash-скрипт, #!/usr/bin/perlPerl-скрипт и т. Д.

  4. Если файл начинается с \177ELF, это исполняемый двоичный файл, и ld.soзапускает его.

Прочитайте man execveи man ld.soдля более подробного объяснения.


15
Да, в Linux вы можете дважды щелкнуть файл Secrets.pdf, не зная, что это на самом деле исполняемый файл;)
OrangeDog

1
@OrangeDog Я знаю, что вы шутите, но я чувствую, что должен указать, что исполняемый бит ( chmod +x) в значительной степени решает эту проблему, верно?
wchargin

3
@WChargin Это зависит от того, насколько хорошо ведет себя ваша файловая система (например, смонтированный сетевой ресурс или раздел NTFS может оптимистично установить xбит для всего) и откуда пришел файл (любой процесс с контролем над каталогом может быть обманут в настройке разрешений) , Таким образом, это смягчает это, но я бы не сказал, что это решает это.
IMSoP

2
@WChargin, пока, но я думаю, что его точка зрения в том, что обычно файловые менеджеры не показывают исполняемый бит, то есть нет «подсказки людям», как расширение.
Пол Дрейпер

1
Я никогда не нажимаю по ошибке, Secrets.pdf.exeпотому что я всегда отключаю глупую hide file extensionфункцию
phuclv

12

Ключевой момент заключается в следующем: расширения не имеют значения в любой Unix-подобной системной системе. Имя файла является просто именем и не влияет на возможность запуска скрипта или скомпилированного исполняемого файла . Программист может добавить .shрасширение, чтобы указать, что файл является сценарием оболочки или .pyсценарием Python, но в отличие от Windows, любой Unix не заботится о наименовании, он заботится о разрешениях.

Что имеет значение, так это исполняемое разрешение, предоставленное файлу. Который вы можете проверить с

ls -l /path/to/file

Запуск исполняемых файлов

Для запуска скрипта есть несколько способов.

  • Если ваш текущий каталог совпадает со сценарием, а сценарий имеет права на выполнение, вы можете запустить его следующим образом ./my_script_name. .Означает текущий каталог.
  • Если ваш текущий каталог отличается и скрипт имеет разрешения на выполнение, вы можете запустить его, указав полный путь: /home/user/bin/my_script_name

(Два вышеупомянутых метода основаны на том, чтобы иметь исполняемый набор разрешений; независимо от того, является ли файл частью $PATHпеременной, значение не имеет. Наличие #!строки также имеет значение; без него скрипт будет выполняться текущей оболочкой, которую вы открыли. Если у меня есть cshскрипт без этой строки, и попробуйте запустить его в bash ./my_script.csh, это не удастся)

  • Если ваш скрипт находится в каталоге, который является частью вашей $PATHпеременной, вы можете запустить его, просто вызвав имя. Вы можете вызвать chmodкоманду в командной строке, просто набрав ее имя, потому что она находится в /binпапке. /binвсегда является частью $PATHпеременной. В этом случае исполняемые права доступа и местоположение скрипта имеют значение
  • Указание интерпретатора в качестве команды и сценария в качестве аргумента. Таким образом, скрипт будет служить входным файлом для интерпретатора.
  • Поиск файла. С помощью . filename.shили source filename.shсценарий будет обрабатываться так, как если бы он вводился с клавиатуры, т. Е. Как если бы он был введен непосредственно в командную строку. В этом случае исполняемые права доступа и местоположение не имеют значения

Примеры

Пример # 1, работающий с интерпретатором, для разрешения exec

$-> ls -l abc.py                                                               
-rw-rw-r-- 1 xieerqi xieerqi 44 Apr 27 22:39 abc.py
$-> python abc.py                                                              
a
b
c

Пример №2, работающий с ./набором разрешений на исполняемый файл, набор строк shebang.

$-> cat abc.py                                                                 
#!/usr/bin/env python
for letter in 'a' 'b' 'c' :
   print letter
$-> ls -l abc.py
-rwxrwxr-x 1 xieerqi xieerqi 66 Apr 27 23:02 abc.py*
$-> ./abc.py                                                                   
a
b
c

Пример №3, работающий без установки строки shebang (не удается, потому что bash не может читать сценарии python; ни одна строка shebang не принимает текущую оболочку в качестве интерпретатора)

$-> cat abc.py                                                                 
for letter in 'a' 'b' 'c' :
   print letter
$-> ./abc.py                                                                   
./abc.py: 2: ./abc.py: Syntax error: word unexpected (expecting "do")

Пример # 4, запуск сценария, который имеет исполняемый набор прав доступа к папке формы, которая является частью $PATHпеременной

#  /home/xieerqi/bin is part of my path variable
$-> echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/opt/microchip/xc16/v1.25/bin:/opt/microchip/xc32/v1.40/bin:/opt/microchip/xc8/v1.35/bin:/home/xieerqi/bin:/home/xieerqi/bin/sh

$-> # current directory is /home/xieerqi
$-> pwd
/home/xieerqi
$-> # move the file to ~/bin
$-> mv ~/abc.py ~/bin/abc.py
$-> # now I can run it just by calling the name
$-> abc.py
/home/xieerqi/bin/abc.py: 2: /home/xieerqi/bin/abc.py: Syntax error: word unexpected (expecting "do")
$-> # Syntax error because again, no interpreter specified.                    
$-> # must add #!/usr/bin/env python
$-> vi /home/xieerqi/bin/abc.py          
$-> # after adding the line with vi text editor, we can run
$-> abc.py                                                                     
a
b
c

Пример № 5, удаляющий расширение, все еще выполняется, потому что расширения не имеют значения, но у него есть разрешения и он является частью $PATH:

$-> mv ~/bin/abc.py  ~/bin/abc                                                 
$-> abc
a
b
c

Я выполнил команду и получил это «-rwxr-x ---». Что я хочу, чтобы значение читалось и как я могу его изменить?
Филипп Киркбрайд

Или вы говорите, что я должен просто переименовать «filename.sh» в «filename»?
Филипп Киркбрайд

1
@PhilipKirkbride Имя не имеет значения. Как вы управляете своей командой? Где это ? Каталог это часть вашего PATH?
Сергей Колодяжный

@PhilipKirkbride Позвольте мне через минуту расширить мой ответ, чтобы прояснить его.
Сергей Колодяжный

1
Взгляните, man chmodчтобы узнать, как устанавливать разрешения
Ник Мертен,

6

Хорошие объяснения здесь уже. Я просто хотел добавить, что в идеале вы не должны использовать расширения файлов для исполняемых файлов.

Обычно вам нужно выполнить что-то относительно простое, и вы начинаете с небольшого сценария оболочки. Со временем вы начинаете добавлять все больше и больше функциональных возможностей в ваш скрипт, пока не придет время, когда он станет не поддерживаемым, или вам понадобятся некоторые функции, которые вы не можете легко реализовать с помощью скрипта оболочки, и подумаете о переписывании этого скрипта на другом языке (python , perl, ...?).

Переписывание с нуля обычно считается ошибкой, но для сценариев это может иметь смысл, поскольку обычно они невелики или имеют множество функций. Но давайте предположим, что выполнимо переписать с нуля на другом языке, поддерживая функциональность и параметры / параметры исходного сценария оболочки.

Пользователям этого скрипта не нужно знать об этом изменении языка, они будут продолжать выполнять ту же команду, и она продолжит работать.

Если ваш сценарий был назван do-something.sh, он может продолжать существовать do-something.sh, но теперь он написан на python (например), и поэтому ваш начальный совет теперь полностью вводит в заблуждение.


4

Для запуска файлов без расширения вам обычно не нужно много делать, просто убедитесь, что у вас есть (в случае сценариев bash) правильная строка shebang в самой первой строке:

#!/bin/bash

тогда вам также нужно сделать исполняемый файл для системы

chmod 755 yourfilename

Это так же, как использование chmod +x yourfilenameчисел легко объяснить.

Это число, состоящее из трех восьмеричных добавок, первое число обозначает пользователя, второе - группу, а третье - остальные, подробнее об этом вы можете узнать здесь .

И если вы находитесь в той же директории, что и ваш скрипт, не забудьте использовать ./вот так:

./yourfilename

Пробовал это. К сожалению нет отличий от оригинальных результатов.
Филипп Киркбрайд

@PhilipKirkbride взгляните на мой пересмотренный ответ, который, вероятно, прольет еще немного света.
Видеонавт

0

Суффикс .sh на самом деле может помешать, потому что затем, чтобы запустить его, вы должны набрать myscript.sh вместо просто myscript, который не будет работать. Лучше просто назвать его «myscript» без суффикса .sh, и быстрое использование команды «file» скажет вам, является ли это двоичным исполняемым файлом (формат ELF в linux) или сценарием оболочки, или любым другим видом сценария.

QDOS (Quick and Dirty Operating System, позже переименованная в «DOS» IBM после того, как mirosoft скопировала его и незаконно продала ему) и другие дешевые копии CP / M, включая windows, смешивают все это, потому что в этих системах нет такая вещь, как разрешение на выполнение файлов. Это привело к бесчисленным группам безопасности за последние 30-40 лет. На самом деле всего несколько минут назад я только что получил несколько нежелательных писем с заминированным zip-файлом, переименованным в MYPICTURE.JPG.zip :)

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.