回答:
sudo su -
は、複雑な記述方法でありsudo -i
、手付かずの環境を構築します。それがログインシェルのポイントです。平原でさえsudo
、環境からほとんどの変数を削除します。さらにsudo
、外部コマンドです。シェルスクリプト自体で権限を昇格させる方法はありません。sudo
追加の権限で外部プログラム()を実行するだけです。つまり、親シェルで定義されているシェル変数(つまり、エクスポートされない変数)と関数は、子シェル。
あなたはありません(ログインシェルを起動してて、環境変数を渡すことができますsudo bash
代わりにsudo su -
またはsudo -i
)及び(とを介してこれらの変数をできるようにsudoを設定するDefaults !env_reset
か、Defaults env_keep=…
中sudoers
のファイル)。これは関数の助けにはなりません(bashには関数エクスポート機能がありますが、sudoはそれをブロックします)。
子シェルで関数を取得する通常の方法は、そこで関数を定義することです。引用に注意<<EOF
してください。ヒアドキュメントに使用する場合、ヒアドキュメントのコンテンツは最初に親シェルによって展開され、その展開の結果が子シェルに表示されるスクリプトになります。つまり、
sudo -u "$target_user" -i <<EOF
echo "$(whoami)"
EOF
これにより、ターゲットユーザーではなく、元のユーザーの名前が表示されます。この展開の最初のフェーズを回避するには、<<
演算子の後にhereドキュメントマーカーを引用します。
sudo -u "$target_user" -i <<'EOF'
echo "$(whoami)"
EOF
したがって、親シェルから子シェルにデータを渡す必要がない場合は、引用符付きのhereドキュメントを使用できます。
#!/bin/bash
sudo -u "$target_user" -i <<'EOF'
log_f() {
echo "LOG line: $@"
}
intVAR=$(date)
log_f "${intVAR}"
EOF
引用符で囲まれていないhereドキュメントマーカーを使用して親シェルから子シェルにデータを渡すことができますが、これは、データに特殊文字が含まれていない場合にのみ機能します。それは、次のようなスクリプトで
sudo -u "$target_user" -i <<EOF
echo "$(whoami)"
EOF
の出力はwhoami
、文字列ではなく、シェルコードの一部になります。たとえば、whoami
コマンドが返された"; rm -rf /; "true
場合、子シェルはコマンドを実行しecho ""; rm -rf /; "true"
ます。
親シェルからデータを渡す必要がある場合、簡単な方法は、それを引数として渡すことです。子シェルを明示的に呼び出して、位置パラメーターを渡します。
#!/bin/bash
extVAR="yourName"
sudo -u "$target_user" -i sh _ "$extVAR" <<'EOF'
log_f() {
echo "LOG line: $@"
}
intVAR=$(date)
log_f "${intVAR}" "${1}"
EOF
渡す変数が複数ある場合は、名前で渡す方が読みやすくなります。env
明示的に呼び出して、子シェルの環境変数を設定します。
#!/bin/bash
extVAR="yourName"
sudo -u "$target_user" -i env extVAR="$extVAR" sh <<'EOF'
log_f() {
echo "LOG line: $@"
}
intVAR=$(date)
log_f "${intVAR}" "${1}"
EOF
期待どおり/etc/profile
にターゲットユーザー~/.profile
を読み取る場合は、明示的に読み取るか、bash --login
ではなくを呼び出す必要がありsh
ます。
起動log_f
したsudo su -
シェルで関数が宣言されていないため、これは機能しません。代わりに:
extVAR="yourName"
sudo su - <user> << EOF
log_f() {
echo "LOG line: $@"
}
intVAR=$(date)
log_f ${intVAR} ${extVAR}
EOF
ルートサブシェルで定義された関数を取得する必要があります。それでうまくいくかもしれませんが、ほとんどのことは私にはわかりません。少なくとも-stdinがパスワードを読み取る必要sudo
もsu
なければ、log_f()
宣言する必要があります。
ところで、これらの値をルートシェルの入力に展開するつもりだと私は信じています。そうするつもりがない場合はEOF
、var自体を引用する必要があります。
私の場合、配列を渡す必要があり、いくつかの問題がありましたが、しばらくして配列の値をenv
-keyにエコーし、目的のコードをでラップしてbash -c '<intended code>'
、基本的に配列を再作成して成功しましたINNER_KEY=($<env_key>)
。例:
たとえば:
#!/usr/bin/env bash
PLUGINS=(foo bar baz)
sudo -u <some-user> -i env PLUGINS="`echo ${PLUGINS[@]}`" sh <<'EOF'
bash -c '
FOO=($PLUGINS);
echo values: \[${FOO[@]}\];
for pl in ${FOO[@]};
do echo value: $pl;
done;
'
EOF
問題は、次のようなことを直接実行できないことでした(を使用していませんbash -c '...'
)。
FOO=($PLUGINS);
for pl in ${FOO[@]};
...