Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between using `sh` and `source`?

What is the difference between sh and 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. 

And for 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). 
like image 929
0x90 Avatar asked Dec 09 '12 10:12

0x90


People also ask

What is the difference between source and sh commands?

What is the difference between sh and 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.

What is the difference between executing a bash script vs sourcing it?

Sourcing a script will run the commands in the current shell process. Changes to the environment take effect in the current shell. Executing a script will run the commands in a new shell process.

What is source script sh?

source script.sh runs the script within the current process, thus all variable assignments are preserved as variables even after the script finishes (and don't have to be explicitly export 'd). ./script.sh just runs the script in a subprocess, and any variables which are assigned disappear after the script is done.

What is difference between source and bash?

There is a post Using source vs bash commands, which attempted to explain, but I could not clarify if the responder tried to say "source" ignores past definition and sets environment variables in current shell or bash ignores past definition and sets environment variables in current shell.


1 Answers

When you call source or . (the one is an alias to the other. source cmd not POSIX - kind of bashism), you load and execute a bash script into the current bash process. So you can

  • read variables set in the sourced script,
  • use functions defined within it.
  • and even execute forks and/or subprocess if script do this.

When you call sh, you initiate a fork (sub-process or child) that runs a new session of /bin/sh, which is usually a symbolic link to bash. In this case, environment variables set by the sub-script would be dropped when the sub-script finishes.

Caution: sh could be a symlink to another shell.

Practical sample

For example, if you want to change current working directory by a specific manner, you could not do

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

This won't do what you expect:

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

because current working dir is part of environment and myCd2Doc.sh would run in a subshell.

But:

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

Have a look at mycd function!! (With bash completion based on Associative Array).

Execution level $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. 

Recursion (when a script run from itself)

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

A little futher

$ 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 

( Current PID ($$ == process Id) are same identifier than SID (session ID). It's not alway true.)

$ ./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 

Dot . is an alias of source. So the only difference between two command are slash replaced by space.

And a final test:

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

... You may notice a different behaviour between the two syntaxes. ;-)

like image 100
F. Hauri Avatar answered Sep 20 '22 04:09

F. Hauri