Bash

eval 和 exec 有什麼區別?

  • July 29, 2019

eval並且exec都內置在執行命令的 bash(1) 命令中。

我也看到exec有一些選擇,但這是唯一的區別嗎?他們的背景會發生什麼?

eval``exec是完全不同的野獸。(除了兩者都將執行命令這一事實之外,您在 shell 中所做的一切也是如此。)

$ help exec
exec: exec [-cl] [-a name] [command [arguments ...]] [redirection ...]
   Replace the shell with the given command.

做什麼exec cmd,與 running 完全相同,只是cmd目前 shell 被替換為命令,而不是執行一個單獨的程序。在內部,執行say/bin/ls會呼叫fork()創建一個子程序,然後exec()在子程序中執行/bin/lsexec /bin/ls另一方面不會分叉,而只是替換外殼。

比較:

$ bash -c 'echo $$ ; ls -l /proc/self ; echo foo'
7218
lrwxrwxrwx 1 root root 0 Jun 30 16:49 /proc/self -> 7219
foo

$ bash -c 'echo $$ ; exec ls -l /proc/self ; echo foo'
7217
lrwxrwxrwx 1 root root 0 Jun 30 16:49 /proc/self -> 7217

echo $$列印我啟動的 shell 的 PID,並且列出從 shell 執行/proc/self的 PID 。ls通常,程序 ID 不同,但與execshellls具有相同的程序 ID。此外,以下命令exec沒有執行,因為 shell 已被替換。


另一方面:

$ help eval
eval: eval [arg ...]
   Execute arguments as a shell command.

eval將在目前 shell 中將參數作為命令執行。換句話說eval foo bar就是和剛才一樣foo bar。但是變數在執行前會被展開,所以我們可以執行保存在shell變數中的命令:

$ unset bar
$ cmd="bar=foo"
$ eval "$cmd"
$ echo "$bar"
foo

不會創建子程序,因此變數是在目前 shell 中設置的。(當然eval /bin/ls會創建一個子程序,就像普通的舊程序一樣/bin/ls。)

或者我們可以有一個輸出 shell 命令的命令。執行ssh-agent在後台啟動代理,並輸出一堆變數分配,可以在目前 shell 中設置並由子程序(ssh您將執行的命令)使用。因此ssh-agent可以開始:

eval $(ssh-agent)

並且目前的shell會獲取其他命令繼承的變數。


當然,如果變數cmd碰巧包含類似的東西rm -rf $HOME,那麼執行eval "$cmd"就不是你想做的事情。即使是字元串中的命令替換之類的東西也會被處理,所以在使用它之前應該確保輸入eval安全的。

通常,eval可以避免甚至避免以錯誤的方式意外混合程式碼和數據。

引用自:https://unix.stackexchange.com/questions/296838