web-dev-qa-db-fra.com

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

Quelle est la différence entre sh et 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.

Et pour 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).
52
0x90

Lorsque vous appelez source (ou son alias .), vous insérer le script dans le processus bash en cours . Vous pouvez donc lire les variables définies par le script.

Lorsque vous appelez sh, vous lancez un fork (sous-processus) qui exécute une nouvelle session de /bin/sh, qui est généralement un lien symbolique vers bash. Dans ce cas, les variables d'environnement définies par le sous-script seraient supprimées à la fin du sous-script.

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

Un petit échantillon

Par exemple, si vous voulez changer répertoire de travail actuel d'une manière spécifique, vous ne pouvez 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

(J'ai écrit un petit échantillon de la fonction mycd .)

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.

Peu récursivité

cat <<eoqlvl >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.

Et un final test:

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

bash finalTest.sh 
Ending this.

source finalTest.sh
Ending this.

... Vous pouvez remarquer un comportement différent entre les deux syntaxes. ;-)

68
F. Hauri

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

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

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

Lisez le Advanced Bash Scripting Guide .

Cette différence n'est pas spécifique à Linux; chaque implémentation Posix l'aurait.

10

Comme d'autres l'ont mentionné, lorsque vous exécutez sh test.sh, toutes les modifications qui test.sh les modifications apportées à votre environnement Shell ne persisteront pas une fois le processus terminé.

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:

lap@my-ThinkPad:~$ cat test.sh
#!/bin/sh
cd /etc
lap@my-ThinkPad:~$ sh test.sh 
lap@my-ThinkPad:~$ pwd
/home/savoury
lap@my-ThinkPad:~$ source test.sh 
lap@my-ThinkPad:/etc$ pwd
/etc
lap@my-ThinkPad:/etc$ 
3
Will Vousden

Lorsque vous exécutez un programme avec la commande sh:

  • votre terminal utilisera sh ou Bourne Shell pour exécuter le programme.
  • un nouveau processus est créé car Bash fait une copie exacte de lui-même. ce processus enfant a le même environnement que son parent, seul le numéro d'identification du processus est différent. (ce processus appelé fourche)
  • vous devez avoir besoin d'une autorisation d'exécution pour l'exécuter (car il bifurque)

et lorsque vous utilisez la commande source:

  • vous exécutez le programme avec votre interprète par défaut
  • vous exécutez le processus dans votre terminal actuel (techniquement votre commande * nix interprétée)
  • Étant donné que le programme sera exécuté dans le terminal actuel, vous n'avez pas besoin de lui donner la permission d'exécution
1
Aria2end

source (ou.) - s'exécute à l'intérieur du shell actuel et change son attribut/environnement.

sh fait un fork et s'exécute dans un sous-shell et ne peut donc pas changer les attributs/l'environnement.

Par exemple

Mon script Shell est -

Elite12!rg6655:~/sh_pr [33]$ cat changeDir.sh
#!/bin/bash
cd /home/elt/rg6655/sh_pr/justdir
pwd
echo $$

Mon shell actuel -

Elite12!rg6655:~/sh_pr [32]$ echo $$
3272

L'ID de processus de mon shell actuel est 3272

Exécution avec la source -

Elite12!rg6655:~/sh_pr [34]$ source changeDir.sh
/home/elt/rg6655/sh_pr/justdir
3272
Elite12!rg6655:~/sh_pr/justdir

Observer deux choses - 1) L'ID de processus (3272) est le même que mon shell, ce qui confirme que la source s'exécute dans le shell actuel. 2) La commande cd a fonctionné et le répertoire a été changé en justdir.

Exécution avec sh -

Elite12!rg6655:~/sh_pr [31]$ sh changeDir.sh
/home/elt/rg6655/sh_pr/justdir
13673
Elite12!rg6655:~/sh_pr

Dans ce cas, l'ID de processus (13673) est différent et le répertoire reste le même, ce qui signifie qu'il s'exécute dans un processus ou sous-shell différent.

1
rg665n