Chinaunix首页 | 论坛 | 博客
  • 博客访问: 534956
  • 博文数量: 142
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1452
  • 用 户 组: 普通用户
  • 注册时间: 2013-09-12 16:28
文章分类

全部博文(142)

文章存档

2016年(10)

2015年(60)

2014年(72)

我的朋友

分类: LINUX

2015-01-05 10:35:56

一、首先举两个例子,
例子1. 假设有一个shell文件test.sh,

点击(此处)折叠或打开

  1. gwwu@hz-dev2.wgw.com:~/test/qos>cat test.sh
  2. #!/bin/bash
  3. A=123wgw
  4. 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的内容如下:

点击(此处)折叠或打开

  1. gwwu@hz-dev2.aerohive.com:~/test/qos>cat test0.sh
  2. #!/bin/bash
  3. 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)命令后上面两个例子运行的结果

点击(此处)折叠或打开

  1. gwwu@hz-dev2.wgw.com:~/test/qos>source ./test.sh
  2. gwwu@hz-dev2.wgw.com:~/test/qos>echo $A
  3. 123wgw
  4. gwwu@hz-dev2.wgw.com:~/test/qos>source ./test0.sh
  5. gwwu@hz-dev2.wgw.com:~/test>
二、习题
在学习了source和直接执行shell脚本的区别后,检验一下学习成果,看看以下例子的输出是多少?

点击(此处)折叠或打开

  1. gwwu@hz-dev2.wgw.com:~/test/shell>more 1.sh
  2. #!/bin/bash
  3. sleep 1
  4. exit 1
  5. gwwu@hz-dev2.wgw.com:~/test/shell>more test1.sh
  6. #!/bin/bash
  7. ./1.sh
  8. echo "can you see me"
  9. gwwu@hz-dev2.wgw.com:~/test/shell>more test2.sh
  10. #!/bin/bash
  11. . ./1.sh
  12. echo "can you see me"
在test1.sh中是直接运行shell脚本1.sh,它是通过fork子进程来执行脚本的。
而在test2.sh中是通过.(dot)运行脚本,它是直接在当前sehll下执行脚本。当其运行到1.sh中的exit 1时,当前shell退出,那么字符串"can you see me"就输出不了了。
运行结果:

点击(此处)折叠或打开

  1. gwwu@hz-dev2.wgw.com:~/test/shell>./test1.sh
  2. can you see me
  3. gwwu@hz-dev2.wgw.com:~/test/shell>./test2.sh
  4. gwwu@hz-dev2.wgw.com:~/test/shell>

三、exec与source/fork的区别
exec也是让脚本在同一个进程上执行,但是原有进程就结束了。
简言之也就是:原有shell进程是否终止,是exec与source/fork的最大区别
下面这个例子可以帮助我们好好理解其中的区别:

点击(此处)折叠或打开

  1. gwwu@hz-dev2.wgw.com:~/test/shell>more 11.sh
  2. #!/bin/bash
  3. A=B
  4. echo "ID for 11.sh before exec/source/fork$"
  5. export A
  6. echo "11.sh: \$A is $A"
  7. case $1 in
  8.     exec)
  9.         echo "using exec..."
  10.         exec ./22.sh ;;
  11.     source)
  12.         echo "using source..."
  13.         . ./22.sh ;;
  14.     *)
  15.         echo "using fork by default..."
  16.         ./22.sh ;;
  17. esac
  18. echo "ID for 11.sh after exec/source/fork$"
  19. echo "11.sh: \$A is $A"
  20. gwwu@hz-dev2.wgw.com:~/test/shell>more 22.sh
  21. #!/bin/bash
  22. echo "ID for 22.sh: $$"   #$$表示运行脚本的进程ID
  23. echo "22.sh get \$A=$A from 11.sh"
  24. A=C
  25. export A
  26. echo "22.sh: \$A is $A"
运行结果:

点击(此处)折叠或打开

  1. gwwu@hz-dev2.wgw.com:~/test/shell>./11.sh fork
  2. ID for 11.sh before exec/source/fork$
  3. 11.sh: $A is B
  4. using fork by default...
  5. ID for 22.sh: 20115
  6. 22.sh get $A=B from 11.sh
  7. 22.sh: $A is C
  8. ID for 11.sh after exec/source/fork$
  9. 11.sh: $A is B
  10. gwwu@hz-dev2.wgw.com:~/test/shell>./11.sh source
  11. ID for 11.sh before exec/source/fork$
  12. 11.sh: $A is B
  13. using source...
  14. ID for 22.sh: 20116
  15. 22.sh get $A=B from 11.sh
  16. 22.sh: $A is C
  17. ID for 11.sh after exec/source/fork$
  18. 11.sh: $A is C
  19. gwwu@hz-dev2.wgw.com:~/test/shell>./11.sh exec
  20. ID for 11.sh before exec/source/fork$
  21. 11.sh: $A is B
  22. using exec...
  23. ID for 22.sh: 20118
  24. 22.sh get $A=B from 11.sh
  25. 22.sh: $A is C
  26. gwwu@hz-dev2.wgw.com:~/test/shell>

在这里对运行结果就不进行解释了,大家应该也都清楚了。

阅读(855) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~