使用 HEREDOC 在 shell 脚本内与不同用户循环数组不起作用

使用 HEREDOC 在 shell 脚本内与不同用户循环数组不起作用

我想在运行脚本时在不同用户内执行一组操作,因此我使用 HEREDOC 来执行此类操作,但无论我尝试什么替代方案,我都无法在 HEREDOC 内的循环中引用我的值。

在这种情况下,它打印第一行并退出。

#!/bin/bash

func () {
test=("$@")
sudo su - someuser <<- EOF
    echo "${test[*]}"
    for i in "${test[@]}" ; do
        echo "$i"
    done
EOF
}


arrVar=("AC" "TV" "Mobile" "Fridge" "Oven" "Blender")
arrVar+=("hello.   why would it fail now      with spaces then")

func "$arrVar"  ###### Tried this as well "${arrVar[@]}"

打印输出如下:

[root@ip-10-9-1-1 ~]# ./test.sh
AC

如果我删除 HEREDOC 并以 currentUser 身份运行,它就可以正常工作,但我需要以不同用户身份运行它。

编辑:@roaima 答案看起来很有希望,但我必须访问很多外部变量,因此按如下方式传递它们对我来说扩展性不够好。

sudo -u someuser bash -c ' ' -- "lot" "of" "variables" "$@"

所以我首先使用数组而不是字符串来解决这个问题,因为IFS在 HEREDOC 内部不受尊重,如果我发布我原来的问题,也许我会得到更好的答案。

所以它是:

cp="/usr/bin/cp"
rm="/usr/bin/rm"
mv="/usr/bin/mv"
exec_operations () {

    echo "Executing operations: $@"
    operations=$@
    date=$(date +%Y-%m-%d-%H-%M-%S)
    sudo su - someuser <<- EOF
    IFS=";"
    for operation in $operations ; do
        echo "Performing the following $operation with $cp, $rm & $mv"
    done
    unset IFS
EOF
}
text="cp /tmp/text.txt something/;cp /tmp/text2.txt something/;"
exec_operations "$text"

答案1

您的调用func "$arrVar"传递一个字符串而不是一个数组。该字符串恰好对应于数组的第一个元素,这就是为什么您在循环中只看到第一个值(只有一个值)。

用这个代替

func "${arrVar[@]}"

您还需要注意,未加引号的定界符符号EOF意味着括弧被视为位于双引号中。这反过来意味着对变量的任何引用(例如)$i将被评估为定界文档的一部分,而不是作为其执行的一部分。双引号也将作为扩展的一部分进行处理,而不是执行。你的sudo su) 构造因此会看到类似这样的内容:

echo 'AC TV Mobile Fridge Oven Blender hello.   why would it fail now      with spaces then'
for i in 'AC TV Mobile Fridge Oven Blender hello.   why would it fail now      with spaces then' ; do
    echo ''
done

像这样的东西应该对你有用。我扩展了您的示例来回答您修改后的问题,询问如何传递额外的变量:

#!/bin/bash

func () {
    sudo -u someuser bash -c '
        date=$1; shift
        test=("$@")
        echo "${test[*]}"
        for i in "${test[@]}"
        do
            echo "$date: $i"
        done
    ' -- "$@"
}

arrVar=("AC" "TV" "Mobile" "Fridge" "Oven" "Blender")
arrVar+=("hello.   why would it fail now      with spaces then")
date=$(date --utc +'%Y-%m-%d %H:%M')

func "$date" "${arrVar[@]}"

相关内容