LV100-子shell
一、子 shell?
上边的文件包含会把另一个脚本的内容复制到此脚本中执行,就很类似于 C 语言中的 include,还有其他方法可以执行其他脚本吗?还有以下两种方式:
- fork: 如果脚本有执行权限的话,path/to/foo.sh 。如果没有的话就这样:sh path/to/foo.sh。
- exec: exec path/to/foo.sh
这两种有什么特点?与上边的 source 有什么不同?我们来看一看吧
1. fork
1.1 使用格式
path/to/foo.sh # 有执行权限
sh path/to/foo.sh # 无执行权限执行方式:在主脚本中写所要调用脚本的路径,比如 /home/hk/1sharedfiles/6temp/file1.sh
特点:
(1)运行主脚本运行的的终端会新开一个子 shell 来执行脚本 first.sh;
(2)子 shell 执行的时候,父 shell 还在;
(3)子 shell 执行完毕后返回父 shell,子 shell 会继承父 shell 的环境变量,但是子 shell 中的环境变量不会带回父 shell
1.2 使用实例
- 主调 shell 脚本:file1.sh
#!/bin/bash
# filename: file1.sh
A=999
echo "before fork: PID for file1.sh = $$"
export A
echo "In file1.sh: variable file1_variable=$A"
echo -e "==>>> using fork start\n"
/home/hk/1sharedfiles/6temp/file2.sh
echo "after exec/source/fork: PID for file1.sh = $$"
echo -e "In file1.sh: variable file1_variable=$A\n"- 被调 shell 脚本:file2.sh
#!/bin/bash
# filename: file2.sh
echo "PID for file2.sh = $$"
echo "In for file2.sh get variable file1_variable=$A from file1.sh"
A=111
export A
echo -e "In for file2_variable.sh: variable for file2_variable=$A\n"- 执行结果如下
hk@ubuntu-22-04:~/1sharedfiles/6temp$ ./file1.sh
before fork: PID for file1.sh = 6773
In file1.sh: variable file1_variable=999
==>>> using fork start
PID for file2.sh = 6774
In for file2.sh get variable file1_variable=999 from file1.sh
In for file2_variable.sh: variable for file2_variable=111
after exec/source/fork: PID for file1.sh = 6773
In file1.sh: variable file1_variable=9992. exec
2.1 使用格式
exec script_path执行方式:exec + 脚本路径
特点:
(1)运行主脚本时不会新开一个子 shell 来执行被调用脚本 first.sh,被调用的脚本与主脚本在同一个 Shell 内执行,所以被调用的脚本中声明的变量和环境变量, 都可以在主脚本中进行获取和使用。
(2)使用 exec 调用一个新脚本以后, 父脚本中 exec 行之后的内容就不会再执行。
2.2 使用实例
- 主调 shell 脚本:file1.sh
#!/bin/bash
# filename: file1.sh
A=999
echo "before fork: PID for file1.sh = $$"
export A
echo "In file1.sh: variable file1_variable=$A"
echo -e "==>>> using fork start\n"
exec /home/hk/1sharedfiles/6temp/file2.sh
echo "after exec/source/fork: PID for file1.sh = $$"
echo -e "In file1.sh: variable file1_variable=$A\n"- 被调 shell 脚本:file2.sh
#!/bin/bash
# filename: file2.sh
echo "PID for file2.sh = $$"
echo "In for file2.sh get variable file1_variable=$A from file1.sh"
A=111
export A
echo -e "In for file2_variable.sh: variable for file2_variable=$A\n"- 执行结果如下
hk@ubuntu-22-04:~/1sharedfiles/6temp$ ./file1.sh
before fork: PID for file1.sh = 6808
In file1.sh: variable file1_variable=999
==>>> using fork start
PID for file2.sh = 6808
In for file2.sh get variable file1_variable=999 from file1.sh
In for file2_variable.sh: variable for file2_variable=1113. source
与 fork 的区别是不新开一个子 Shell 来执行被调用的脚本,而是在同一个 Shell 中执行. 所以被调用的脚本中声明的变量和环境变量, 都可以在主脚本中进行获取和使用。
其实从命名上可以感知到其中的细微区别,下面通过两个脚本来体会三种调用方式的不同:
3.1 使用格式
source script_path
. script_path执行方式:source(或者 . ) + 脚本路径
特点:
(1)同 exec 的特点(1)即运行主脚本时不会新开一个子 shell 来执行被调用脚本 file2.sh,被调用的脚本与主脚本在同一个 shell 内执行。
(2)使用 source 调用一个新脚本以后, 主脚本中 exec 行之后的内容还会执行。
(3)被调用的脚本中声明的变量和环境变量, 都可以在主脚本中进行获取和使用。
3.2 使用实例
- 主调 shell 脚本:file1.sh
#!/bin/bash
# filename: file1.sh
A=999
echo "before fork: PID for file1.sh = $$"
export A
echo "In file1.sh: variable file1_variable=$A"
echo -e "==>>> using fork start\n"
. /home/hk/1sharedfiles/6temp/file2.sh
echo "after exec/source/fork: PID for file1.sh = $$"
echo -e "In file1.sh: variable file1_variable=$A\n"- 被调 shell 脚本:file2.sh
#!/bin/bash
# filename: file2.sh
echo "PID for file2.sh = $$"
echo "In for file2.sh get variable file1_variable=$A from file1.sh"
A=111
export A
echo -e "In for file2_variable.sh: variable for file2_variable=$A\n"- 执行结果如下
hk@ubuntu-22-04:~/1sharedfiles/6temp$ ./file1.sh
before fork: PID for file1.sh = 6840
In file1.sh: variable file1_variable=999
==>>> using fork start
PID for file2.sh = 6840
In for file2.sh get variable file1_variable=999 from file1.sh
In for file2_variable.sh: variable for file2_variable=111
after exec/source/fork: PID for file1.sh = 6840
In file1.sh: variable file1_variable=1114. ()括号
() 可以用来创建子shell,这样在子 shell中执行命令,不会影响当前 shell 的环境(目录、环境变量等)。常用于临时改变环境而不影响当前 shell。
# 圆括号会创建一个子 shell 来执行其中的命令
(
cd /tmp
echo "当前目录: $(pwd)"
var="子 shell 中的变量"
)
# 父 shell 的环境不受影响
echo "回到原目录: $(pwd)" # 仍在原目录
echo "var = $var" # 空,因为 var 在子 shell 中定义