问题

问题

两者execenv不要 fork,请参阅以下示例:

docker run --rm -it ubuntu:18.04 sh -c 'exec sleep 1 & ps -Ho pid,ppid,cmd'
  PID  PPID CMD
    1     0 sh -c exec sleep 1 & ps -Ho pid,ppid,cmd
    7     1   sleep 1
    8     1   ps -Ho pid,ppid,cmd
docker run --rm -it ubuntu:18.04 sh -c 'env sleep 1 & ps -Ho pid,ppid,cmd'
  PID  PPID CMD
    1     0 sh -c env sleep 1 & ps -Ho pid,ppid,cmd
    7     1   sleep 1
    8     1   ps -Ho pid,ppid,cmd

问题

我看到很多人使用,exec env ...但我认为没有exec必要,因为env它不像exec.

是否有任何我们需要使用的用例exec env来代替env

答案1

env(可能)本身不会分叉,只是用它所执行的程序替换自身。但这与父 shell 分叉不同env,或者只是将其替换为env

例如比较这两个:

$ bash -c 'env ls > /dev/null; echo hi'
hi
$ bash -c 'exec env ls > /dev/null; echo hi'
[no output]

使用 时exec,外壳本身被替换,并且以下内容echo不会运行。

当然,你有exec env ... &。使用&,shell 无论如何都会分叉来启动后台进程,并且它可能不会分叉再次在后台任务中运行单个命令。至少 Bash 优化了这样的情况,例如:

$ bash -c 'ps -Ho pid,ppid,cmd; echo x'
  PID  PPID CMD
11967  1545 -/bin/bash
14851 11967   bash -c ps -Ho pid,ppid,cmd; echo x
14852 14851     ps -Ho pid,ppid,cmd
x
$ bash -c 'ps -Ho pid,ppid,cmd'
  PID  PPID CMD
11967  1545 -/bin/bash
14853 11967   ps -Ho pid,ppid,cmd

如果后者不显示中间过程bash,则行为与存在该过程相同exec。 (-/bin/bash是我的交互式 shell。)

Bash 只对单个命令执行此操作,如果有多个命令,shell 会等待最后一个命令退出。使用exec那里会有所不同:

$ bash -c 'echo x; ps -Ho pid,ppid,cmd'
x
  PID  PPID CMD
11967  1545 -/bin/bash
14929 11967   bash -c echo x; ps -Ho pid,ppid,cmd
14930 14929     ps -Ho pid,ppid,cmd
$ bash -c 'echo x; exec ps -Ho pid,ppid,cmd'
x
  PID  PPID CMD
11967  1545 -/bin/bash
14933 11967   ps -Ho pid,ppid,cmd

对于&,这与以下相同exec ps

$ bash -c 'ps -Ho pid,ppid,cmd & sleep 1'
  PID  PPID CMD
11967  1545 -/bin/bash
14867 11967   bash -c ps -Ho pid,ppid,cmd & sleep 1
14868 14867     ps -Ho pid,ppid,cmd
14869 14867     sleep 1

但通过复合块,我们也可以看到后台 shell 进程:

$ bash -c '{ ps -Ho pid,ppid,cmd; } & sleep 1'
  PID  PPID CMD
11967  1545 -/bin/bash
14877 11967   bash -c { ps -Ho pid,ppid,cmd; } & sleep 1
14878 14877     bash -c { ps -Ho pid,ppid,cmd; } & sleep 1
14880 14878       ps -Ho pid,ppid,cmd
14879 14877     sleep 1

您没有提供这些人所做的任何具体消息来源exec env,因此我们不知道他们的确切情况。但是,如果您想用其他进程替换 shell,则可以使用exec env与 : 相同的方式。exec anyprogram例如这个模拟示例:

#!/bin/bash
. someconfigfile
if [ "$someconfig" = blah ]; then
    exec env myprogram some args...
    echo "failed to start" >&2
    exit 1
elif
    ... whatever
fi

那里exec用启动的程序替换脚本,这样 shell 就不会无用地保留在内存中。此外,如果脚本只有一个启动程序的中介,执行 anexec将使 PID 保持相同,这使得父级(脚本的父级,然后是程序的)更容易监视其子级。

相关内容