将函数和变量转发到 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,构建出质朴的环境。这就是登录 shell 的意义所在。即使是普通的也会sudo从环境中删除大多数变量。此外sudo还有一个外部命令;没有办法提升 shell 脚本本身的权限,只能以sudo额外的权限运行外部程序 ( ),这意味着父 shell 中定义的任何 shell 变量(即非导出变量)和函数在孩子的外壳。

您可以通过不调用登录 shell(sudo bash而不是sudo su -sudo -i)并配置 sudo 让这些变量通过(在文件中Defaults !env_reset或在文件Defaults env_keep=…sudoers)来传递环境变量。这对您的函数没有帮助(尽管 bash 有函数导出工具,但 sudo 会阻止它)。

在子 shell 中获取函数的正常方法是在那里定义它们。注意引用:如果您使用<<EOFhere文档,则here文档的内容首先由父shell扩展,并且该扩展的结果成为子shell看到的脚本。也就是说,如果你写

sudo -u "$target_user" -i <<EOF
echo "$(whoami)"
EOF

这显示原始用户的名称,而不是目标用户的名称。为了避免第一阶段的扩展,请在运算符后面引用此处的文档标记<<

sudo -u "$target_user" -i <<'EOF'
echo "$(whoami)"
EOF

因此,如果您不需要将数据从父 shell 传递到子 shell,则可以使用此处引用的文档:

#!/bin/bash
sudo -u "$target_user" -i  <<'EOF'
log_f() {
echo "LOG line: $@"
}
intVAR=$(date)
log_f "${intVAR}"
EOF

虽然您可以使用未加引号的此处文档标记将数据从父 shell 传递到子 shell,但这仅在数据不包含任何特殊字符时才有效。那是因为在像这样的脚本中

sudo -u "$target_user" -i <<EOF
echo "$(whoami)"
EOF

的输出whoami变成了一些 shell 代码,而不是字符串。例如,如果whoami命令返回"; rm -rf /; "true,则子 shell 将执行该命令echo ""; rm -rf /; "true"

如果需要从父 shell 传递数据,一种简单的方法是将其作为参数传递。显式调用子 shell 并向其传递位置参数:

#!/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以设置子 shell 的环境变量。

#!/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 -您启动的 shell 中声明。反而:

extVAR="yourName"

sudo su - <user> << EOF

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

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

您需要获取根子 shell 中定义的函数。这也许可以,但是……我不知道大部分东西是做什么的。至少——只要标准输入既不需要sudo也不su需要读取密码——就应该log_f()声明这一点。

顺便说一句,我相信您的意思是将这些值扩展到根 shell 的输入中。如果您不想这样做,那么您应该引用EOF和变量本身。

答案3

就我而言,我需要传入一个数组并遇到了一些麻烦,但在一段时间后通过将数组的值回显到 -keyenv并将预期的代码包装在 中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[@]};
...

相关内容