関数と変数をsudo su-<user> << EOFに転送します


9

私は関数と変数を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

回答:


4

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ます。


1

起動log_fしたsudo su -シェルで関数が宣言されていないため、これは機能しません。代わりに:

extVAR="yourName"

sudo su - <user> << EOF

log_f() {
echo "LOG line: $@"
}

  intVAR=$(date)
  log_f ${intVAR} ${extVAR}
EOF

ルートサブシェルで定義された関数を取得する必要があります。それでうまくいくかもしれませんが、ほとんどのことは私にはわかりません。少なくとも-stdinがパスワードを読み取る必要sudosuなければ、log_f()宣言する必要があります。

ところで、これらの値をルートシェルの入力に展開するつもりだと私は信じています。そうするつもりがない場合はEOF、var自体を引用する必要があります。


1

私の場合、配列を渡す必要があり、いくつかの問題がありましたが、しばらくして配列の値を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[@]};
...
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.