Set env variable inside sudo statement - Linux shell - linux

I need to modify an environment variable inside a sudo statement. The sudo statement includes some instructions.
In the example, I set the environment variable VAR1 with the value "ABC".
Then, in the sudo statement (and only here), I need to change that value to "DEF". But the value did not change after I set the value to "DEF". Echo commands return "ABC" as the value of VAR1.
How can I change/set the value of the variable inside the sudo statement?
Here an example of the code I run:
#!/bin/bash
export VAR1="ABC"
sudo -u <user> -i sh -c "
export VAR1="DEF";
echo $VAR1;
"
echo $VAR1;
Extra info: I tryed the option -E of sudo, to preserve the environment variable at the moment of sudo invocation (source: https://unix.stackexchange.com/questions/337819/how-to-export-variable-for-use-with-sudo/337820), but the result did not change:
#env VAR1="DEF" sudo -u <user> -E -i sh -c " [...]"

Use single quotes to prevent the outer shell from interpolating $VAR1. You need $VAR1 to be passed to the inner shell so it can expand it.
sudo -u <user> -i sh -c '
export VAR1="DEF"
echo "$VAR1"
'
It's also a good idea to quote variable expansions to prevent globbing and splitting mishaps: write "$VAR1" instead of $VAR1.
(The semicolons aren't necessary since you have newlines.)

Try this
export VAR1="ABC"
sudo -u <user> -i sh -c '
export VAR1="DEF"
echo "${VAR1}"
'
echo $VAR1;
as John Kugelman pointed out, you should use ' instead of " to wrap your command to avoid shell vars interpolation. Also, when referencing to VAR inside the command, use "${}" instead of $, this is what did the trick for me

Related

How to deal with multiple quotes in one line bash command?

For example, if my goal is that run a one-line bash command like this,
sudo bash -c ' sudo bash -c '' sudo bash -c ''' echo ''''1234'''' ''' '' '
It doesn't work.
Also I tried the 2nd commnad,
sudo bash -c ' sudo bash -c " sudo bash -c ''' echo ""1234"" ''' " '
Not work neither.
sudo bash -c ' sudo bash -c " echo '''123''' " '
the 3rd one, it indeed works, but it only has 3 levels at the top.
So, is there an actual way to get this command work with only quotes trick?
How to deal with multiple quotes in one line bash command?
Use functions, declare -f and printf "%q" to properly quote stuff. Don't do it yourself.
# Function to run, just normally write stuff to execute.
work() {
echo "1234"
}
# Script to run - contains work function definition and calls work.
script="$(declare -f work); work"
# bash -c "$script"
# quote it
script2="$(printf " %q" bash -c "$script")"
# bash -c "$script2"
# Well, no point, but an example, quote it again:
script3="$(printf " %q" bash -c "$script2")"
bash -c "$script3"
printf "%q " bash -c "$script3"
outputs:
1234
bash -c \ bash\ -c\ \\\ bash\\\ -c\\\ \\\$\\\'work\\\ \\\(\\\)\\\ \\\\n\\\{\\\ \\\\n\\\ \\\ \\\ \\\ echo\\\ \\\"1234\\\"\\\\n\\\}\\\;\\\ work\\\'
You can copy the bash -c .... line to your terminal and execute it.
If you want different quotation style, you can use bash special ${var#Q} variable expansion or /bin/printf executable from coreutils.
Is there an actual way to get this command work with only quotes trick?
No. Quotes are grouped in pars, writing multiple quotes is useless and used for readability. In your example 'bash -c ''''1234''''' is just 'qouted stuff'unqouted stuff'quoted stuff'unqouted stuff' etc... Doing '''' changes nothing. You have to escape \' quotes to preserve literal meaning of them.

How environment variables can be read from a file when going into a login shell with here-string and using the sudo command?

I am trying to write a small script that aims to login to a remote server, load environment variables and print one of them. (In the actual script, instead of an echo, the parameters that are read are to be used. For the sake of simplicity here I am using just echo.)
The structure of the script and the commands that I tried are as follows but unfortunately none succeeds:
ssh -i lightsail.pem ubuntu#production <<< '
sudo echo $TEST_PARAMETER
sudo sh -c "~/Environment/environment-variables.sh && echo $TEST_PARAMETER"
sudo bash -c "~/Environment/environment-variables.sh && echo $TEST_PARAMETER"
sudo bash -c "source ~/Environment/environment-variables.sh && echo $TEST_PARAMETER"
sudo bash <<< "source ~/Environment/environment-variables.sh && echo $TEST_PARAMETER"
';
How environment variables can be read from a file when going into a login shell with here-string and using the sudo command?
If your environment variable is set for ubuntu and not root you will need to use sudo -E
-E Indicates to the security policy that the user wishes to preserve their existing environment variables

How to run .profile inside a script

I have to SU first and run a profile inside a script, when I ran below script..the profile is giving log to the terminal and the parameters resolved in profiel or not resolving for the next line.thanks in advance
if [ $owner = "user1" ]
then
su -c " . ~/.profile; cd $LOG_DOR; cat $job.log" - user1
else
echo "$owner not found"
fi
To read in a file to the current shell, use source
source ~/.profile
When the shell parses a double-quoted string, it does variable expansion on the contents (replacing $varname with the variable's value) before executing the command. In this case, since the LOG_DOR and job variables are defined in ~/.profile (and not in the script) and that means that
su -c " . ~/.profile; cd $LOG_DOR; cat $job.log" - user1
will be expanded to:
su -c " . ~/.profile; cd ; cat .log" - user1
Which isn't what you want at all. To defer expansion of the variables, you can use single-quotes instead of double:
su -c ' . ~/.profile; cd $LOG_DOR; cat $job.log' - user1
But I'll actually recommend a couple of other changes as well: Put double-quotes around the variable references, to avoid possible problems when they do get expanded, and join the commands with && (instead of ;) so that if one fails it skips the rest (rather than blindly trying to continue):
su -c '. ~/.profile && cd "$LOG_DOR" && cat "$job.log"' - user1
EDIT: apparently in this case job is defined in the script, and LOG_DOR in ~/.profile; therefore the expansion of $job should be done immediately, and $JOB_DOR deferred. Fortunately, it's possible to use double-quotes and escape (\) the $ for expansions you want deferred. You'll also need to escape some other special characters, like included double-quotes (which would end the string if not escaped). Here, I've also switched to single-quotes around the $job reference, in case it contains any special characters that'd otherwise cause trouble (although this will fail if it contains any single-quotes itself):
su -c ". ~/.profile && cd \"\$LOG_DOR\" && cat '$job.log'" - user1

Open new gnome-terminal from scripts and input vars from present script.

#!/bin/bash
Dpath=/home/$USER/Docker/
IP=`sed -n 1p /home/medma/.medmadoc`
DockerMachine=`sed -n 2p /home/$USER/.medmadoc`
DockerPort=`sed -n 5p /home/$USER/.medmadoc`
DockerUser=`sed -n 3p /home/$USER/.medmadoc`
DockerPass=`sed -n 4p /home/$USER/.medmadoc`
if [ ! -d $Dpath ] ; then
mkdir -p $Dpath
else
stat=`wget -O ".dockerid" http://$IP/DOCKER-STAT.txt`
for ids in `cat .dockerid`
do
if [ "$ids" == "$DockerMachine" ] ; then
gnome-terminal -x sh -c 'sshfs -p$DockerPort $DockerUser#$IP:/var/www/html $Dpath ; bash '
nautilus $Dpath
zenity --info --text "Mounted $DockerMachine"
exit
else
:
fi
done
zenity --info --text "No Such ID:$DockerMachine"
fi
gnome-terminal -x sh -c 'sshfs -p$DockerPort $DockerUser#$IP:/var/www/html $Dpath ; bash '
this command opens up a new terminal but the problem is that it does not load vars like $DockerPort $DockerUser $IP $Dpath from this script.
How do I input the values in these vars from this script to the newly opened terminal ?
Thanks !
As indicated before, you could try to use double quotes instead of single quotes around the sshfs invocation.
Single quotes in Bash are used to delimit verbatim text, in which variables are not expanded. Double quotes, in contrast, allow for variables expansion and command substitution ($(...)) to take place.
If you do use double quotes, beware of unintended side-effects (your username may contain a space, a dollar, a semicolon, or any other shell-special character). A cleaner approach would be to export the variables to the environment before calling gnome-terminal (and not forgetting to add double quotes around your variables inside the single-quotes), so that your code looks like :
export Docker{Port,User} IP Dpath
gnome-terminal -x sh -c 'sshfs -p"$DockerPort" "$DockerUser#$IP":/var/www/html "$Dpath" ; bash'
You may not want to pollute the environment with variables that will only be used once. If that is the case, instead of exporting them, you can use Bash's declare -p feature to serialize variables before loading them into a new environment (in my opinion, this is the cleanest approach). Here is what it looks like :
set_vars="$(declare -p Docker{Port,User} IP Dpath)"
gnome-terminal -x bash -c "$set_vars;"'sshfs ....'
Using this latest method, the variables are only visible to the shell process that runs the sshfs command, not gnome-terminal itself nor any sub-process run thereafter.
PS: you could read all your variables at once from the ~/.medmadoc file by using the following code instead of repeated sed invocations :
for var in IP Docker{Machine,User,Pass,Port}; do
read $var
done < ~/.medmadoc
This code makes use of the read builtin, that reads a line of input into a variable (in its simplest form).
PPS: That stat variable probably won't contain any useful information, since the output of wget was redirected by the -O flag. Perhaps you meant to store the result code of wget into stat, in which case what you meant was :
wget -O .dockerid ...
stat=$?

Multiple commands in sudo over ssh in shell script

My script is as below.
#!/bin/bash
version = 1.1
echo "Enter username"
read UserName
ssh -t $UserName#server bash -c " '
./runSomeScript
echo "Entering Sudo"
sudo -s -u user1 -c "cd random; ./randomscrip xx-$version-yy"
'"
But this is not working.
Basically i want to do a ssh to a account. And then runSomeScript
Then do a sudo with user as user1 and then run commands cd random and ./randomscrip (with xx-Version-yy as argument) as the sudo user only.
But the commands inside sudo are not working.
Your quoting is a little careless. You're using double-quotes for the first and third levels of quoting, and the shell can't tell one from the other. Do something like this instead:
sudoScript="cd random; ./randomscrip xx-${version}-yy"
sshScript='
./runSomeScript
echo "Entering Sudo"
sudo -s -u user1 bash -c '"'${sudoScript}'"'
'
ssh -t ${UserName}#server "${sshScript}"
But beware that if you embed any single-quotes, it will still go wrong unless you add a layer of shell-quoting.
Finally, remove the spaces around = when you assign to version.

Resources