.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 не зробила помилок Windows Secrets.pdf.exe.

Ось що відбувається під час введення foo:

  1. Перенаправлення для STDIN, STDOUTі STDERRвстановлюються.

  2. Оболонка перевіряє свою внутрішню хеш-таблицю, щоб побачити, чи вона вже знає $PATHзапис foo. Якщо такої немає, оболонка здійснює пошук у каталогах $PATH, шукаючи файл, який називається fooбіт Execute, встановлений у його дозволах на отримання файлів. Перші fooперемоги.

  3. Якщо перші два байти файлу fooє #!, наступний рядок - це ім'я інтерпретатора, який слід запустити. Таким чином #!/bin/bashвводиться сценарій Bash, #!/usr/bin/perlвводиться сценарій Perl і т.д.

  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, що працює з інтерпретатором, для виконання дозволів

$-> 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 , перл, ...?).

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

Користувачам цього сценарію не потрібно знати про цю зміну мови, вони продовжуватимуть виконувати ту ж команду, і вона продовжить працювати.

Якщо ваш сценарій був названий do-something.sh, він може продовжувати бути do-something.sh, але тепер він написаний у python (наприклад), і тому ваш початковий натяк зараз є абсолютно оманливим.


4

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

#!/bin/bash

тоді вам також потрібно зробити файл виконуваним для системи

chmod 755 yourfilename

Це те саме, що використання chmod +x yourfilenameцифр пояснюється легко.

Це число втричі доданих восьмериків, перше число - для користувача, друге - для групи, а третє - для інших, більше про це ви можете знайти тут .

І якщо ви перебуваєте в тому ж каталозі, що і ваш скрипт, не забудьте використовувати ./так:

./yourfilename

Спробував це. На жаль, немає відмінностей від оригінальних результатів.
Філіп Кіркбрід

@PhilipKirkbride подивіться на мою переглянуту відповідь, це, можливо, прожене трохи світла.
Videonauth

0

Суфікс .sh насправді може перешкоджати, оскільки тоді для його запуску ви повинні ввести myscript.sh замість просто myscript, який не працюватиме. Краще просто назвати його «скриптом» без суфікса .sh, а швидке використання команди «файл» підкаже, чи це бінарний виконуваний файл (формат ELF в Linux) або сценарій оболонки, або будь-який інший тип скрипту.

QDOS (швидка та брудна операційна система, пізніше IBM перейменована на "DOS", після того, як mirosoft пірат її і незаконно продав їм) та інші дешеві рипофти CP / M, включаючи windows, все це змішують, тому що в цих системах немає таке, як виконувати дозволи на файли. Це призвело до незліченних спадів безпеки за останні 30-40 років. Насправді всього кілька хвилин тому я щойно отримав декілька небажаних листів із заграваним поштовим файлом, перейменованим на MYPICTURE.JPG.zip :)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.