转:linux中fork, source和exec的区别

shell的命令可以分为内部命令和外部命令. 内部命令是由特殊的文件格式.def实现的,如cd,ls等.而外部命令是通过系统调用或独立程序实现的,如awk,sed. source和exec都是内部命令.

fork
   使用 fork 方式运行 script 时, 就是让 shell(parent process) 产生一个 child process 去执行该 script, 当 child process 结束后, 会返回 parent process,但 parent process 的环境是不会因 child process 的改变而改变的.

source
   使用 source 方式运行 script 时, 就是让 script 在当前 process 内执行, 而不是产生一个 child process 来执行. 由于所有执行结果均于当前 process 内完成,若 script 的环境有所改变, 当然也会改变当前 process 环境了.
source ./my.sh 或 . ./my.sh
 
exec
   使用 exec 方式运行script时, 它和 source 一样, 也是让 script 在当前process内执行, 但是 process 内的原代码剩下部分将被终止. 同样, process 内的环境随script 改变而改变.

结论:通常如果我们执行时,都是默认为fork的。大家可以通过pstree命令看看关于父子进程的关系。如上,如果想让父进程得到子进程的环境变量,就是source方式了

* fork ( /directory/script.sh)
    fork是最普通的, 就是直接在脚本里面用/directory/script.sh来调用script.sh这个脚本.运行的时候开一个sub-shell执行调用的脚 本,sub-shell执行的时候, parent-shell还在。sub-shell执行完毕后返回parent-shell. sub-shell从parent-shell继承环境变量.但是sub-shell中的环境变量不会带回parent-shell
* source (source /directory/script.sh)
   与fork的区别是不新开一个sub-shell来执行被调用的脚本,而是在同一个shell中执行. 所以被调用的脚本中声明的变量和环境变量, 都可以在主脚本中得到和使用.
* exec (exec /directory/script.sh)
    exec与fork不同,不需要新开一个sub-shell来执行被调用的脚本. 被调用的脚本与父脚本在同一个shell内执行。但是使用exec调用一个新脚本以后, 父脚本中exec行之后的内容就不会再执行了。这是exec和source的区别

exp:

1.sh 
代码:

#!/bin/bash
A=B
echo "PID for 1.sh before exec/source/fork: $$"
export A
echo "1.sh: \$A is $A"
case $ in
exec)
echo "using exec..."
exec ./.sh ;;
source)
echo "using source..."
. ./.sh ;;
*)
echo "using fork by default..."
./.sh ;;
esac
echo "PID for 1.sh after exec/source/fork: $$"
echo "1.sh: \$A is $A"

2.sh 
代码:

#!/bin/bash
echo "PID for 2.sh: $$"
echo "2.sh get \$A=$A from 1.sh"
A=C
export A
echo "2.sh: \$A is $A"

然后,分別跑如下参数来观察结果: 
$ ./1.sh fork 
$ ./1.sh source 
$ ./1.sh exec

#fork下主进程(PID:)环境变量为改变,并且子进程(PID:)执行完毕后回到主进程
[root@localhost ~]# ./.sh fork
PID for .sh before exec/source/fork:
.sh: $A is B
using fork by default...
PID for .sh:
.sh get $A=B from .sh
.sh: $A is C
PID for .sh after exec/source/fork:
.sh: $A is B #source下进程环境变量改变,.sh和2.sh的PID均为8530,表明在同一进程下执行
[root@localhost ~]# ./.sh source
PID for .sh before exec/source/fork:
.sh: $A is B
using source...
PID for .sh:
.sh get $A=B from .sh
.sh: $A is C
PID for .sh after exec/source/fork:
.sh: $A is C #exec下环境变量改变;.sh和2.sh的PID虽然一样,但是执行2.sh完毕后,并没有回到原进程中继续执行剩余代码;可见主脚本在调用执行exec之后就退出了,余下代码也不会被执行了。
[root@localhost ~]# ./.sh exec
PID for .sh before exec/source/fork:
.sh: $A is B
using exec...
PID for .sh:
.sh get $A=B from .sh
.sh: $A is C

***********************************************************

学习永远不晚。——高尔基

***********************************************************

