zoukankan      html  css  js  c++  java
  • Linux Shell exec绑定重定向

    shell 中的 exec 两种用法

      1.exec 命令 ;命令代替shell程序,命令退出,shell 退出;比如 exec ls

      2.exec 文件重定向,可以将文件的重定向就看为是shell程序的文件重定向 比如 exec 5</dev/null;exec 5<&-

      shell的内建命令exec将并不启动新的shell,而是用要被执行命令替换当前的shell进程,并且将老进程的环境清理掉,而且exec命令后的其它命令将不再执行。
      因此,如果你在一个shell里面,执行exec ls那么,当列出了当前目录后,这个shell就自己退出了,因为这个shell进程已被替换为仅仅执行ls命令的一个进程,执行结束自然也就退出了。为了避免这个影响我们的使用,一般将exec命令放到一个shell脚本里面,用主脚本调用这个脚本,调用点处可以用bash a.sh,(a.sh就是存放该命令的脚本),这样会为a.sh建立一个sub shell去执行,当执行到exec后,该子脚本进程就被替换成了相应的exec的命令。
      source命令或者".",不会为脚本新建shell,而只是将脚本包含的命令在当前shell执行。
      不过,要注意一个例外,当exec命令来对文件描述符操作的时候,就不会替换shell,而且操作完成后,还会继续执行接下来的命令。
      exec 3<&0:这个命令就是将操作符3也指向标准输入。

      另外,这个命令还可以作为find命令的一个选项,如下所示:
      (1)在当前目录下(包含子目录),查找所有txt文件并找出含有字符串"bin"的行
        find ./ -name “.txt" -exec grep “bin” {} ;
      (2)在当前目录下(包含子目录),删除所有txt文件
        find ./ -name ".txt” -exec rm {} ;
    先总结一个表:

    exec命令 作用
    exec ls 在shell中执行ls,ls结束后不返回原来的shell中了
    exec <file 将file中的内容作为exec的标准输入
    exec >file 将file中的内容作为标准写出
    exec 3<file 将file读入到fd3中
    sort <&3 fd3中读入的内容被分类
    exec 4>file 将写入fd4中的内容写入file中
    ls >&4 Ls将不会有显示,直接写入fd4中了,即上面的file中
    exec 5<&4 创建fd4的拷贝fd5
    exec 3<&- 关闭fd3

      1、exec 执行程序  

      虽然exec和source都是在父进程中直接执行,但exec这个与source有很大的区别,source是执行shell脚本,而且执行后会返回以前的shell。而exec的执行不会返回以前的shell了,而是直接把以前登陆shell作为一个程序看待,在其上经行复制。

      举例说明:

     1 root@localhost:~/test#exec ls
     2 
     3 exp1 exp5 linux-2.6.27.54 ngis_post.sh test xen-3.0.1-install
     4 
     5 root@localhost:~/test#exec >text
     6 
     7 root@localhost:~/test#ls
     8 
     9 root@localhost:~/test#pwd
    10 
    11 root@localhost:~/test#echo “hello”
    12 
    13 root@localhost:~/test#exec>/dev/tty
    14 
    15 root@localhost:~/test#cat text
    16 
    17 exp1
    18 
    19 exp5
    20 
    21 linux-2.6.27.54
    22 
    23 ngis_post.sh
    24 
    25 test
    26 
    27 text
    28 
    29 xen-3.0.1-install
    30 
    31 /root/test
    32 
    33 hello
    34 
    35 root@localhost:~/test#

      Exec >text 是将当前shell的标准输出都打开到text文件中

     1 root@localhost:~/test#cat test
     2 
     3 ls
     4 
     5 Pwd
     6 
     7 root@localhost:~/test#bash
     8 
     9 root@localhost:~/test#exec <test
    10 
    11 root@localhost:~/test#ls
    12 
    13 exp1 exp5 linux-2.6.27.54 ngis_post.sh test text xen-3.0.1-install
    14 
    15 root@localhost:~/test#pwd
    16 
    17 /root/test
    18 
    19 root@localhost:~/test#
    20 
    21 root@localhost:~/test#exit #自动执行

      exec的重定向

      先上我们进如/dev/fd/目录下看一下:

    1 root@localhost:~/test#cd /dev/fd
    2 
    3 root@localhost:/dev/fd#ls
    4 
    5 0 1 2 255

      默认会有这四个项:0是标准输入,默认是键盘。

      1是标准输出,默认是屏幕/dev/tty

      2是标准错误,默认也是屏幕

      255

      当我们执行exec 3>test时:

    1 root@localhost:/dev/fd#exec 3>/root/test/test
    2 
    3 root@localhost:/dev/fd#ls
    4 
    5 0 1 2 255 3
    6 
    7 root@localhost:/dev/fd#

      看到了吧,多了个3,也就是又增加了一个设备,这里也可以体会下linux设备即文件的理念。这时候fd3就相当于一个管道了,重定向到fd3中的文件会被写在test中。关闭这个重定向可以用exec 3>&-。

     1 root@localhost:/dev/fd#who >&3
     2 
     3 root@localhost:/dev/fd#ls >&3
     4 
     5 root@localhost:/dev/fd#exec 3>&-
     6 
     7 root@localhost:/dev/fd#cat /root/test/te
     8 
     9 test text
    10 
    11 root@localhost:/dev/fd#cat /root/test/test
    12 
    13 root tty1 2010-11-16 01:13
    14 
    15 root pts/0 2010-11-15 22:01 (192.168.0.1)
    16 
    17 root pts/2 2010-11-16 01:02 (192.168.0.1)
    18 
    19 0
    20 
    21 1
    22 
    23 2
    24 
    25 255
    26 
    27 3

    应用举例

    1 exec 3<test
    2 
    3 while read -u 3 pkg

      do

      echo “$pkg”

      done

      系统调用exec是以新的进程去代替原来的进程,但进程的PID保持不变。因此,可以这样认为,exec系统调用并没有创建新的进程,只是替换了原来进程上下文的内容。原进程的代码段,数据段,堆栈段被新的进程所代替。

      一个进程主要包括以下几个方面的内容:

      (1)一个可以执行的程序

      (2) 与进程相关联的全部数据(包括变量,内存,缓冲区)

      (3)程序上下文(程序计数器PC,保存程序执行的位置)

      exec是一个函数簇,由6个函数组成,分别是以excl和execv打头的。
      执行exec系统调用,一般都是这样,用fork()函数新建立一个进程,然后让进程去执行exec调用。我们知道,在fork()建立新进程之后,父进各与子进程共享代码段,但数据空间是分开的,但父进程会把自己数据空间的内容copy到子进程中去,还有上下文也会copy到子进程中去。而为了提高效率,采用一种写时copy的策略,即创建子进程的时候,并不copy父进程的地址空间,父子进程拥有共同的地址空间,只有当子进程需要写入数据时(如向缓冲区写入数据),这时候会复制地址空间,复制缓冲区到子进程中去。从而父子进程拥有独立的地址空间。而对于fork()之后执行exec后,这种策略能够很好的提高效率,如果一开始就copy,那么exec之后,子进程的数据会被放弃,被新的进程所代替。

      exec与system的区别
      (1) exec是直接用新的进程去代替原来的程序运行,运行完毕之后不回到原先的程序中去。

      (2) system是调用shell执行你的命令,system=fork+exec+waitpid,执行完毕之后,回到原先的程序中去。继续执行下面的部分。

      总之,如果你用exec调用,首先应该fork一个新的进程,然后exec. 而system不需要你fork新进程,已经封装好了。

  • 相关阅读:
    LeetCode Flatten Binary Tree to Linked List
    LeetCode Longest Common Prefix
    LeetCode Trapping Rain Water
    LeetCode Add Binary
    LeetCode Subsets
    LeetCode Palindrome Number
    LeetCode Count and Say
    LeetCode Valid Parentheses
    LeetCode Length of Last Word
    LeetCode Minimum Depth of Binary Tree
  • 原文地址:https://www.cnblogs.com/Reverse-xiaoyu/p/13122404.html
Copyright © 2011-2022 走看看