0%

exec命令

exec

exec共有三种用法

  1. 执行程序
  2. 文件重定向
  3. 当做find命令的一个选项

    执行命令

    系统调用exec是以新的进程去代替原来的进程,但进程的PID保持不变。因此,可以这样认为,exec系统调用并没有创建新的进程,只是替换了原来进程上下文的内容。原进程的代码段,数据段,堆栈段被新的进程所代替。即: 使用exec执行命令, 将不会启动新的shell, 而是用被执行命令替代当前shell进程, 命令执行结束后, shell退出.
    常用场景:
  • 我们一般将exec写在脚本中, bash执行该脚本; 这样会为该脚本创建一个sub shell去执行, 当执行到exec时, 该子脚本进程就会替换为相应的exec命令.
  • 执行exec系统调用,一般都是这样,用fork()函数新建立一个进程,然后让进程去执行exec调用。我们知道,在fork()建立新进程之后,父进各与子进程共享代码段,但数据空间是分开的,但父进程会把自己数据空间的内容copy到子进程中去,还有上下文也会copy到子进程中去。而为了提高效率,采用一种写时copy的策略,即创建子进程的时候,并不copy父进程的地址空间,父子进程拥有共同的地址空间,只有当子进程需要写入数据时(如向缓冲区写入数据),这时候会复制地址空间,复制缓冲区到子进程中去。从而父子进程拥有独立的地址空间。而对于fork()之后执行exec后,这种策略能够很好的提高效率,如果一开始就copy,那么exec之后,子进程的数据会被放弃,被新的进程所代替。

bash source . 都可以执行脚本, 区别在于source和.不会为脚本新建shell, 而是在当前shell中执行;

文件重定向

我们先看一下/dev/fd目录:
/dev/fd
默认会有这四个项:

  • 0是标准输入,默认是键盘。 stdin
  • 1是标准输出,默认是屏幕/dev/tty stdout
  • 2是标准错误,默认也是屏幕 stderr

例子:

1
2
3
4
exec >file     //将当前shell的标准输出到file文件中, 因为>默认为1
exec 4>file //将写入fd4中的内容写入file中
exec 5<&4 //创建fd4的拷贝fd5
exec 3<&- //关闭fd3

find命令

1
2
3
4
// 在当前目录下(包含子目录),查找所有txt文件并找出含有字符串"bin"的行 
find ./ -name "*.txt" -exec grep "bin" {} \; 
// 在当前目录下(包含子目录),删除所有txt文件 
find ./ -name "*.txt" -exec rm {} \;