sudoで処理されたバックティックにcmdがネストされていますか?

sudoで処理されたバックティックにcmdがネストされていますか?

`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行のうちどれが正しい使い方であるかさえわかりません(sudoblkidではなく擬似コードだけです)。それともシェルに依存していますか?

答え1

`...`$(...)同じですが、構文が異なるため、1つはBourneシェルから、もう1つはKornシェルから来ます。前者は廃止されましたが、古代のBourneシェルとの下位互換性のためにBourne様シェルでまだサポートされています。

異なるシェルには異なる構文があります。たとえば、fishhas(...)およびrc/ eshave `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)shsudocmd1 $(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$IFScmd2一つ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"
'

関連情報