0

I want to perform the set of actions inside a different user while running my script, so i am using HEREDOC to perform such actions, but no matter alternatives i try, i cannot able to reference my values in loop inside the HEREDOC.

In this case it prints the first line and exits.

#!/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[@]}"

prints the output as like this:

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

it works fine just fine if i remove the HEREDOC and run as currentUser, but i need to run this as Different User.

EDIT: @roaima answer looks to be promising , but i had to access lot of outside variables, hence passing them as below wouldn't scale well enough for me.

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

so i came to this question in the first place using arrays over strings because of the IFS being not respected inside HEREDOC, perhaps i will get better answer if i post my original issue.

so here it it is:

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"
  • Try this: `func "${arrVar[@]}"` – Edgar Magallon Jan 20 '23 at 08:44
  • Tangentially relevant: [Is there ever a good reason to run sudo su?](https://unix.stackexchange.com/q/218169) – terdon Jan 20 '23 at 11:04
  • "_because of the IFS being not respected inside HEREDOC_" - it is respected inside the heredoc, but you're not quoting it right. (And I'm not sure there is a correct way.) – roaima Jan 20 '23 at 11:30
  • i havent understood which part u meant that i have not quoted, i believe u meant in for loop, i have tried this as well it is no different `for operation in "${operations}" ; do` – Alapati Srikanth Chowdary Jan 20 '23 at 11:42

1 Answers1

3

Your invocation func "$arrVar" passes in a string rather than an array. The string happens to correspond to the first element of the array, which is why you see just the first value in your loop (there is only one value).

Use this instead

func "${arrVar[@]}"

You also need to be aware that the unquoted heredoc symbol EOF means that the enclosure is treated as being in double quotes. This in turn means that any reference to a variable such as $i will be evaluated as part of the heredoc, and not as part of its execution. Double quotes will be handled also as part of the expansion, not the execution. Your sudo su (ugh) construct will therefore see something like this:

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

Something like this should work for you instead. I've extended your example to respond to your revised question asking how to pass in extra variables:

#!/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[@]}"
roaima
  • 107,089
  • 14
  • 139
  • 261
  • but how do i access global variables in this block, like `date=$(date +%Y-%m-%d-%H-%M-%S)` inside this HEREDOC block ? – Alapati Srikanth Chowdary Jan 20 '23 at 10:18
  • Pass in the value before the `"test[@]}"` array, and pick it off inside the subscript before you assign `test=("$@")` – roaima Jan 20 '23 at 10:32
  • I have edited my question one moe time stating why it may not solve usecase that i had, i am more interested to knowing the answer for edited question than original question for which your answer was more accurate – Alapati Srikanth Chowdary Jan 20 '23 at 11:17
  • @AlapatiSrikanthChowdary don't use scalar variables to store commands. That way leads to even more problems – roaima Jan 20 '23 at 11:33
  • what if yoou need sudo to make the array? im trying to get a list of files in a dir that needs sudo privs for that, thats my arrray. the array i need to create inside the HEREDOC, as well as loop it. – Brian Thomas Aug 25 '23 at 19:47
  • @BrianThomas the original question here didn't need a heredoc. Are you really sure you need one? – roaima Aug 25 '23 at 21:32
  • yeah i wasnt sure, i was also trying using `su -c "command-to-run"`. i couldn't figure it out in time and ended running it without sudo by putting the file i needed into /tmp space. darn. I think one of the solutions i had actually worked, and was just returning empty results for another reason, so maybe both the HEREDOC and the su -c actually worked in hindsight. Thanks though! – Brian Thomas Aug 27 '23 at 23:39