Wat is het verschil tussen het uitvoeren van een Bash script en het sourcen ervan?
Wat is het verschil tussen het uitvoeren van een Bash-script als A en het sourcen van een Bash-script als B?
A
> ./myscript
B
> source myscript
Wat is het verschil tussen het uitvoeren van een Bash-script als A en het sourcen van een Bash-script als B?
A
> ./myscript
B
> source myscript
Sourcing een script voert de commando’s uit in het huidige commandoregelproces.
Uitvoeren een script zal de commando’s in een nieuw shell proces uitvoeren.
Gebruik source als je wilt dat het script de omgeving in je huidige shell verandert. Gebruik anders execute.
Als je nog steeds in de war bent, lees dan verder.
Om wat verwarring op te helderen over de syntaxis voor execute en source:
./myscript
Dit zal Uitvoeren myscript
mits het bestand uitvoerbaar is en zich in de huidige directory bevindt. De voorlopende punt en schuine streep (./
) geven de huidige directory aan. Dit is nodig omdat de huidige directory meestal niet in $PATH
staat (en meestal ook niet zou moeten staan).
myscript
Dit Uitvoeren myscript
als het bestand uitvoerbaar is en zich in een directory in $PATH
bevindt.
source myscript
Dit bron myscript
. Het bestand hoeft niet uitvoerbaar te zijn, maar het moet wel een geldig shell script zijn. Het bestand kan in de huidige directory staan of in een directory in $PATH
.
. myscript
Dit zal ook source myscript
. Deze “spelling” is de officiële zoals gedefinieerd door POSIX . Bash heeft source
gedefinieerd als een alias voor de punt.
Beschouw myscript.sh
met de volgende inhoud:
#!/bin/sh
# demonstrate setting a variable
echo "foo: "$(env | grep FOO)
export FOO=foo
echo "foo: "$(env | grep FOO)
# demonstrate changing of working directory
echo "PWD: "$PWD
cd somedir
echo "PWD: "$PWD
Voordat we het script uitvoeren, controleren we eerst de huidige omgeving:
$ env | grep FOO
$ echo $PWD
/home/lesmana
De variabele FOO
is niet gedefinieerd en we zijn in de homedirectory.
Nu Uitvoeren we het bestand:
$ ./myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir
Controleer de omgeving opnieuw:
$ env | grep FOO
$ echo $PWD
/home/lesmana
De variabele FOO
is niet gedefinieerd en de werkdirectory is niet gewijzigd.
De uitvoer van het script laat duidelijk zien dat de variabele is ingesteld en dat de directory is gewijzigd. De controle achteraf laat zien dat de variabele niet is ingesteld en de map niet is gewijzigd. Wat is er gebeurd? De wijzigingen werden aangebracht in een nieuwe commandoregel. De huidige shell spawnde een nieuwe shell om het script uit te voeren. Het script wordt uitgevoerd in de nieuwe shell en alle wijzigingen in de omgeving worden van kracht in de nieuwe shell. Nadat het script klaar is, wordt de nieuwe shell vernietigd. Alle veranderingen aan de omgeving in de nieuwe shell worden vernietigd met de nieuwe shell. Alleen de uitvoertekst wordt in de huidige shell afgedrukt.
Nu sourcen we het bestand:
$ source myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir
Controleer de omgeving opnieuw:
$ env | grep FOO
FOO=foo
$ echo $PWD
/home/lesmana/somedir
De variabele FOO is ingesteld en de werkdirectory is gewijzigd.
Het sourcen van het script maakt geen nieuwe commandoregel aan. Alle commando’s worden uitgevoerd in de huidige shell en wijzigingen in de omgeving worden van kracht in de huidige shell.
Merk op dat in dit eenvoudige voorbeeld de uitvoer van het uitvoeren hetzelfde is als het sourcen van het script. Dit is niet noodzakelijkerwijs altijd het geval.
Beschouw het volgende script pid.sh
:
#!/bin/sh
echo $$
(de speciale variabele $$
expandeert tot de PID van het huidige draaiende shellproces)
Druk eerst de PID van de huidige shell af:
$ echo $$
25009
Bron het script:
$ source pid.sh
25009
Voer het script uit, noteer de PID:
$ ./pid.sh
25011
Bron opnieuw:
$ source pid.sh
25009
Voer opnieuw uit:
$ ./pid.sh
25013
Je kunt zien dat het sourcen van het script in hetzelfde proces draait, terwijl het uitvoeren van het script iedere keer een nieuw proces creëert. Dat nieuwe proces is de nieuwe commandoregel die is aangemaakt voor de uitvoering van het script. Sourcing van het script maakt geen nieuwe commandoregel aan en dus blijft de PID hetzelfde.
Zowel het sourcen als het uitvoeren van het script voert de commando’s in het script regel voor regel uit, alsof je die commando’s regel voor regel met de hand hebt ingetypt.
De verschillen zijn:
Gebruik source als je wilt dat het script de omgeving in je huidige shell verandert. Gebruik anders execute.
Zie ook:
Het uitvoeren van een script voert het uit in een apart child proces, dat wil zeggen dat een aparte instantie van shell wordt aangeroepen om het script te verwerken. Dit betekent dat omgevingsvariabelen etc., gedefinieerd in het script, niet kunnen worden bijgewerkt in de bovenliggende (huidige) shell.
Een script sourcen betekent dat het wordt geparsed en uitgevoerd door de huidige shell zelf. Het is alsof je de inhoud van het script intypt. Om deze reden hoeft het script dat gesourced wordt niet uitvoerbaar te zijn. Maar het moet natuurlijk wel uitvoerbaar zijn als je het uitvoert.
Als je positionele argumenten hebt in de huidige shell, blijven ze ongewijzigd.
Dus als ik een bestand a.sh
heb met daarin:
echo a $*
en ik doe:
$ set `date`
$ source ./a.sh
dan krijg ik zoiets als:
a Fri Dec 11 07:34:17 PST 2009
Overwegende dat:
$ set `date`
$ ./a.sh
geeft me:
a
Hoop dat dat helpt.
sourcen is in wezen hetzelfde als elke regel van het script één voor één intypen op de opdrachtprompt…
Execution start een nieuw proces en voert dan elke regel van het script uit, waarbij alleen de huidige omgeving wordt gewijzigd door wat het teruggeeft.
Met broncode krijg je alle extra variabelen die in het script gedefinieerd zijn.
Dus als je configs of functie definities hebt moet je sourcen en niet uitvoeren. Uitvoeringen zijn onafhankelijk van de omgeving van de ouders.
source
commando voert het geleverde script uit (uitvoerbare toestemming is niet verplicht ) in de huidige shell-omgeving, terwijl ./
het geleverde uitvoerbare script in een nieuwe shell uitvoert.
Bekijk ook dit antwoord als voorbeeld: https://superuser.com/a/894748/432100