Exporting a global variable from child to parent in shell scripts - linux

Is it possible to export a variable from a parent shell script to its children ?
Trying the execute the two following scripts it always returns to me 0 but I want it to return 3. I`ve also tried to export, set and add the variable error to the .bash_profile without success...
test.sh
$ cat test.sh
#!/bin/bash
error=0
./envtest.sh
echo $error
envtest.sh
$ cat envtest.sh
#!/bin/bash
source ./test.sh
test=3
error=$test
echo $error

Like #chepner commented, no.
When you invoke ./envtest.sh from within test.sh, a new process is created to run /bin/bash ./envtest.sh, and that process's environment is initialized with a copy of every environment variable from the parent process. No matter what you do inside envtest.sh, it can only impact the variables within its own environment; it cannot touch the variables in the parent's environment.

Related

shell script - how to use variables for a shell script without defining the variable in the script

Raspbian (Jessy) - root#Raspberry Pi - Putty
In the Terminal i type in
finalanswer=0
now i got a script with this code
#!/bin/bash
source /lib/lsb/init-functions
echo $finalanswer #just as a test
if [ ! "$finalanswer" = "0" ]
then
rm -r mnt/objects/all
log_warning_msg "All Files has been deleted" || true
touch its_over.txt
else
let finalanswer=1
log_action_msg "Var finalanswer was 0. setting back to 1" || true
fi
there is a cronjob that starts this script every hour
sooo. somewhere there must be an error.
because he is reading the Variable $finalanswer as nothing.
that means variables that has been defined outside of this script will not work?
how do i fix this?
Shell variables are not inherited by child processes. If you want a variable to be inherited, it has to be an environment variable. You create environment variables using the export command.
export finalanswer=0
or
finalanswer=0
export finalanswer
You can also export a variable just for the duration of a command by putting the assignment at the beginning of the command:
finalanswer=0 /path/to/script
Note that variables you assign in your shell will not be accessible to cron jobs. Variables can only be exported to processes that are descended from the shell, and processes run by cron are not related to your shell process. If you want to set a variable for use in a cron job, you can put the assignment into the crontab file itself.
You can define a variable for a single command by placing its definition before the command you wish to run:
$ VARIABLE=hunter perl -E 'say $ENV{VARIABLE}'
hunter
you can do the same thing for a cron entry:
*/10 * * * * VARIABLE=hunter <command>

incrementing an environmental variable

I need to increment an environmental variable by these steps:
envar=1
export envar
sh script_incrementation
echo $envar
where script_incrementation contains something like this:
#! /bin/sh
envar=$[envar+1] #I've tried also other methods of incrementation
export envar
Whatever I do, after exiting the script the variable remains with its initial value 1.
THanks for your time.
A shell script executes in its own shell, so you cannot affect the outer shell unless you source it. See this question for details of that discussion.
Consider the following script, which I will call Foo.sh.
#!/bin/bash
export HELLO=$(($HELLO+1))
Suppose in the outer shell, I define an environmental variable:
export HELLO=1
If I run the script like this, it run inside its own shell and will not affect the parent.
./Foo.sh
However, if I source it, it will just execute the commands in the current shell, and will achieve the desired affect.
. Foo.sh
echo $HELLO # prints 2
Your script can not change the environment of the calling process (shell), it merely inherits it.
So, if you export foo=bar, and then invoke sh (a new process) with your script, the script will see the value of $foo (which is "bar"), and it will be able to change its own copy of it – but that is not going to affect the environment of the parent process (where you exported the variable).
You can simply source your script in the original shell, i.e. run
source increment_script.sh
or
. increment_script.sh
and that will then change the value of the variable.
This is because sourceing a script avoids spawning a new shell (process).
Another trick is to have your script output the changed environment, and then eval that output, for example:
counter=$[counter+1]
echo "counter=$counter"
and then run that as
eval `increment_script.sh`

Two shell scripts using same variable

I have two shell scripts test1.sh and test2.sh.
In test1.sh I have the below statements :
In, test1.sh,I have a variable I whose value will be used by test2.sh
#!/bin/sh
I="10"
echo $I
In, test2.sh, the same value of the variable will be copied and printed
#!/bin/sh
J=$I
echo $J
I need to run both the scripts in crontab, I tried export command, but nothing worked.
Add this to you crontab :
. ./test1.sh && ./test2.sh;
And modify you test1.sh like that :
#!/bin/sh
export I="10"
echo $I
With . the first will be executed as source and will hold variables.
Both scripts are running in their own shell, and only share their environment with their parent process. If you want two separate shell scripts to share environment variables, the variables have to be set (and exported) in the parent process before calling the scripts.
You could also create a third script that only sets the variables, and source that script from the two main scripts.
If you want to use the output of test1.sh in script test2.sh, you have two options
store the output of test1.sh in a file and read that file back in test2.sh
call test1.sh from test2.sh
test2.sh:
#!/bin/sh
J=$(test1.sh)
echo $J
As #Joachim Pileborg already suggested, you can set (but not echo) variables in one script and source it in the other one
test1.sh
I="10"
J=20
K=30
test2.sh
source test1.sh
# do something with I, J, K

Why doesn't a shell get variables exported by a script run in a subshell?

I have two scripts 1.sh and 2.sh.
1.sh is as follows:
#!/bin/sh
variable="thisisit"
export variable
2.sh is as follows:
#!/bin/sh
echo $variable
According to what I read, doing like this (export) can access the variables in one shell script from another. But this is not working in my scripts.
If you are executing your files like sh 1.sh or ./1.sh Then you are executing it in a sub-shell.
If you want the changes to be made in your current shell, you could do:
. 1.sh
# OR
source 1.sh
Please consider going through the reference-documentation.
"When a script is run using source [or .] it runs within the existing shell, any variables created or modified by the script will remain available after the script completes. In contrast if the script is run just as filename, then a separate subshell (with a completely separate set of variables) would be spawned to run the script."
export puts a variable in the executing shell's environment so it is passed to processes executed by the script, but not to the process calling the script or any other processes. Try executing
#!/bin/sh
FOO=bar
env | grep '^FOO='
and
#!/bin/sh
FOO=bar
export FOO
env | grep '^FOO='
to see the effect of export.
To get the variable from 1.sh to 2.sh, either call 2.sh from 1.sh, or import 1.sh in 2.sh:
#!/bin/sh
. ./1.sh
echo $variable

exported variables are not reflected in "env" output

I ran the below script to set environment variables for oracle(oracle_env.sh which comes with oracle package itself).
ORACLE_HOME=/usr/lib/oracle/xe/app/oracle/product/10.2.0/server
export ORACLE_HOME
ORACLE_SID=XE
export ORACLE_SID
NLS_LANG=`$ORACLE_HOME/bin/nls_lang.sh`
export NLS_LANG
PATH=$ORACLE_HOME/bin:$PATH
export PATH
if [ $?LD_LIBRARY_PATH ]
then
LD_LIBRARY_PATH=$ORACLE_HOME/lib:$LD_LIBRARY_PATH
else
LD_LIBRARY_PATH=$ORACLE_HOME/lib
fi
export LD_LIBRARY_PATH
After that when I ran env to ensure that the variables are exported properly, I found no properties are exported(below is the output).
invincible:/home/invincible# /usr/lib/oracle/xe/app/oracle/product/10.2.0/server/bin/oracle_env.sh
invincible:/home/invincible# env | grep ORACLE_HOME
invincible:/home/invincible#
Now I am not sure whether variables are exported properly.If not what I have done wrong? Please help me out.
And one more thing, I am running as root.
The scripts only sets the environment inside the subshell it runs in. You should source it:
# POSIX
. /usr/lib/oracle/xe/app/oracle/product/10.2.0/server/bin/oracle_env.sh
or
# bash/ksh
source /usr/lib/oracle/xe/app/oracle/product/10.2.0/server/bin/oracle_env.sh
I believe that when you run a script, bash forks and execs the script in a new shell instance, any exports done in the script doesn't propagate back to your parent shell.
However it seems that you can simply execute your script with:
prompt$ . /path/to/script.sh # note the period!
Example:
prompt$ echo "export FOO=foobar" > /tmp/tst
prompt$ sh /tmp/tst
prompt$ echo $FOO
prompt$ . /tmp/tst
prompt$ echo $FOO
foobar
I believe you should use source to load that script.
source /usr/lib/oracle/xe/app/oracle/product/10.2.0/server/bin/oracle_env.sh
From man source:
source filename [arguments]
Read and execute commands from filename in the current shell environment and
return the exit
status of the last command executed from filename.
Exporting variables only makes them available to children of the shell you export them from. There is no way of changing the environment variables in the parent shell, as you seem to be trying to do. You can change the variables in the same shell by sourcing the script using the "dot" command:
. myscript

Resources