wal*_*auf 9 bash ksh sudo environment-variables function
我已经在 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
Run Code Online (Sandbox Code Playgroud)
sudo su -,这是一种复杂的写作方式sudo -i,构建了一个原始的环境。这就是登录shell的意义所在。即使是普通的也会sudo从环境中删除大多数变量。此外sudo是一个外部命令;无法在 shell 脚本本身中提升权限,只能运行sudo具有额外权限的外部程序 ( ),这意味着在父 shell 中定义的任何 shell 变量(即非导出变量)和函数将不可用子壳。
您可以通过不调用登录外壳程序(sudo bash而不是sudo su -或sudo -i)并配置 sudo 以让这些变量通过(在文件中Defaults !env_reset或Defaults env_keep=…在sudoers文件中)来传递环境变量。这对函数没有帮助(尽管 bash 具有函数导出功能,但 sudo 会阻止它)。
在子 shell 中获取函数的正常方法是在那里定义它们。注意引用:如果<<EOF用于here文档,here文档的内容首先被父shell展开,展开的结果成为子shell看到的脚本。也就是说,如果你写
sudo -u "$target_user" -i <<EOF
echo "$(whoami)"
EOF
Run Code Online (Sandbox Code Playgroud)
这将显示原始用户的名称,而不是目标用户的名称。为了避免这个第一阶段的扩展,在<<操作符后面引用 here 文档标记:
sudo -u "$target_user" -i <<'EOF'
echo "$(whoami)"
EOF
Run Code Online (Sandbox Code Playgroud)
因此,如果您不需要将数据从父 shell 传递到子 shell,则可以使用此处引用的文档:
#!/bin/bash
sudo -u "$target_user" -i <<'EOF'
log_f() {
echo "LOG line: $@"
}
intVAR=$(date)
log_f "${intVAR}"
EOF
Run Code Online (Sandbox Code Playgroud)
虽然您可以使用不带引号的 here 文档标记将数据从父 shell 传递到子 shell,但这仅适用于数据不包含任何特殊字符的情况。那是因为在像这样的脚本中
sudo -u "$target_user" -i <<EOF
echo "$(whoami)"
EOF
Run Code Online (Sandbox Code Playgroud)
的输出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
Run Code Online (Sandbox Code Playgroud)
如果您要传递多个变量,按名称传递它们将更具可读性。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
Run Code Online (Sandbox Code Playgroud)
请注意,如果您希望读取/etc/profile目标用户~/.profile,则必须明确读取它们,或者调用bash --login而不是sh.