Qual è la differenza tra l’uso di `sh` e` source`?

Qual è la differenza tra sh e source ?

 source: source filename [arguments] Read and execute commands from FILENAME and return. The pathnames in $PATH are used to find the directory containing FILENAME. If any ARGUMENTS are supplied, they become the positional parameters when FILENAME is executed. 

E per l’ man sh :

 NAME bash - GNU Bourne-Again SHell SYNOPSIS bash [options] [file] COPYRIGHT Bash is Copyright (C) 1989-2004 by the Free Software Foundation, Inc. DESCRIPTION Bash is an sh-compatible command language interpreter that executes commands read from the standard input or from a file. Bash also incorporates useful features from the Korn and C shells (ksh and csh). Bash is intended to be a conformant implementation of the IEEE POSIX Shell and Tools specification (IEEE Working Group 1003.2). 

Quando chiami source (o il suo alias), inserisci lo script nel processo bash corrente . Quindi puoi leggere le variabili impostate dallo script.

Quando chiami sh , inizi un fork (processo secondario) che esegue una nuova sessione di /bin/sh , che di solito è un link simbolico a bash . In questo caso, le variabili di ambiente impostate dal sotto-script verrebbero eliminate al termine del sub-script.

Attenzione : sh potrebbe essere un link simbolico a un’altra shell.

Un piccolo campione

Ad esempio, se si desidera modificare la directory di lavoro corrente in un modo specifico, non è ansible

 cat <myCd2Doc.sh #!/bin/sh cd /usr/share/doc eof chmod +x myCd2Doc.sh 

Questo non farà quello che ti aspetti:

 cd /tmp pwd /tmp ~/myCd2Doc.sh pwd /tmp 

poiché la myCd2Doc.sh lavoro corrente è parte dell’ambiente e myCd2Doc.sh dovrebbe essere eseguito in una sottoshell .

Ma:

 cat >myCd2Doc.source < 

(Ho scritto un piccolo esempio di funzione mycd .)

Livello di esecuzione $SHLVL

 cd /tmp printf %b '\43\41/bin/bash\necho This is level \44SHLVL.\n' >qlvl.sh bash qlvl.sh This is level 2. source qlvl.sh This is level 1. 

Piccola ricorsione

 cat <qlvl.sh #!/bin/bash export startLevel echo This is level $SHLVL starded:${startLevel:=$SHLVL}. ((SHLVL<5)) && ./qlvl.sh eoqlvl chmod +x qlvl.sh ./qlvl.sh This is level 2 starded:2. This is level 3 starded:2. This is level 4 starded:2. This is level 5 starded:2. source qlvl.sh This is level 1 starded:1. This is level 2 starded:1. This is level 3 starded:1. This is level 4 starded:1. This is level 5 starded:1. 

E un test finale :

 printf %b '\43\41/bin/bash\necho Ending this.\nexit 0\n' >finalTest.sh bash finalTest.sh Ending this. source finalTest.sh Ending this. 

... Potresti notare un comportamento diverso tra entrambe le syntax. 😉

La differenza principale è che vengono eseguiti in un processo diverso.

Quindi se si source un file foo che fa un cd , la shell di sourcing (ad esempio la shell intertriggers nel terminale) è interessata (e la sua directory corrente cambierà)

Se esegui sh foo il cd non influenza la shell di sourcing, solo il processo sh appena creato sta funzionando

Leggi la Guida avanzata di scripting di Bash .

Questa differenza non è specifica per Linux; ogni implementazione Posix lo avrebbe

Come altri hanno menzionato, quando si esegue sh test.sh , qualsiasi modifica apportata da test.sh all’ambiente di shell non verrà mantenuta dopo la fine del processo.

Tuttavia, si noti anche che qualsiasi elemento dell’ambiente che non viene esportato (ad es. Variabili, alias e funzioni shell) non sarà disponibile per il codice in test.sh quando viene eseguito come sottoprocesso (cioè con sh test.sh ).

Per esempio:

 $ cat > test.sh echo $foo $ foo=bar $ sh test.sh $ . test.sh bar 

Esempio 2:

 [email protected]:~$ cat test.sh #!/bin/sh cd /etc [email protected]:~$ sh test.sh [email protected]:~$ pwd /home/savoury [email protected]:~$ source test.sh [email protected]:/etc$ pwd /etc [email protected]:/etc$ 

Quando esegui un programma con il comando sh:

  • il terminale utilizzerà sh o Bourne Shell per eseguire il programma.
  • viene creato un nuovo processo perché Bash crea una copia esatta di se stesso. questo processo figlio ha lo stesso ambiente del suo genitore, solo il numero ID del processo è diverso. (questo processo ha chiamato biforcazione)
  • è necessario avere il permesso di esecuzione per eseguirlo (dato che sta forando)

e quando usi il comando sorgente:

  • si esegue il programma con l’interprete predefinito
  • si esegue il processo nel terminale corrente (tecnicamente il comando * nix è stato interpretato)
  • Poiché il programma verrà eseguito nel terminale corrente, non è necessario concedere il permesso di esecuzione