
bash / kshに宣言された関数と変数があり、それを次に渡す必要がありますsudo su - {user} << EOF
。
#!/bin/bash
log_f() {
echo "LOG line: $@"
}
extVAR="yourName"
sudo su - <user> << EOF
intVAR=$(date)
log_f ${intVAR} ${extVAR}
EOF
答え1
sudo su -
複雑な書き込み方法を使用してsudo -i
素朴な環境を作成します。これがログインシェルのすべてです。通常のsudo
環境でもほとんどの変数が削除されます。外部コマンドもありますsudo
。シェルスクリプト自体の権限を昇格させる方法はなく、sudo
追加の権限を使用して外部プログラム( )を実行するだけです。つまり、シェル変数(エクスポートされていない変数など)と関数の親シェルはシェルです。
代わりに、sudo bash
ログインシェルを呼び出さずにその変数がファイルまたはファイルから渡されるようにsudoを設定して、環境変数を渡すこともできます。これは機能には役立ちません(bashには機能エクスポート機能がありますが、sudoはそれをブロックします)。sudo su -
sudo -i
Defaults !env_reset
Defaults env_keep=…
sudoers
サブシェルから関数を取得する一般的な方法は、サブシェルで関数を定義することです。引用に注意してください。<<EOF
hereドキュメントを使用する場合、hereドキュメントの内容は最初に親シェルによって拡張され、その拡張の結果はサブシェルに表示されるスクリプトになります。つまり、文章を書くと
sudo -u "$target_user" -i <<EOF
echo "$(whoami)"
EOF
ターゲットユーザー名の代わりに元のユーザー名が表示されます。ステップ1の拡張を防ぐには、演算子の後に文書マークアップを引用してください<<
。
sudo -u "$target_user" -i <<'EOF'
echo "$(whoami)"
EOF
したがって、親シェルから子シェルにデータを渡す必要がない場合は、ここで引用したドキュメントを使用できます。
#!/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
。
答え2
起動したシェルで関数が宣言されlog_f
ていないため、機能しません。sudo su -
代わりに:
extVAR="yourName"
sudo su - <user> << EOF
log_f() {
echo "LOG line: $@"
}
intVAR=$(date)
log_f ${intVAR} ${extVAR}
EOF
ルートサブシェルで定義された関数を取得する必要があります。それはうまくいくかもしれませんが…私はほとんどのことが何をしているのかわかりません。少なくとも標準入力が要求されない場合、またはパスワードの読み取りに必要でない限り、これは宣言する必要がありsudo
ますsu
。log_f()
ちなみに、私はあなたがルートシェルの入力にこの値を拡張したいと思います。そうしたくない場合は、EOF
変数自体を引用する必要があります。
答え3
私の場合、配列を渡す必要があるため、いくつかの問題がありましたが、しばらくすると、配列の値を-keyにエコーし、env
予想されるコードをラップしてデフォルト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[@]};
...