Define environment variable in a subshell with heredoc - linux

Background: testing a bash script inside a pod where default user does not have sudo rights so that user cannot user vim or nano to create a .sh file so I have to find a way around with cat << EOF >> test.sh.
I am doing some local test to make sure it's working properly first. Locally I am creating a file test.sh with nano. See below
#!/bin/bash
# test.sh
VAR="Test"
echo $VAR
When I cat it:
#!/bin/bash
# test.sh
VAR="Test"
echo $VAR%
I save test.sh , made it execuatble chmod +x test.sh and ran it with ./test.sh The output:
Test
Now when I try to mimic the same behavior in a bash heredoc instead this is the command I use:
cat <<EOF >> test.sh
#!/bin/bash
# test.sh
VAR="Test"
echo $VAR
EOF
I saved it and made it execuatble as well. The cat output is:
#!/bin/bash
# test.sh
VAR="Test"
echo
So obviously running it wouldn't work. The output null.
I think the issue I am facing is that the environment variable $VAR is not defined properly inside the subshell using heredoc.

When you write this:
cat <<EOF >> test.sh
#!/bin/bash
# test.sh
VAR="Test"
echo $VAR
EOF
...that $VAR is expanded by your current shell (just like writing something like echo "$VAR"). If you want to suppress variable expansion inside your heredoc, you can quote it (note the quotes around 'EOF'):
cat <<'EOF' >> test.sh
#!/bin/bash
# test.sh
VAR="Test"
echo $VAR
EOF
This inhibits variable expansion just like single quotes (echo '$VAR').

Related

How to enter docker container use shell script and do something?

I want to enter my container and do something, then leave this container.
#!/bin/bash
docker exec -i ubuntu-lgx bash << EOF
echo "test file" >> /inner.txt
ls -l /inner.txt
content=`cat /inner.txt`
echo ${conent}
# do something else
EOF
when I run this script, the bash tell me the file is not exist.but the ls can output the file's property.
cat: /inner.txt: No such file or directory
-rw-r--r--. 1 root root 58 Nov 14 11:51 /inner.txt
where am I wrong? and how to fix it?
The problem is that you're not protecting your "here" document from local shell expansion. When you write:
#!/bin/bash
docker exec -i ubuntu-lgx bash << EOF
content=`cat /inner.txt`
EOF
That cat /inner.txt is run on your local system, not the remote system. The contents of here document are parsed for variable expansion and other shell features.
To prevent that, write it like this:
#!/bin/bash
docker exec -i ubuntu-lgx bash << 'EOF'
echo "test file" >> /inner.txt
ls -l /inner.txt
content=`cat /inner.txt`
echo ${content}
# do something else
EOF
The single quotes in 'EOF' are a signal to the shell to interpret the here document verbatim.

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.

Can I call an interactive script in orther bash?

For example,there is an interactive script that read user input his name.And then write the name in a file.
#! /bin/bash
read name
echo $name>>name.txt
If I can't change the interactive script , how can I use anothor bash to quote the interactive script?
For example,I want to write a bash that extracts the name from a text and then calls this interactive script.
So can I achieve my idea?
Use a pipe to combine output of one program with the input of the next program:
echo 'name from other script' | ./script1.sh
echo can be replaced with any other executable file or script:
$ cat >script2.sh
#!/bin/sh
echo 'first input'
echo 'second input'
^D
$ chmod u+x script2.sh
$ ./script2.sh | ./script1.sh
If your intended input name is already in a file, use IO redirection instead:
$ ./script2.sh < file_containing_name.txt

Unable to use local and remote variables within a heredoc or command over SSH

Below is an example of a ssh script using a heredoc (the actual script is more complex). Is it possible to use both local and remote variables within an SSH heredoc or command?
FILE_NAME is set on the local server to be used on the remote server. REMOTE_PID is set when running on the remote server to be used on local server. FILE_NAME is recognised in script. REMOTE_PID is not set.
If EOF is changed to 'EOF', then REMOTE_PID is set and `FILE_NAME is not. I don't understand why this is?
Is there a way in which both REMOTE_PID and FILE_NAME can be recognised?
Version 2 of bash being used. The default remote login is cshell, local script is to be bash.
FILE_NAME=/example/pdi.dat
ssh user#host bash << EOF
# run script with output...
REMOTE_PID=$(cat $FILE_NAME)
echo $REMOTE_PID
EOF
echo $REMOTE_PID
You need to escape the $ sign if you don't want the variable to be expanded:
$ x=abc
$ bash <<EOF
> x=def
> echo $x # This expands x before sending it to bash. Bash will see only "echo abc"
> echo \$x # This lets bash perform the expansion. Bash will see "echo $x"
> EOF
abc
def
So in your case:
ssh user#host bash << EOF
# run script with output...
REMOTE_PID=$(cat $FILE_NAME)
echo \$REMOTE_PID
EOF
Or alternatively you can just use a herestring with single quotes:
$ x=abc
$ bash <<< '
> x=def
> echo $x # This will not expand, because we are inside single quotes
> '
def
remote_user_name=user
instance_ip=127.0.0.1
external=$(ls /home/)
ssh -T -i ${private_key} -l ${remote_user_name} ${instance_ip} << END
internal=\$(ls /home/)
echo "\${internal}"
echo "${external}"
END

Linux bash script: share variable among terminal windows

If I do this:
#!/bin/bash
gnome-terminal --window-with-profile=KGDB -x bash -c 'VAR1=$(tty);
echo $VAR1; bash'
echo $VAR1
How can I get the last line from this script to work? I.e., be able to access the value of $VAR1 (stored on the new terminal window) from the original one? Currently, while the first echo is working, the last one only outputs an empty line.
The short version is that you can't share the variable. There's no shared channel for that.
You can write it to a file/pipe/etc. and then read from it though.
Something like the following should do what you want:
#!/bin/bash
if _file=$(mktemp -q); then
gnome-terminal --window-with-profile=KGDB -x bash -c 'VAR1=$(tty); echo "$VAR1"; declare -p VAR1 > '\'"$_file"\''; bash'
cat "$_file"
. "$_file"
echo "$VAR1"
fi

Resources