shell exec
exec 是 bash 的内置命令
shell 的内件命令exec执行命令时,不启用新的shell进程。
source 和 . 不启用新的shell
在当前shell中执行,设定的局部变量在执行完命令后仍然有效。
bash 或 sh 或 shell script 执行时,另起一个子shell,其继承父shell的环境变量,其子shell的变量执行完后不影响父shell
exec是用被执行的命令行替换掉当前的shell进程(当前shell进程会被关闭),且exec命令后的其他命令将不再执行
为了避免这个结果的影响,一般将exec命令放到一个shell脚本中,用主脚本调用这个脚本,调用处可以用bash xx.sh(xx.sh为存放exec命令的脚本),这样会为xx.sh建立一个子shell去执行,当执行exec后该子脚本进程就被替换成相应的exec的命令
exec 两种用法,一种是执行 Shell 命令,一种是操作文件描述符
exec 命令可以永久性地重定向,直到再次遇到 exec 命令才会改变重定向的方向,一次重定向,永久有效
shell中描述符一共有12个
0 代表标准输入
1 代表标准输出
2 错误输出
其他 3-9 都是空白描述符
Demo:
绑定新的文件描述符之前的状态
qiweijie@qiweijie:~/study_shell$ ls /proc/self/fd
0 1 2 3
# 绑定一个新的文件描述符6,并且绑定标准输出(相当于给标准输出保存一个临时copy)
qiweijie@qiweijie:~/study_shell$ exec 6>&1
qiweijie@qiweijie:~/study_shell$ ls /proc/self/fd
0 1 2 3 6
# 绑定标准输出给suc.txt
qiweijie@qiweijie:~/study_shell$ exec 1>suc.txt
# 发现标准输出都没有了啊
qiweijie@qiweijie:~/study_shell$ ls -al
# 俨然发现suc.txt已经是输出文件
qiweijie@qiweijie:~/study_shell$ cat suc.txt
cat: suc.txt:输入文件是输出文件
qiweijie@qiweijie:~/study_shell$ ls /proc/self/fd
# 把标准输出绑定回来
qiweijie@qiweijie:~/study_shell$ exec 1>&6
qiweijie@qiweijie:~/study_shell$ ls /proc/self/fd
0 1 2 3 6
# 关闭自定义的文件描述符
qiweijie@qiweijie:~/study_shell$ exec 6>&-
qiweijie@qiweijie:~/study_shell$ ls /proc/self/fd
0 1 2 3
# 如果直接把标准输出绑定到文件,那么问题就是,你再也变不回来了
qiweijie@qiweijie:~/study_shell$ exec 1>suc.txt
qiweijie@qiweijie:~/study_shell$ cat suc.txt
cat: suc.txt:输入文件是输出文件
qiweijie@qiweijie:~/study_shell$ exec 1>&-
qiweijie@qiweijie:~/study_shell$ cat suc.txt
cat: 标准输出: 错误的文件描述符
qiweijie@qiweijie:~/study_shell$ ls /proc/self/fd
ls: 写入错误: 错误的文件描述符
qiweijie@qiweijie:~/study_shell$
Ps: > 同类的重定向只对当前命令有效,对后面的命令无效
$@ 表示所有脚本参数的内容
$# 表示返回所有脚本参数的个数
$0 表示当前脚本的名字