一、首先举两个例子,
例子1. 假设有一个shell文件test.sh,
-
gwwu@hz-dev2.wgw.com:~/test/qos>cat test.sh
-
#!/bin/bash
-
A=123wgw
-
export A
在shell下运行该文件:
gwwu@hz-dev2.wgw.com:~/test/qos>chmod 777 test.sh
gwwu@hz-dev2.wgw.com:~/test/qos>./test.sh
gwwu@hz-dev2.wgw.com:~/test/qos>echo $A
//此处无任何输出。
gwwu@hz-dev2.wgw.com:~/test/qos>
例子2.假设test1.sh的内容如下:
-
gwwu@hz-dev2.aerohive.com:~/test/qos>cat test0.sh
-
#!/bin/bash
-
cd ..
在shell下运行该文件:
gwwu@hz-dev2.wgw.com:~/test/qos>chmod 777 test0.sh
gwwu@hz-dev2.wgw.com:~/test/qos>./test0.sh
gwwu@hz-dev2.wgw.com:~/test/qos> --------------------------此处目录没有任何变化
为啥这两个例子中通过执行shell脚本时,发现对应的环境变量和目录变化没有生效呢?
其实,当我们执行一个shell脚本的时候,首先当前shell会fork产生一个shell的子进程,然后在shell子进程中去执行命令,执行完了返回到当前shell。但是回到父shell后,子进程中修改的环境变量和路径信息不回影响到父shell进程。这也就解释了上面两个例子为啥没有任何改变了。
那有没有办法让执行的结果直接反应到当前shell上呢?
可以用source或者.(dot),明确告诉shell不要fork执行脚本,而是在当前的shell执行
使用source或者.(dot)命令后上面两个例子运行的结果
-
gwwu@hz-dev2.wgw.com:~/test/qos>source ./test.sh
-
gwwu@hz-dev2.wgw.com:~/test/qos>echo $A
-
123wgw
-
gwwu@hz-dev2.wgw.com:~/test/qos>source ./test0.sh
-
gwwu@hz-dev2.wgw.com:~/test>
二、习题
在学习了source和直接执行shell脚本的区别后,检验一下学习成果,看看以下例子的输出是多少?
-
gwwu@hz-dev2.wgw.com:~/test/shell>more 1.sh
-
#!/bin/bash
-
sleep 1
-
exit 1
-
gwwu@hz-dev2.wgw.com:~/test/shell>more test1.sh
-
#!/bin/bash
-
./1.sh
-
echo "can you see me"
-
gwwu@hz-dev2.wgw.com:~/test/shell>more test2.sh
-
#!/bin/bash
-
. ./1.sh
-
echo "can you see me"
在test1.sh中是直接运行shell脚本1.sh,它是通过fork子进程来执行脚本的。
而在test2.sh中是通过.(dot)运行脚本,它是直接在当前sehll下执行脚本。当其运行到1.sh中的exit 1时,当前shell退出,那么字符串"can you see me"就输出不了了。
运行结果:
-
gwwu@hz-dev2.wgw.com:~/test/shell>./test1.sh
-
can you see me
-
gwwu@hz-dev2.wgw.com:~/test/shell>./test2.sh
-
gwwu@hz-dev2.wgw.com:~/test/shell>
三、exec与source/fork的区别
exec也是让脚本在同一个进程上执行,但是原有进程就结束了。
简言之也就是:原有shell进程是否终止,是exec与source/fork的最大区别
下面这个例子可以帮助我们好好理解其中的区别:
-
gwwu@hz-dev2.wgw.com:~/test/shell>more 11.sh
-
#!/bin/bash
-
A=B
-
echo "ID for 11.sh before exec/source/fork$"
-
export A
-
echo "11.sh: \$A is $A"
-
case $1 in
-
exec)
-
echo "using exec..."
-
exec ./22.sh ;;
-
source)
-
echo "using source..."
-
. ./22.sh ;;
-
*)
-
echo "using fork by default..."
-
./22.sh ;;
-
esac
-
echo "ID for 11.sh after exec/source/fork$"
-
echo "11.sh: \$A is $A"
-
gwwu@hz-dev2.wgw.com:~/test/shell>more 22.sh
-
#!/bin/bash
-
echo "ID for 22.sh: $$" #$$表示运行脚本的进程ID
-
echo "22.sh get \$A=$A from 11.sh"
-
A=C
-
export A
-
echo "22.sh: \$A is $A"
运行结果:
-
gwwu@hz-dev2.wgw.com:~/test/shell>./11.sh fork
-
ID for 11.sh before exec/source/fork$
-
11.sh: $A is B
-
using fork by default...
-
ID for 22.sh: 20115
-
22.sh get $A=B from 11.sh
-
22.sh: $A is C
-
ID for 11.sh after exec/source/fork$
-
11.sh: $A is B
-
gwwu@hz-dev2.wgw.com:~/test/shell>./11.sh source
-
ID for 11.sh before exec/source/fork$
-
11.sh: $A is B
-
using source...
-
ID for 22.sh: 20116
-
22.sh get $A=B from 11.sh
-
22.sh: $A is C
-
ID for 11.sh after exec/source/fork$
-
11.sh: $A is C
-
gwwu@hz-dev2.wgw.com:~/test/shell>./11.sh exec
-
ID for 11.sh before exec/source/fork$
-
11.sh: $A is B
-
using exec...
-
ID for 22.sh: 20118
-
22.sh get $A=B from 11.sh
-
22.sh: $A is C
-
gwwu@hz-dev2.wgw.com:~/test/shell>
在这里对运行结果就不进行解释了,大家应该也都清楚了。
阅读(909) | 评论(0) | 转发(0) |