cmd嵌套在從sudo處理的反引號中?
commands
是否使用(不推薦使用的)反引號以 root 權限(sudo
從命令行)執行嵌套,而命令替換$(...)
不是?例如
sudo mount `blkid -u /dev/sda1` ... sudo mount `sudo blkid -u /dev/sda1` ...
對比
sudo mount $(blkid -u /dev/sda1) ... sudo mount $(sudo blkid -u /dev/sda1) ...
方法之間有區別嗎?我什至不太確定這四行中哪一行是正確的用法(關於
sudo
,而不是 blkid,它只是虛擬碼)。還是它依賴於外殼?
...
並且$(...)
是具有不同語法的相同事物,一個 if 來自 Bourne shell,另一個來自 Korn shell,前者已被棄用,但仍被 Bourne-like shell 支持,以便與古老的 Bourne shell 向後兼容。其他 shell 對此有不同的語法。例如,
fish
has(...)
和rc
/es
havecmd`or
{more complex cmd},或``(sep){cmd}
指定不同的拆分行為。ksh93
並且mksh
還有${ ...; }
(無子外殼)變體。無論如何,這是 shell 語言中的語法,因此您需要一個 shell 來解釋它並執行命令替換。
在:
sudo cmd1 `cmd2`
在類伯恩貝殼中,貝殼
- 在子程序中執行
cmd2
,其輸出重定向到管道- 從管道的另一端讀取該 cmd 的輸出,
- 刪除尾隨的換行符,
- 根據拆分結果
$IFS
- 對生成的單詞執行文件名生成(除了 in
zsh
;一些 ksh 變體也執行大括號擴展)- 然後將生成的單詞作為單獨的參數傳遞給
sudo
在另一個子程序中執行的命令。
sudo
然後更改 uids 並執行它作為參數傳遞的命令。如果你想
cmd2
使用不同的 uid 執行,你需要sudo
執行一個 shell 來解釋執行命令替換的 shell 程式碼:sudo sh -c 'cmd1 $(cmd2)' sudo fish -c 'cmd1 (cmd2)' sudo rc -c 'cmd1 `cmd2'
等等。
請注意,在 Bourne-like shell 中,命令替換仍然在雙引號內執行,所以不要這樣做:
sudo sh -c "cmd1 $(cmd2)"
首先,它不會
cmd2
作為執行root
,而且cmd2
(這一次,因為它在引號內,所以不受 split+glob 的影響)的輸出將被解釋為sh
程式碼,因此通常會構成命令注入漏洞。例如,如果cmd2
輸出$(reboot)
,sh
呼叫者sudo
將被要求解釋cmd1 $(reboot)
並重新啟動。同樣,如果您想將shell 變數的內容(與以 開頭的變數相反)傳遞給
sudo sh -c 'cmd1 $(cmd2) '"$var"
or ,請不要這樣做。相反,將這些變數的內容作為額外參數傳遞給(不在程式碼參數內部),或通過環境變數(因此它們也成為 shell 的變數):sudo sh -c 'cmd1 $(cmd2 '"$var"')'``sudo``cmd1``cmd2``sh``sudo
sudo sh -c 'cmd1 $(cmd2) "$1"' sh "$var" sudo VAR="$var" sh -c 'cmd1 $(cmd2) "$VAR"' sudo sh -c 'cmd1 $(cmd2 "$1")' sh "$var" sudo VAR="$var" sh -c 'cmd1 $(cmd2 "$VAR")'
在這裡,您還可以隨時執行以下操作:
sudo cmd1 $(sudo cmd2) "$var" sudo cmd1 $(sudo cmd2 "$var")
那就是讓你的shell 通過兩個單獨的呼叫來執行這兩個命令,
sudo
因此它們都以提升的權限執行。如上所述,在類似 Bourne 的 shell 中(但也適用於類似 csh 的 shell),不帶引號的命令替換受 split+glob 的影響,因此
$(cmd2)
如果cmd1 $(cmd2)
輸出cmd2
分隔$IFS
列表萬用字元模式。如果您希望cmd2
(不帶尾隨換行符)的輸出作為一個參數作為一個整體傳遞給cmd1
,您希望cmd1 "$(cmd2)"
或更可能cmd1 -- "$(cmd2)"
確保該參數不被視為選項(假設cmd1
支持--
end-選項標記)。因此,對於您的特定案例,這將是:
sudo DEVICE="$device" sh -c 'mount -- "$(blkid -u -- "$DEVICE")"'
或
mount
僅在blkid
成功時呼叫:sudo DEVICE="$device" sh -c ' output=$(blkid -u -- "$DEVICE") && mount -- "$output" '