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 &quot;Executing operations: $@&quot;
operations=$@
date=$(date +%Y-%m-%d-%H-%M-%S)
sudo su - someuser &lt;&lt;- EOF
IFS=&quot;;&quot;
for operation in $operations ; do
    echo &quot;Performing the following $operation with $cp, $rm &amp; $mv&quot;
done
unset IFS

EOF } text="cp /tmp/text.txt something/;cp /tmp/text2.txt something/;" exec_operations "$text"

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

Chris Davies
  • 116,213
  • 16
  • 160
  • 287
  • 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=("$@") – Chris Davies 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 – Chris Davies 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? – Chris Davies Aug 25 '23 at 21:32
  • yeah i wasnt sure, i was also trying using su <user> -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