これは期待どおりに機能します。
$ 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
-i
with を使用すると、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バグレポートで使用されたコマンドの例で、その結果はまだ現在の動作であると考えられます。
- バグ564 - sudoは$をエスケープして環境変数にアクセスできません。(bugzilla.sudo.ws)
sudo -i sh -c 'echo $foo'
壊れる特別な場合はここで議論されます:
(後者はコメントリンクに同じ問題に関する以前の質問)