Switching user inside a shell script doesn't seem to work

Linux version : Oracle Linux 6.4
Shell : Bash

The following script will be run as root. During the execution, it should switch to oracle user and execute few commands.
After googling and searching within unix.com , I came up with the following syntax

## Enclosing all commands in double quotes with the following syntax

su -l anotheruser -c "command1;command2;command3;..."

## Using single quote like below didn't work for me

su -l anotheruser -c 'command1;command2;command3;...'

So, I created the following simple script called test.sh and executed it.
But it seems that the switch user using su didn't work properly.
/tmp/who.txt file shows root. It should show orace user if su worked properly.
/tmp/MYVAR2.txt is empty . It should show Duffy
/tmp/Instancename.txt is empty. It should show JUMBO1

# cat test.sh
#!/bin/bash
#Usage     :  /root/SCRIPTS/test.sh <Argument1>
echo -e "\n"

## Currently you are root user

## su to oracle user and run the following commands which are separated by semi colon

su -l oracle -c "export ORACLE_SID=$11;export MYVAR1=Stomper;export MYVAR2=Duffy; echo `whoami` >/tmp/who.txt;echo $1 >/tmp/Arg_name.txt;echo $ORACLE_SID >/tmp/Instancename.txt;echo $MYVAR2 >/tmp/MYVAR2.txt"

whoami ## Now you should be back as root
#

-- Executing the script

#
# test.sh JUMBO


root
#

--- Verifying the content of the files

# cat /tmp/who.txt
root
# cat /tmp/Arg_name.txt
JUMBO
#
#
# cat /tmp/MYVAR2.txt

# cat /tmp/Instancename.txt

#

The variable and command substitutions in the double-quoted string are performed by the parent shell, while it reads the string, before it invokes su.

Regards,
Alister

Because of the use of double quotes, echo `whoami` gets executed before the su - l takes place. What did not work for you, when you were using single quotes?

1 Like

you can try this

su -l oracle -c "export ORACLE_SID=$11;export MYVAR1=Stomper;export MYVAR2=Duffy; echo \`whoami\` >/tmp/who.txt;echo $1 >/tmp/Arg_name.txt;echo $ORACLE_SID >/tmp/Instancename.txt;echo $MYVAR2 >/tmp/MYVAR2.txt"
1 Like

Thanks everyone.

I tried enclosing in single quotes. But it doesn't work properly. Any Idea how I can fix this ?

# cat test_singleQuote.sh
#!/bin/bash
#Usage     :  /root/SCRIPTS/test_singleQuote.sh <Argument1>
# single quote variant of test.sh

echo -e "\n"

## Currently you are root user

## su to oracle user and run the following commands which are separated by semi colon

su -l oracle -c 'export ORACLE_SID=$11; echo $ORACLE_SID >/tmp/ORACLE_SID_VAR; export MYVAR1=Stomper; \
export MYVAR2=Duffy; echo `whoami` >/tmp/who.txt;echo $1 >/tmp/Arg_name.txt; echo $ORACLE_SID >/tmp/Instancename.txt; echo $MYVAR2 >/tmp/MYVAR2.txt'

whoami ## Now you should be back as root
#
#

--- Executing the script
#

# test_singleQuote.sh SOFIA


root

-- Verifying the contents of files

# cat /tmp/ORACLE_SID_VAR
1 ---------------------> I am expecting SOFIA1 :confused:
#
# cat /tmp/who.txt
oracle ---------------------> Worked as expected :slight_smile:
#
# cat /tmp/Arg_name.txt
----------------------> null. I was expecting SOFIA :confused:
#
# cat /tmp/MYVAR2.txt
Duffy ---------------------> Worked as expected :slight_smile:
#

Any Idea how I can fix this ?

Try this sample code:

#!/bin/bash
su -l guest -c "export a=$1;export b=$2;echo \`whoami\`>/tmp/me;echo \$a >/tmp/a;echo \$b>/tmp/b"
echo Now I am
whoami
echo -----------
echo Contentes of file me
cat me
echo -----------
echo Contentes of file a
cat a
echo -----------
echo Contents of file b
cat b

And this is the output I am getting:

./test.sh 1 2
Now I am
root
-----------
Contentes of file me
guest
-----------
Contentes of file a
1
-----------
Contents of file b
2
1 Like

Thanks Chacko, everyone
Your script works.
How does this work, when all the echo commands put together after the export commands ?

In this first code sample that u gave, all the $ symbol were given without escaping them. So what the shell was doing was expanding the variables first and then pass it to the su command. This variables being undefined in the shell in which you invoked them were expanded as blank and then passed to the su. So when you try to print them into a file using echo the actual variables that were getting printed was the one in the main shell and the not the one that was intended,i.e, the One which are in su.
That being said what I did was escape all the characters that might be expanded in the main shell and then pass it to su so that unwantef shell substitution/expansion do not take place.

That also being said the best approach to your issue would be to create another script which does all the things that the other user does and then call that script while you do su. That way you can avoid all these confusion.