`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) ...
どのように違いがありますか? 4行のうちどれが正しい使い方であるかさえわかりません(sudo
blkidではなく擬似コードだけです)。それともシェルに依存していますか?
答え1
`...`
$(...)
同じですが、構文が異なるため、1つはBourneシェルから、もう1つはKornシェルから来ます。前者は廃止されましたが、古代のBourneシェルとの下位互換性のためにBourne様シェルでまだサポートされています。
異なるシェルには異なる構文があります。たとえば、fish
has(...)
およびrc
/ es
have `cmd
、またはは`{more complex cmd}
別`(sep){cmd}
の分割動作を指定します。ksh93
そして(サブシェルなし)バリエーションmksh
もあります。${ ...; }
とにかくこれはシェル言語の構文なので、それを解釈してコマンド置換を実行するにはシェルが必要です。
存在する:
sudo cmd1 `cmd2`
Bourneのような殻では、
cmd2
出力がパイプにリダイレクトされる子プロセスで実行されます。- パイプのもう一方の端からこのcmdの出力を読み取ります。
- 末尾の改行を削除し、
- セグメンテーション結果によると
$IFS
- 生成された単語に対してファイル名の生成を実行します(inに加えて、
zsh
一部のkshバリアントは中括弧拡張も実行します)。 - 結果の単語は、
sudo
別のサブプロセスで実行されるコマンドに別々の引数として渡されます。
sudo
次にuidを変更し、引数として渡されたコマンドを実行します。
別のuidで実行するには、コマンドの置き換えを実行するシェルコードを解釈するために実行中のシェルがcmd2
必要です。sudo
sudo sh -c 'cmd1 $(cmd2)'
sudo fish -c 'cmd1 (cmd2)'
sudo rc -c 'cmd1 `cmd2'
など。
Bourneに似たシェルでは、コマンドの置換は依然として二重引用符内で実行されるためいいえする:
sudo sh -c "cmd1 $(cmd2)"
cmd2
まず、実行されず、root
出力cmd2
(今回は引用符内にあるため、分割+globの影響を受けません)がコードとして解釈されるsh
ため、通常はコマンド注入の脆弱性を構成します。たとえば、出力の場合、呼び出し元にcmd2
説明して再起動するように求められます。$(reboot)
sh
sudo
cmd1 $(reboot)
同様に、変数の内容を渡すには、次のことをしないでください。sudo sh -c 'cmd1 $(cmd2) '"$var"
あなたのシェル(で始まるシェルを除く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")
つまり、あなたのシェルはこれら2つのコマンドを別々の2つの呼び出しで実行するため、両方ともsudo
高い権限で実行できます。
前述のように、Bourneのようなシェル(しかしこれは異なるがcshのようなシェルにも当てはまります)から引用されていないコマンド置換は分割+globによって制御されるため、別々のリストを出力するときにワイルドカードパターンが可能な場合にのみ$(cmd2)
使用する必要があります。引用なし。出力(末尾の改行なし)を完全に渡したい場合cmd1 $(cmd2)
cmd2
$IFS
cmd2
一つcmd1
必要なパラメータを選択するcmd1 "$(cmd2)"
か、cmd1 -- "$(cmd2)"
パラメータがオプションとして処理されないようにする必要があります(オプションの閉じるタグがサポートされていると仮定cmd1
)--
。
したがって、特定のユースケースでは、次のようになります。
sudo DEVICE="$device" sh -c 'mount -- "$(blkid -u -- "$DEVICE")"'
mount
または単に成功を求めてくださいblkid
:
sudo DEVICE="$device" sh -c '
output=$(blkid -u -- "$DEVICE") &&
mount -- "$output"
'