shell exit命令及父子进程的理解

实验

  1. 情形1
    直接在终端中执行exit:
$ exit 1

这时候,终端会直接退出(logout)。

  1. 情形2
    我们新建一个文件 test.sh,写上以下内容:
exit 1

然后再在终端中执行:

$ bash test.sh # 如果给予 test.sh 执行权限,然后执行 ./test.sh 效果是相同的

这时候,终端不退出,并且能够捕获上一次命令的执行状态:

$ echo $?

结果:1

  1. 情形3
    还是执行上述test.sh文件,但是我们不使用bash命令,而改用source命令:
source test.sh

结果:终端退出。

分析

情形1和情形2的区别在哪里呢?
为什么情形2终端不退出呢?

  1. 打开一个虚拟终端,将自动进入bash进程中,这个过程发生了什么?
    这应该是:操作系统新建一个“虚拟终端”进程,该进程 fork 一个bash进程。于是,我们就进入了bash进程环境。

  2. exit命令究竟是在做什么?
    它的作用是终止当前进程,并且将进程终止状态返回给父进程。

  3. bash中直接执行exit 1,发生了什么?

  • 我们首先要思考,bash进程开启之后,为什么没有自动退出,这一定是bash进程执行了一个while(1)循环,不然进程执行完所有语句,就退出了。
  • 这个while(1)循环在等待终端的输入,所以,当我们键入 “exit 1” 字符串,然后按下Enter之后,while(1)循环解析这个字符串,然后调用exit()函数退出当前进程,那么问题来了,当前进程是什么?当然是我们的bash进程。
  • bash进程退出,为什么终端也会退出呢?这取决于“虚拟终端”程序的逻辑,当然可以设定成:一旦子进程bash退出,父进程也退出。
  1. 如果我们执行 bash test.sh命令,发生了什么?
    这时候,bash进程会再次fork一个新的bash进程(暂命名为“bash2”),bash2进程再来解析这个 .sh 文件,当解析到 “exit 1” 字符串时,bash2进程退出。但是父进程bash依然存在,并且捕获到子进程的退出状态1

  2. 情形3验证了我们的第 4 点,因为source命令与bash命令不同,source会在当前的bash进程中直接解析 .sh 文件,而不是新开一个进程。

环境变量

在 shell 中运行一个新程序(不必是子 shell),是先 fork 一个子进程,然后使用 exec 将原先的二进制代码替换为新进程的程序。所以,shell 的普通变量无法在新进程中起作用。而环境变量则会将 shell 的环境变量复制一份到子进程中。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值