「-i」なしで動作しますが、「sudo -i」が変数の拡張を中断するのはなぜですか?

「-i」なしで動作しますが、「sudo -i」が変数の拡張を中断するのはなぜですか?

これは期待どおりに機能します。

$ sudo -u romain bash -c 'a="b" ; echo $a'
b
$

しかし、-i変数はエコーされません。なぜですか?

$ sudo -iu romain bash -c 'a="b" ; echo $a'

$

どの程度bash間接参照または変数補間が追加されたのか疑問に思います-i。それでは、これはどのように機能しますか?

$ sudo -iu romain bash -c 'a="b" ; echo ${a}'
b
$

答え1

-iwith を使用すると、sudoユーザーのログインシェルが使用され、$SHELLログインシェルとして呼び出されます。

次のように実行するコマンドとともにコマンドを追加で提供する場合

sudo -u user -i 'some-command'

...をsudo使用してコマンドを実行します$SHELL -c。つまり、引数リストを単一のコマンドライン文字列に変換する必要があり、これはシェルで再評価されます。これを行うには、some-command英数字、アンダースコア、ハイフン、ドル記号を除くすべての文字をエスケープする必要があります。

これは意味する

sudo -u user -i bash -c 'a="b" ; echo ${a}'

user として実行され、user次のようにエスケープされます。

$SHELL -c bash\ -c\ \'a\=\"b\"\ \;\ echo\ $\{a\}\'

...使用すると、$aコマンドは次のようになります。

$SHELL -c bash\ -c\ \'a\=\"b\"\ \;\ echo\ $a\'

最後のコマンドでは、$a始める前にユーザーのログインシェルが展開されますbash -c。前のコマンドで${a}使用されていた場所は$\{a\}有効な拡張ではないため、ユーザーシェルはそれを拡張しませんが、インラインbash -cシェルはそれを表示して${a}拡張できます。

sudoこれについては、オプションを説明するマニュアルセクションに記載されています-i

-i, --login
            Run the shell specified by the target user's password
            database entry as a login shell.  This means that login-
            specific resource files such as .profile, .bash_profile, or
            .login will be read by the shell.  If a command is specified,
            it is passed to the shell as a simple command using the -c
            option.  The command and any arguments are concatenated,
            separated by spaces, after escaping each character (including
            white space) with a backslash (‘\’) except for alphanumerics,
            underscores, hyphens, and dollar signs.  If no command is
            specified, an interactive shell is executed. [...]

答え2

これは、sudoがコマンドラインから取得した引数を別のシェル(sudo -iターゲットユーザーのログインシェルを実行しますが一般は実行しません)に提供するためにエスケープする方法sudo間の奇妙な対話によるものです。

特にドル記号を残します。$ いいえ引用すると、そのようなコマンドは次のとおりです。

sudo -i /bin/echo '$USER'

働く

その場合したまた、ドル記号を引用しても動作しませんが、

sudo -i sh -c 'echo "$USER"'

しなければならない。まあ、私の言葉はそれがうまくいくと思いましたが、それが実行されました。二つシェル(ターゲットユーザーのログインシェルとsh私たちが特別に要求したもの)から逃れることを考えるのは痛いです。

この$USER例はあまり役に立ちませんが、他の変数と一緒に実行して、ユーザーがログイン環境で取得する値を確認することをお勧めします。

とにかく、これはこのsudoバグレポートで使用されたコマンドの例で、その結果はまだ現在の動作であると考えられます。

sudo -i sh -c 'echo $foo'壊れる特別な場合はここで議論されます:

(後者はコメントリンク同じ問題に関する以前の質問)

関連情報