関数と変数をsudo suに渡す -<

関数と変数をsudo suに渡す -<

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 -iDefaults !env_resetDefaults env_keep=…sudoers

サブシェルから関数を取得する一般的な方法は、サブシェルで関数を定義することです。引用に注意してください。<<EOFhereドキュメントを使用する場合、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ますsulog_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[@]};
...

関連情報