linux env command does not work as expected? - linux

These 2 lines work as expected:
$ env NEW=hello bash -c "env | grep hello"
NEW=hello
$ env NEW=hello bash -c "echo $PATH"
/bin:/usr/bin
But I don't know why the following does not work (as expected).
$ env NEW=hello bash -c "echo $NEW"
Any suggestion?

$ env NEW=hello bash -c "echo $NEW"
You're using double-quotes on the argument to bash here, so the $NEW in the argument is expanded by your current shell, not by the bash command you're executing. Since $NEW isn't set in your current shell, the command is expanded to bash -c "echo ".
Use single-quotes on the argument to solve this:
$ env NEW=hello bash -c 'echo $NEW'
hello

Related

why single quotes and double quotes works differently in "bash -c"?

While using bash -c option to spawn new shell before running shell script,
I encountered unexpected action.
When I use single quotes, new shell is spawned to run the script.
$ bash -c 'echo pid is $$'
pid is 53465
$ bash -c 'echo pid is $$'
pid is 53466
$ bash -c 'echo pid is $$'
pid is 53477
But double quotes didn't.
$ bash -c "echo pid is $$"
pid is 2426
$ bash -c "echo pid is $$"
pid is 2426
$ bash -c "echo pid is $$"
pid is 2426
I carefully read similar question and bash manual but could not find why.
Anyone knows the reason why?
So when you execute the command
$ command "echo pid is $$"
The double quotes ensure that the command command gets a string passed where all substitutions are done. So assuming that the pid of the interactive shell is 1234. You will get the equivalent
$ command "echo pid is 1234"
When you use single quotes, the command gets passed the string echo pid is $$ where $$ is just like any string. If the command is now bash, $$ has a special meaning
$ bash -c 'echo pid is $$'
So now you get the PID returned of the executed command bash and not of your interactive shell.

Bash: Creating a shell variable in a bash script that I can access from command line

I have very little experience working with bash. With that being said I need to create a bash script that takes your current directory path and saves it to a shell variable. I then need to be able to type "echo $shellvariable" and have that output the directory that I saved to that variable in the bash script. This is what I have so far.
#!/bin/bash
mypath=$(pwd)
cd $1
echo $mypath
exec bash
now when I go to command line and type "echo $mypath" it outputs nothing.
You can just run source <file_with_your_vars>, this will load your variables in yours script or command line session.
> cat source_vars.sh
my_var="value_of_my_var"
> echo $my_var
> source source_vars.sh
> echo $my_var
value_of_my_var
You have to export the variable for it to exist in the newly-execed shell:
#!/bin/bash
export mypath=$(pwd)
cd $1
echo $mypath
exec bash
Hello
'env -i' gives control what vars a shell/programm get...
#!/bin/bash
mypath=$(pwd)
cd $1
echo $mypath
env -i mypath=${mypath} exec bash
...i.e. with minimal environment.

bash -c variable does not get assigned

I am trying to execute the following command:
$ bash -c "var='test' && echo $var"
and only an empty line is being printed.
If I execute the same command without bash -c
$ var='test' && echo $var
test
the value assigned to $var is being printed. Could someone explain why I can't assign variables in the first example?
Double quotes expand variables, so your command is expanded to
bash -c "var='test' && echo"
if $var is empty when you run it. You can verify the behaviour with
var=hey
bash -c "var='test' && echo $var"
Switch the quotes:
bash -c 'var="test" && echo $var'

Set Env Var and Access From Bash Script

This is probably a really stupid question, but how do I set an Environment Variable in Bash, then access it in a shell script?
kkeiper#machine:/home/kkeiper $ export APIKEY="adsf"
In bash script
#!/bin/bash
echo $APIKEY; # prints a blank line
echo $(env | grep APIKEY); # wouldn't return APIKEY even if it did work, but this also prints a blank string
What you show should work! It does for me:
$ export APIKEY="asfw"
$ cat script.sh
#!/bin/bash
echo $APIKEY
env | grep APIKEY
$ bash -x script.sh
+ echo asfw
asfw
+ env
+ grep APIKEY
APIKEY=asfw
$ sudo bash script.sh
Password:
$
Note that you don't need the semicolons or the echo $(...) notation in the script — but they don't do any damage either.
(Tested Mac OS X 10.9 Mavericks, Bash 3.2.51. However, I don't expect it to matter. Only true Bourne shells don't support the export VAR=value notation — and you'll have to look hard to find a shell with that limitation these days; Solaris /bin/sh, perhaps.)
Example with sudo added after question in comments. Yes, sudo unsets stray environment variables such as APIKEY.
More notes on sudo:
$ env | wc -l
24
$ env | grep APIKEY
APIKEY=asfw
$ cat script.sh
#!/bin/bash
echo $APIKEY
env | grep APIKEY
env | wc -l
$ bash script.sh
asfw
APIKEY=asfw
23
$ sudo bash script.sh
18
$
One day, I'll investigate the what and the why for the difference between 24 and 23 environment variables without sudo being involved, but clearly sudo eliminated a number of variables (5 or 6, including APIKEY specifically).
How to ensure that environment variables are preserved?
If you know which ones need to be preserved, then:
The sudo man page says:
-E The -E (preserve environment) option will override the env_reset option
in sudoers(5)). It is only available when either the matching command
has the SETENV tag or the setenv option is set in sudoers(5).
You can arrange to relay the environment variables to the commands environment:
$ sudo -E bash script.sh
Password:
asfw
APIKEY=asfw
26
$ sudo bash -c "APIKEY='$APIKEY' bash script.sh"
asfw
APIKEY=asfw
SUDO_COMMAND=/bin/bash -c APIKEY='asfw' bash script.sh
19
$
The appearance of SUDO_COMMAND in the environment is interesting.
(Note that the bash script.sh notation is only needed because I've not made script.sh executable. If it was executable, I could type either script.sh or ./script.sh depending on whether it is in a directory on my $PATH or not.)

Executing a set of commands inside a new bash instance from as script

I'm trying execute a set of commands in a new bash session:
exec bash <<- EOF
ln -snf $JDK_REPO'/jdk'$1 $CURRENT;
JAVA_HOME=$(readlink -f $CURRENT);
echo $JAVA_HOME;
export PATH= $JAVA_HOME/bin:$PATH;
exec usejdk
EOF
I get this error :
warning: here-document at line 46 delimited by end-of-file (wanted `EOF')
I tried to debug it with whatswrongwithmyscript, I get :
Use <<- instead of << if you want to indent the end token.
Any suggestion to execute a set of commands in a new bash instance ?
doing it this way works for me:
cmd="
ln -snf $JDK_REPO'/jdk'$1 $CURRENT;
JAVA_HOME=$(readlink -f $CURRENT);
echo $JAVA_HOME;
export PATH= $JAVA_HOME/bin:$PATH;
exec usejdk"
bash <<< "$cmd"
The bash <<< "$cmd" is equivalent to echo "$cmd" | bash or bash -c "$cmd"

Resources