深入理解linux shell 中的exec内置命令&ubuntu bash

概览

每当我们在Bash shell 中运行任何命令时,默认情况下都会创建一个子 shell,并生成(分叉)一个新的子进程来执行该命令。但是,当使用 exec时,exec 后面的命令将替换当前 shell。这意味着不会创建任何子 shell,并且当前进程将替换为此新命令。

进程替换实验

  1. 先查看当前shell的PID

    bash 复制代码
    jagitch@jagitch-MS-7B93:tmp$ echo $$
    280513
  2. 打开第二个shell,查看shell 1的进程信息

    bash 复制代码
    jagitch@jagitch-MS-7B93:tmp$ ps -aef | grep 280513
    jagitch   280513   22748  0 11:37 pts/0    00:00:00 bash
    jagitch   281157  273610  0 11:38 pts/1    00:00:00 grep --color=auto 280513
  3. 在shell 1中执行exec命令

    bash 复制代码
    jagitch@jagitch-MS-7B93:tmp$ exec sleep 40
  4. 在shell 2中再次查看shell 1的进程信息

    bash 复制代码
    jagitch@jagitch-MS-7B93:tmp$ ps -aef | grep 280513
    jagitch   280513   22748  0 11:37 pts/0    00:00:00 sleep 40
    jagitch   281573  273610  0 11:38 pts/1    00:00:00 grep --color=auto 280513

    此时发现280513这个进程由之前的bash替换成了sleep 40,说明exec执行地命令不会创建子进程,而是替换掉当前进程的程序。这样可以达到节约计算机资源的目的。

  5. 等shell 1中地exec命令结束后,发现shell 1退出了,此时在shell 2中查看shell 1的进程ID

    bash 复制代码
    jagitch@jagitch-MS-7B93:tmp$ ps -aef | grep 280513
    jagitch   281749  273610  0 11:39 pts/1    00:00:00 grep --color=auto 280513

    此时发现shell 1那个进程已经被销毁了,因为默认的bash进程被exec替换为了sleep命令,这个命令执行完后就会退出,而之前那个shell进程会一直循环解释执行用户输入的命令,它不会退出被销毁。

exec的常用用法

  1. 脚本中进行命令替换

    bash 复制代码
    jagitch@jagitch-MS-7B93:tmp$ cat ./execdemo.sh 
    #!/bin/bash
    
    echo first
    exec echo second
    echo last
    
    jagitch@jagitch-MS-7B93:tmp$ chmod +x ./execdemo.sh 
    jagitch@jagitch-MS-7B93:tmp$ ./execdemo.sh 
    first
    second

    我们可以发现last没有被输出,因为./execdemo.sh在一个子进程中执行,第一个echo正常输出,但是遇到exec echo second后,这个子进程就被替换成echo second了,执行完这条命令该进程就退出销毁了,自然就不会执行后面的echo last了。

  2. 使用exec进行日志记录

    bash 复制代码
    jagitch@jagitch-MS-7B93:tmp$ cat execlog.sh 
    #!/bin/bash
    
    LOG_FILE="output.log"
    
    exec &> "$LOG_FILE"
    
    echo "1. script started at $(date +'%Y-%m-%d')"
    
    echo "2. find all .txt files in current dir"
    find -type f -name "*.txt"
    
    echo "3. make some error"
    cat hello
    
    echo "4. script finished at $(date +'%Y-%m-%d')"
    
    jagitch@jagitch-MS-7B93:tmp$ bash execlog.sh
    jagitch@jagitch-MS-7B93:tmp$ cat output.log
    1. script started at 2024-06-28
    2. find all .txt files in current dir
    ./2.txt
    ./1.txt
    ./favorite colors.txt
    3. make some error
    cat: hello: 没有那个文件或目录
    4. script finished at 2024-06-28

    execlog.sh脚本中使用`exec &> "$LOG_FILE"将标准输出和标准错误都重定向到指定地文件中。

  3. 使用exec操作文件描述符

    bash 复制代码
    jagitch@jagitch-MS-7B93:tmp$ cat execfd.sh
    #!/bin/bash
    
    exec 3> fruit.txt
    exec 1>&3
    echo "apple"
    echo "orange"
    exec 3>&-
    jagitch@jagitch-MS-7B93:tmp$ bash execfd.sh
    jagitch@jagitch-MS-7B93:tmp$ cat fruit.txt 
    apple
    orange

    exec 3> fruit.txt将文件描述符重定向到fruit.txt文件

    exec 1>&3把标准输出重定向到文件描述符为3的文件中

    exec 3>&-的意思是关闭文件描述符

每一次点赞,都是你独特的味道。每一次关注,都是我前行的动力。感谢有你,一起成长!

推荐阅读

1. 互联网、因特网和万维网傻傻分不清,一文带你彻底理解计算机中的各种网络

2. 十分钟带你入门Go语言(Golang)开发

3. 超级详细的Github双重验证开启教程&github Two-factor authentication

相关推荐
wdfk_prog5 小时前
[Linux]学习笔记系列 -- [drivers][input]input
linux·笔记·学习
盟接之桥6 小时前
盟接之桥说制造:引流品 × 利润品,全球电商平台高效产品组合策略(供讨论)
大数据·linux·服务器·网络·人工智能·制造
忆~遂愿6 小时前
ops-cv 算子库深度解析:面向视觉任务的硬件优化与数据布局(NCHW/NHWC)策略
java·大数据·linux·人工智能
湘-枫叶情缘6 小时前
1990:种下那棵不落叶的树-第6集 圆明园的对话
linux·系统架构
Fcy6487 小时前
Linux下 进程(一)(冯诺依曼体系、操作系统、进程基本概念与基本操作)
linux·运维·服务器·进程
袁袁袁袁满7 小时前
Linux怎么查看最新下载的文件
linux·运维·服务器
代码游侠8 小时前
学习笔记——设备树基础
linux·运维·开发语言·单片机·算法
Gary Studio8 小时前
rk芯片驱动编写
linux·学习
mango_mangojuice8 小时前
Linux学习笔记(make/Makefile)1.23
java·linux·前端·笔记·学习
Harvey9038 小时前
通过 Helm 部署 Nginx 应用的完整标准化步骤
linux·运维·nginx·k8s