将函数和变量转发到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

Answers:


4

sudo su -是一种复杂的写作方式sudo -i,它构建了一个原始的环境。这就是登录shell的重点。即使是平原也sudo可以从环境中删除大多数变量。而且sudo是一个外部命令;没有办法在shell脚本本身中提升特权,而只能以sudo额外的特权运行外部程序(),这意味着在父shell中定义的所有shell变量(即非导出变量)和函数都将不可用。子壳。

您可以通过调用不(登录shell传递环境变量sudo bash,而不是sudo su -sudo -i)和配置须藤通过(与让这些变量Defaults !env_resetDefaults env_keep=…将在sudoers文件)。这对功能没有帮助(尽管bash具有功能导出功能,但sudo会阻止它)。

在子外壳中获取函数的通常方法是在其中定义它们。请注意引用:如果<<EOF用于here文档,here文档的内容首先由父shell展开,并且扩展的结果成为子shell看到的脚本。也就是说,如果你写

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

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

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

虽然您可以使用此处未加引号的文档标记将数据从父外壳传递到子外壳,但这仅在数据不包含任何特殊字符的情况下才有效。那是因为在类似

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

的输出whoami变成了一些shell代码,而不是字符串。例如,如果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 -启动的shell中声明。代替:

extVAR="yourName"

sudo su - <user> << EOF

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

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

您需要获取在根子shell中定义的功能。也许可以做到,但是....我不知道大多数东西能做什么。至少-只要既不需要stdin sudo也不su需要读取密码-就应该log_f()声明它。

我相信您的意思是顺便将这些值扩展到根shell的输入中。如果您不打算这样做,则应引用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[@]};
...
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.