GNU/Linux >> Tutoriels Linux >  >> Linux

Quelle est la différence entre utiliser `sh` et `source` ?

La principale différence est qu'ils sont exécutés dans un processus différent.

Donc, si vous source un fichier foo qui fait un cd , le sourcing shell (par exemple votre shell interactif dans le terminal) est affecté (et son répertoire courant va changer)

Si vous exécutez sh foo le cd n'affecte pas le sourcing shell, seulement le sh fraîchement créé processus exécutant foo

Lisez le Guide de création de scripts avancés pour Bash.


Comme d'autres l'ont mentionné, lorsque vous exécutez sh test.sh , toute modification test.sh les modifications apportées à votre environnement shell ne persisteront pas après la fin du processus.

Cependant, notez également que tout élément de votre environnement qui n'est pas exporté (par exemple, les variables, les alias et les fonctions shell) ne sera pas disponible pour le code dans test.sh lorsqu'il est exécuté en tant que sous-processus (c'est-à-dire avec sh test.sh ).

Par exemple :

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

Exemple 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$ 

Lorsque vous appelez le source ou . (l'un est un alias de l'autre. source cmd pas POSIX - une sorte de bashisme ), vous chargez et exécutez un script shell dans le courant processus shell . Vous pouvez donc

  • lire les variables définies dans le script sourcé,
  • utiliser les fonctions qui y sont définies.
  • et même exécuter des forks et/ou des sous-processus si le script le fait.

Lorsque vous appelez le sh , vous lancez un fork (sous-processus ou enfant ) qui exécute une nouvelle session de /bin/sh (qui est souvent un lien symbolique vers bash ). Dans ce cas, les variables d'environnement définies par le sous-script seraient supprimées lorsque le sous-script se terminerait.

Attention :sh pourrait être un lien symbolique vers un autre coque.

Exemple pratique

Par exemple, si vous souhaitez modifier le répertoire de travail actuel d'une manière spécifique, vous ne pourriez pas faire

$ cat <<eof >myCd2Doc.sh
#!/bin/sh
cd /usr/share/doc
eof

$ chmod +x myCd2Doc.sh

Cela ne fera pas ce que vous attendez :

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

car répertoire de travail actuel fait partie de l'environnement et myCd2Doc.sh s'exécuterait dans un sous-shell .

Mais :

$ cat >myCd2Doc.source <<eof
# Shell source file
myCd2Doc() {
    cd /usr/share/doc
}
eof

$ . myCd2Doc.source
$ cd /tmp
$ pwd
/tmp
$ myCd2Doc
$ pwd
/usr/share/doc

Jetez un œil à mycd fonction!! (Avec complétion bash basée sur Associative Array ).

Niveau d'exécution $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.

Récursivité (lorsqu'un script s'exécute à partir de lui-même)

$ cat <<eoqlvl2 >qlvl2.sh 
#!/bin/bash

export startLevel recursionLimit=5
echo This is level $SHLVL started:${startLevel:=$SHLVL}.
(( SHLVL < recursionLimit )) && ./qlvl2.sh
eoqlvl2
$ chmod +x qlvl2.sh

$ ./qlvl2.sh 
This is level 2 started:2.
This is level 3 started:2.
This is level 4 started:2.
This is level 5 started:2.

$ source qlv2.sh 
This is level 1 started:1.
This is level 2 started:1.
This is level 3 started:1.
This is level 4 started:1.
This is level 5 started:1.

Un peu plus loin

$ sed '$a ps --sid $SID fw' qlvl.sh >qlvl3.sh
$ chmod +x qlvl3.sh 
$ export SID
$ read SID < <(ps ho sid $$)
$ echo $SID $$
8983 8983

PID actuel ($$ ==identifiant de processus ) sont le même identifiant que SID (identifiant de session ). Ce n'est pas toujours vrai.)

$ ./qlvl3.sh 
This is level 2.
  PID TTY      STAT   TIME COMMAND
 8983 pts/10   Ss     0:00 /bin/bash
10266 pts/10   S+     0:00  \_ /bin/bash ./qlvl3.sh
10267 pts/10   R+     0:00      \_ ps --sid 8983 fw

$ . qlvl3.sh 
This is level 1.
  PID TTY      STAT   TIME COMMAND
 8983 pts/10   Ss     0:00 /bin/bash
10428 pts/10   R+     0:00  \_ ps --sid 8983 fw

Point . est un alias de source . Donc, la seule différence entre deux commandes est slash remplacé par space .

Et une finale tester :

$ printf %b '\43\41/bin/bash\necho Ending this.\nsle' \
    'ep 1;exit 0\n' >finalTest.sh

$ bash finalTest.sh 
Ending this.

$ source finalTest.sh
Ending this.

... Vous remarquerez peut-être un différent comportement entre les deux syntaxes.;-)


Linux
  1. Quelle est la différence entre strtok_r et strtok_s en C ?

  2. Quelle est la différence entre fsck et e2fsck ?

  3. Quelle est la différence entre ls et l ?

  4. Quelle est la différence entre `su -` et `su --login` ?

  5. Quelle est la différence entre la route et la route IP ?

Quelle est la différence entre InnoDB et MyISAM ?

Quelle est la différence entre Linux et Unix ?

Quelle est la différence entre la connexion et le shell sans connexion

Quelle est la différence entre la commande apt et apt-get ?

Qu'est-ce qu'un Hyperviseur ? Quelle est la différence entre les types 1 et 2 ?

Quelle est la différence entre curl et Wget ?