it-swarm-eu.dev

Různé způsoby spuštění skriptu Shell

Existuje několik způsobů, jak spustit skript, ty, které znám, jsou:

/path/to/script # using the path (absolute or relative)
. script        # using the . (dot)
source script   # using the `source` command

Je toho více? Jaké jsou mezi nimi rozdíly? Existují situace, které musím použít jednu a ne druhou?

44
phunehehe

Dalším způsobem je volání tlumočníka a předání cesty ke skriptu:

/bin/sh /path/to/script

Tečka a zdroj jsou ekvivalentní. (ÚPRAVA: ne, nejsou: jak KeithB zdůrazňuje v komentáři k jiné odpovědi, „.“ Funguje pouze v shellech souvisejících s bashem, kde „zdroj“ pracuje v shellech souvisejících s bashem i csh.) Spustí skript v - místo (jako byste zkopírovali a vložili skript přímo sem). To znamená, že všechny funkce a nelokální proměnné ve skriptu zůstanou. To také znamená, že pokud skript provede cd do adresáře, budete tam stále, když bude hotovo.

Ostatní způsoby spouštění skriptu jej spustí ve vlastní podsíti. Proměnné ve skriptu nejsou po dokončení stále naživu. Pokud skript změnil adresáře, pak to neovlivní volající prostředí.

/ cesta/do/skript a/bin/sh skript se mírně liší. Skript má obvykle na začátku „Shebang“, který vypadá takto:

#! /bin/bash

Toto je cesta k interpretovi skriptu. Pokud specifikuje jiného tlumočníka než vy, když jej provedete, může se chovat odlišně (nebo nemusí fungovat vůbec).

Například skripty Perl a Ruby skripty začínají (respektive):

#! /bin/Perl

a

#! /bin/Ruby

Pokud spustíte jeden z těchto skriptů spuštěním /bin/sh script, pak nebudou vůbec fungovat.

Ubuntu ve skutečnosti nepoužívá bash Shell, ale velmi podobný, který se nazývá pomlčka. Skripty, které vyžadují bash, mohou při volání /bin/sh script protože jste právě zavolali bash skript pomocí pomlčkového tlumočníka.

Další malý rozdíl mezi přímým vyvoláním skriptu a předáním cesty skriptu interpretovi je, že skript musí být označen jako spustitelný, aby jej mohl přímo spustit, ale ne jej spustit předáním cesty interpretovi.

Další drobná variace: můžete předponou libovolného z těchto způsobů spustit skript s evalem, takže můžete mít

eval sh script
eval script
eval . script

a tak dále. Ve skutečnosti to nic nezmění, ale myslel jsem, že to zahrnuji pro důkladnost.

32
Shawn J. Goff

Většina lidí ladí skripty prostředí Shell přidáním následujících ladicí příznaky do skriptu:

set -x     # Print command traces before executing command.
set -v     # Prints Shell input lines as they are read.
set -xv    # Or do both

To však znamená, že musíte otevřít soubor pomocí editoru (za předpokladu, že máte oprávnění k úpravě souboru) a přidat řádek jako set -x, uložte soubor a spusťte soubor. Až budete hotovi, musíte provést stejné kroky a odstranit set -x atd. atd. To může být únavné.

Namísto toho všeho můžete nastavit příkazy ladění na příkazovém řádku:

$ bash -x ~/bin/ducks
+ du -cks -x dir1 dir2 dir3 file1 file2 file3
+ sort -n
+ tail .ducks
123 etc
424 bin
796 total



$ sh -xv ~/bin/ducks  
#!/usr/bin/env bash

# Find the disk hog
# Borrowed from http://oreilly.com/pub/h/15
...
...
9
Stefan Lasiewski

Shawn J. Goff udělal spoustu dobrých bodů, ale nezahrnul celý příběh:

Ubuntu ve skutečnosti nepoužívá bash Shell, ale velmi podobný, který se nazývá pomlčka. Skripty, které vyžadují bash, mohou při volání /bin/sh skript, protože jste právě zavolali bash skript pomocí pomlčky tlumočníka.

Mnoho systémových skriptů (jako v init.d, v/etc atd.) Má Shebang #!/bin/sh, ale /bin/sh je ve skutečnosti symbolickým odkazem na další Shell - v dřívějších dobách /bin/bash, dnes /bin/dash. Ale když je jeden z nich vyvolán jako /bin/sh se chovají odlišně, tj. drží se v režimu kompatibility POSIX.

Jak to dokážou? Prověřují, jak byly vyvolány.

Může skript sám otestovat, jak byl vyvolán, a dělat různé věci, v závislosti na tom? Ano, může. Takže způsob, kterým se dovoláváte, může vždy vést k různým výsledkům, ale samozřejmě vás občas obtěžuje. :)

Zpravidla: Pokud se učíte konkrétní prostředí jako bash a píšete příkazy z bash tutoriálu, vložte #!/bin/bash v nadpisu, nikoli #!/bin/sh, pokud není uvedeno jinak. Jinak vaše příkazy mohou selhat. A pokud jste sami nenapsali skript, vyvolejte jej přímo (./foo.sh, bar/foo.sh) namísto hádání Shell (sh foo.sh, sh bar/foo.sh). Shebang by měl vyvolat ten pravý Shell.

A zde jsou dva další druhy vyvolání:

cat foo.sh | dash
dash < foo.sh
7
user unknown

. a source jsou ekvivalentní v tom, že nevytvářejí podproces, ale provádějí příkazy v aktuálním prostředí. To je důležité, když skript nastavuje proměnné prostředí nebo mění aktuální pracovní adresář.

Použití cesty nebo její zadání /bin/sh vytvoří nový proces, ve kterém jsou prováděny příkazy.

5
mouviciel
sh script
bash script

Přemýšlím, jestli jich je víc ...

. a source jsou stejné. Po provedení budou všechny změny prostředí v script zachovány. Obvykle by bylo použito ke zdroji knihovny Bash, takže knihovna může být znovu použita v mnoha různých skriptech.

Je to také dobrý způsob, jak zachovat aktuální adresář. Pokud změníte adresář ve skriptu, nebude použit v prostředí, ve kterém tento skript spustíte. Pokud jej však spustíte, bude po ukončení skriptu zachován aktuální adresář.

2
livibetter

. a zdroj jsou trochu odlišné v zsh (to je to, co používám), protože

source file

Funguje, zatímco

. file

ne, potřebuje

. ./file
1
bollovan
. ./filename
# ( dot space dot slash filename )

Spustí skript v aktuálním prostředí, když adresář není v cestě.

1
jrh_enginnering

Počítá se „ serland exec “ odlišným způsobem? Userland exec načte kód a nechá jej provést bez použití systémového volání execve ().

1
Bruce Ediger