質問

質問

execどちらかを分岐しないでください。env次の例を参照してください。

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 ...ないと思います。execenvexec

exec env代わりに使用する必要があるユースケースはありますかenv

ベストアンサー1

env(おそらく)自分を分岐せずに実行するプログラムに自分自身を置き換えます。しかし、これは親シェルを分岐するか、env単にenv

たとえば、次の2つを比較します。

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

を使用すると、execシェル自体が置き換えられ、次はecho実行されません。

もちろんあなたはexec env ... &。を使用すると、&シェルはとにかくバックグラウンドプロセスを開始するために分岐し、分岐しない可能性があります。再びバックグラウンドジョブで単一のコマンドを実行します。少なくとも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私の対話型シェルです。)

Bashは単一のコマンドに対してのみこれを行います。複数のコマンドがある場合、シェルは最後のコマンドが終了するのを待ちます。使用する方法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

ただし、複合ブロックではバックグラウンドシェルプロセスも表示できます。

$ 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ので、彼らの正確な状況を知ることはできません。ただし、シェルを別のプロセスに置き換えるには、次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シェルがメモリに無駄に残らないように、スクリプトを起動したプログラムに置き換えてください。また、スクリプトにプログラムを開始する仲介者が 1 つしかない場合、仲介者を実行するとexecPID が同じままであるため、親 (スクリプトの親、その後はプログラムの親) が子を監視しやすくなります。

おすすめ記事