Environment-Variables
exec env
與 env
兩者
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 ...
,但我認為沒有exec
必要,因為env
不會像exec
.有沒有我們需要使用的案例來
exec env
代替env
?
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
是我的互動式外殼。)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
,所以我們不知道他們的確切情況。但是你會使用exec env
相同的方式exec anyprogram
:如果你想用其他程序替換 shell。例如這個模擬範例:#!/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 保持不變,這使得父級(腳本和程序)更容易監控其子級。