使用“sh”和“source”有什么区别?
- 2024-10-11 08:36:00
- admin 原创
- 76
问题描述:
sh
和有什么区别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.
对于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).
解决方案 1:
当你调用source
或.
(一个是另一个的别名。cmdsource
不是 POSIX - 一种bashism )时,你将在当前shell 进程中加载并执行一个 shell 脚本。所以你可以
读取源脚本中设置的变量,
使用其中定义的函数。
如果脚本执行此操作,甚至会执行 fork 和/或子进程。
当您调用 时sh
,您将启动一个fork(子进程或子进程),该进程将运行 的新会话/bin/sh
(通常是 的符号链接bash
)。在这种情况下,子脚本设置的环境变量将在子脚本终止时被删除。
警告:可能是另一个sh
符号链接 壳。
实际示例
例如,如果你想通过特定方式更改当前工作目录,你不能这样做
$ cat <<eof >myCd2Doc.sh
#!/bin/sh
cd /usr/share/doc
eof
$ chmod +x myCd2Doc.sh
这不会达到你所期望的效果:
$ cd /tmp
$ pwd
/tmp
$ ~/myCd2Doc.sh
$ pwd
/tmp
因为当前工作目录是环境的一部分并且将在子 shellmyCd2Doc.sh
中运行。
但:
$ source ~/myCd2Doc.sh
$ pwd
/usr/share/doc
相同,声明一个函数:
$ cat >~/myCd2Doc.source <<eof
# Shell source file
myCd2Doc() {
cd /usr/share/doc
}
eof
$ . ~/myCd2Doc.source
$ cd /tmp
$ pwd
/tmp
$ myCd2Doc
$ pwd
/usr/share/doc
看看mycd
函数!(使用狂欢基于关联数组的完成)。
执行级别$SHLVL
$ cd /tmp
printf %b '#!/bin/bash
echo This is level $SHLVL.
' >qlvl.sh
$ bash qlvl.sh
This is level 2.
$ source qlvl.sh
This is level 1.
递归(当脚本从自身运行时)
$ 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.
再远一点
$ 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($$
==进程 ID)与SID(会话 ID)是相同的标识符。这并不总是正确的。)
$ ./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
点.
是 的别名source
。因此两个命令之间的唯一区别被slash
取代space
。
最后一个测试:
$ printf %b '#!/bin/bash
echo Ending this.
sle' \n 'ep 1;exit 0
' >finalTest.sh
$ bash finalTest.sh
Ending this.
$ source finalTest.sh
Ending this.
...您可能会注意到两种语法之间的不同行为。;-)
解决方案 2:
主要区别在于它们是在不同的进程中执行的。
因此如果你的source
文件foo
执行了cd
,源 shell(例如终端中的交互式 shell)会受到影响(并且其当前目录将会改变)
如果你执行sh foo
不会cd
影响源 shell,只有新创建的sh
进程运行foo
阅读高级 Bash 脚本指南。
这种差异并非 Linux 所特有;每个 Posix 实现都会有这种差异。
解决方案 3:
正如其他人所提到的,当您运行时sh test.sh
,对您的 shell 环境所做的任何更改test.sh
在该过程结束后都不会保留。
test.sh
不过,还请注意,当作为子进程执行(即使用)时,环境中未导出的任何元素(例如变量、别名和 shell 函数)都将无法供代码使用sh test.sh
。
例如:
$ cat > test.sh
echo $foo
$ foo=bar
$ sh test.sh
$ . test.sh
bar
示例 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$
解决方案 4:
source(或 . ) - 在当前 shell 内运行并改变其属性/环境。
sh执行 fork 并在子 shell 中运行,因此无法改变属性/环境。
例如
我的 shell 脚本是 -
elite12!rg6655:~/sh_pr [33]$ cat changeDir.sh
#!/bin/bash
cd /home/elt/rg6655/sh_pr/justdir
pwd
echo $$
我当前的 Shell -
elite12!rg6655:~/sh_pr [32]$ echo $$
3272
我当前 shell 的进程 ID 是 3272
使用源代码运行-
elite12!rg6655:~/sh_pr [34]$ source changeDir.sh
/home/elt/rg6655/sh_pr/justdir
3272
elite12!rg6655:~/sh_pr/justdir
观察两件事 - 1)进程 ID(3272)与我的 shell 相同,这确认源在当前 shell 中执行。2)cd 命令有效并且目录更改为 justdir。
使用sh运行-
elite12!rg6655:~/sh_pr [31]$ sh changeDir.sh
/home/elt/rg6655/sh_pr/justdir
13673
elite12!rg6655:~/sh_pr
在这种情况下,进程 ID(13673)不同而目录保持不变,这意味着它在不同的进程或子 shell 中运行。
解决方案 5:
当您使用 sh 命令执行程序时:
您的终端将使用 sh 或 Bourne Shell 来执行该程序。
由于 Bash 对自身进行了精确复制,因此会创建一个新进程。此子进程与其父进程具有相同的环境,只有进程 ID 号不同。(此过程称为分叉)
您需要具有执行权限才能执行它(因为它是分叉的)
当您使用 source 命令时:
使用默认解释器执行程序
您在当前终端中执行该过程(从技术上讲,您的 *nix 命令被解释)
由于该程序将在当前终端中执行,因此您无需授予其执行权限
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件