×

Linux 之exec命令

hqy hqy 发表于2026-04-22 17:06:47 浏览6 评论0

抢沙发发表评论

exec 是 Linux/Unix Shell 中极其核心的内置命令,底层基于 execve() 系统调用,核心作用是替换当前进程(不创建新进程、PID 不变),或永久修改当前 Shell 的 I/O 重定向。它是编写高效脚本、服务启动、日志处理的关键工具。

一、核心原理(与普通命令的区别)

· 普通命令(如 ls、bash)Shell 先 fork() 创建子进程 → 子进程 execve() 执行命令 → 父 Shell 等待子进程结束后回收,Shell 本身不消失

· exec 命令跳过 fork,直接在当前 Shell 进程内执行 execve () → 原 Shell 被新程序完全覆盖(代码 / 数据 / 堆栈)→ 新程序退出时,整个进程直接终止,不会回到原 Shell

二、语法与选项

exec [-cl] [-a name] [command [arguments ...]] [redirection ...]

· -c清空环境变量后执行命令(干净环境)

· -l:为命令加 - 前缀,模拟登录 Shell-bash

· -a name伪造进程名ps 显示为 name,而非真实命令)

· command:要替换执行的程序(省略时仅做重定向)

· redirectionI/O 重定向(全局生效)

三、两大核心用法

1. 进程替换(替换当前 Shell / 脚本)

效果:原进程消失,PID 不变,执行新程序。

# 1. 终端中直接用 ls 替换当前 Shell(执行完 ls 后终端退出)

exec ls -l /etc

# 2. 脚本中 exec 启动服务(脚本进程变服务进程,无残留)

#!/bin/bashecho "Starting Nginx..."

exec /usr/sbin/nginx -g 'daemon off;'  # 脚本消失,PID 归 Nginx

# 3. 换 Shell(旧 bash 消失,新 bash 接管)

exec zsh

exec bash --login

# 4. 清空环境 + 改名

exec -c -a my-proc python3 app.py

2. 全局 I/O 重定向(最常用!不替换进程)

效果永久改变当前 Shell / 脚本的输入输出,后续所有命令自动生效。

 

# 1. 脚本全量日志(所有输出写入文件)

#!/bin/bash

# 标准输出→日志,标准错误→同标准输出

exec > /var/log/script.log 2>&1

echo "任务开始"  # 写入日志

ls -l           # 写入日志

cp file /tmp    # 错误也写入日志

# 2. 自定义文件描述符(读写文件)

# 打开文件(fd=3 读,fd=4 写)

exec 3< /etc/passwd    # 读

exec 4> /tmp/out.txt   # 写

# 从 fd=3 读

read line <&3

echo "第一行:$line"

# 写入 fd=4

echo "Hello" >&4

# 关闭文件描述符

exec 3<&-

exec 4>&-

# 3. 标准输入重定向(从文件读)

exec < /etc/hosts

cat  # 等价 cat /etc/hosts

四、关键特性

· 不可逆exec 后原进程代码不再执行

· PID 不变

· 无残留:无僵尸 / 孤儿进程(适合服务启动)

· 重定向永久:直到 Shell 退出

· 失败即返回:命令不存在时,exec 报错,Shell 继续

五、典型应用场景

1. 服务 / 容器启动脚本Docker ENTRYPOINT、systemd 辅助脚本)

exec python3 /app/main.py  # 容器 1 号进程直接是业务进程,无多余 sh

2. 

3. 脚本全量日志(避免每条命令都加 >>)

4. 文件描述符操作(高效读写、管道、套接字)

5. 登录环境切换exec su - userexec tmux

6. 资源优化(避免 fork 开销,适合嵌入式 / 低资源环境)

六、常见误区

· ❌ exec cd /tmpcd 是内置命令,不是可执行文件,无效

· ❌ 终端直接 exec:执行完会退出终端 / SSH

· ✅ 脚本内 exec:脚本进程被替换,父 Shell 不受影响

七、与系统调用 execve 的关系

Shell exec → 调用 C 库 execvp/execl → 内核 execve()C 语言中:

#include <unistd.h>

execve("/bin/ls", (char*[]){ "ls", "-l", NULL }, NULL);

效果与 Shell exec ls -l 完全一致。

一句话总结exec 要么换程序(进程替换),要么换输入输出(全局重定向),是 Linux 进程与 I/O 管理的底层利器。


打赏

本文链接:https://www.kinber.cn/post/6480.html 转载需授权!

分享到:


推荐本站淘宝优惠价购买喜欢的宝贝:

image.png

 您阅读本篇文章共花了: 

群贤毕至

访客