linux中fork, source和exec的区别的更多相关文章

  1. 用 set follow-fork-mode child即可。这是一个 gdb 命令,其目的是告诉 gdb 在目标应用调用fork之后接着调试子进程而不是父进程,因为在 Linux 中fork系统调用成功会返回两次,一次在父进程,一次在子进程

    GDB的那些奇淫技巧 evilpan 收录于 Security  2020-09-13  约 5433 字   预计阅读 11 分钟  709 次阅读  gdb也用了好几年了,虽然称不上骨灰级玩家,但 ...

  2. Linux中fork的秘密

    linux中fork()函数详解         一.fork入门知识 一个进程,包括代码.数据和分配给进程的资源.fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以 ...

  3. Linux中yum和apt-get用法及区别

    Linux中yum和apt-get用法及区别   一般来说著名的linux系统基本上分两大类:   1.RedHat系列:Redhat.Centos.Fedora等   2.Debian系列:Debi ...

  4. 【转】linux 中fork()函数详解

    在看多线程的时候看到了这个函数,于是学习了下,下面文章写的通俗易懂,于是就开心的看完了,最后还是很愉快的算出了他最后一个问题. linux 中fork()函数详解 一.fork入门知识 一个进程,包括 ...

  5. Linux中fork()函数详解(转载)

    linux中fork()函数详解 一.fork入门知识 一个进程,包括代码.数据和分配给进程的资源.fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事, ...

  6. linux中软链接和硬链接的区别与小结

    ln命令 该命令在文件之间创建链接.这种操作实际上是给系统中已有的某个文件指定另外一个可用于访问它的名称.对于这个新的文件名,我们可以为之指定不同的访问权限,以控制对信息的共享和安全性的问题. 如果链 ...

  7. 线程创建,属性设置与获得,等待线程结束,线程中fork,以及执行exec()

    这篇博客的形式我想以分析代码不同情况为主: 点击(此处)折叠或打开 #include<stdio.h> #include<pthread.h> #include<time ...

  8. linux中fork创建进程讲解(转)

    大家知道Linux中创建子进程的一个很好的方法是函数调用fork,但是很多初学者对fork的理解上可能有点困难.我们举个例子来看看fork的用法吧.         大家用fork的时候记住fork是 ...

  9. linux中软连接和硬链接的区别

    linux中创建软连接和硬链接的方法: 软连接: ln -s oldfile slink 硬连接: ln oldfile hlink linux中创建软连接和硬链接的区别:        原理上,硬链 ...

随机推荐

  1. typescritp 导出默认接口

    假如有ITest.ts文件,如下: export default interface ITest{ } 这样会报错,编译不通过.据说是设计成这样的,具体详细见:https://github.com/M ...

  2. Spring Boot 静态页面

    spring boot项目只有src目录,没有webapp目录,会将静态访问(html/图片等)映射到其自动配置的静态目录,如下 /static /public /resources /META-IN ...

  3. 高通 sensor 从native到HAL

    app注册传感器监听 Android Sensor Framework 的整体架构如下图所示: 前几篇sensor相关的文章介绍了sensor的hal的知识,以press_sensor实时显示气压坐标 ...

  4. python UDP套接字通信

    UDPserver.py import socket #导入套接字模块 s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # - socket.A ...

  5. java基础-温故而知新(02)

    基本数据的自动拆装箱及享元设计模式 1.1 自动装箱        -128~127 之间的整数,装在一个内存区域.         超过这个范围的整数,装在不同的内存区域. 1.2 自动拆箱     ...

  6. Alpha冲刺! Day3 - 砍柴

    Alpha冲刺! Day3 - 砍柴 今日已完成 晨瑶:补充安卓技能树: review接口文档:看了点七牛云安卓API. 昭锡:没有团队项目相关贡献. 永盛: API 文档基本完成:根据 API 文档 ...

  7. selenium 初探

    # -*- coding:utf-8 -*- from selenium import webdriver driver = webdriver.Firefox() # 打开firefox浏览器 dr ...

  8. ES5-ES6-ES7_const声明只读常量

    const 概述const声明一个只读的常量.一旦声明,常量的值就不能改变.const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值. // const P ...

  9. [题目] Luogu P5038 [SCOI2012]奇怪的游戏

    学习资料 -----1----- -----2----- P5038 [SCOI2012]奇怪的游戏 一道甚神但没用到高深模型的题 思路 没思路,看题解吧 代码 #include <iostre ...

  10. MDC的使用(Mapped Diagnostic Context)的使用

    通常我们可能会有大量的任务需要提交提交到线程池执行,但是此时如果不对日志添加唯一标识进行区分的话回到错乱一坨无法进行查看.因此可以对每一天日志添加唯一的标识,例如使用userid作为日志的唯一标志.这 ...