How to export a variable from a subshell to the parent shell?


 
Thread Tools Search this Thread
Top Forums Shell Programming and Scripting How to export a variable from a subshell to the parent shell?
# 1  
Old 03-26-2012
How to export a variable from a subshell to the parent shell?

A not-too-ugly solution to this classic problem...
Code:
#!/bin/bash

mknod fifo p
 
(
       echo 'value' > fifo &
)
 
VARIABLE=`cat fifo`
rm fifo

Whatdcha think? Good? No good?
# 2  
Old 03-26-2012
What happens if you have more than 1 instance if this script running?

I would suggest generating a temp filename for the pipe and passing it to the child.
This User Gave Thanks to Chubler_XL For This Post:
# 3  
Old 03-26-2012
Quote:
Originally Posted by Chubler_XL
What happens if you have more than 1 instance if this script running?

I would suggest generating a temp filename for the pipe and passing it to the child.
Excellent point. Then, maybe something like:
Code:
#!/bin/bash

TMPFIFO="/tmp/fifo.$$"
 
mknod $TMPFIFO p
 
(
       echo 'value' > $TMPFIFO &
)
 
VARIABLE=`cat $TMPFIFO`
rm $TMPFIFO

Thank you.

Last edited by vomv1988; 03-26-2012 at 02:15 AM..
# 4  
Old 03-26-2012
Quote:
Originally Posted by vomv1988
Excellent point. Then, maybe something like:
Code:
#!/bin/bash

TMPFIFO="/tmp/fifo.$$"
 
mknod $TMPFIFO p
 
(
       echo 'value' > $TMPFIFO &
)
 
VARIABLE=`cat $TMPFIFO`
rm $TMPFIFO

Thank you.
Yes or
Code:
#!/bin/bash

PIPE="/tmp/pipe.$$"
mkfifo $PIPE

(
echo 'value' > $PIPE &
)

VARIABLE=`cat $PIPE`
echo $VARIABLE
rm $PIPE

Code:
#!/bin/bash

TMPF="/tmp/tmpf.$$"
mktemp $TMPF >/dev/null

(
echo 'value' > $TMPF
)

VARIABLE=`cat $TMPF`
echo $VARIABLE
rm $TMPF

This User Gave Thanks to ygemici For This Post:
# 5  
Old 03-26-2012
I would use mkfifo instead of mknod. You do not need the ( ) in this case.. If you have more than one write statement, it is better to use exec, otherwise VARIABLE=`cat $TMPFIFO` goes on after the first command writes an EOF and the sub process will not finish.
Code:
FIFO="/tmp/fifo.$$"
if ! [ -p "$FIFO" ]; then
  mkfifo "$FIFO"
fi
{ exec >"$FIFO"; sleep 2; ps -f ;echo "hello from $FIFO" ;} &
var=$(< "$FIFO")
rm "$FIFO"
echo "$var"

In ksh93 you can use coprocesses:
Code:
#!/bin/ksh
{ sleep 2; ps -f ;echo "hello from coproc" ;} |&
var=$(<&p)
echo "$var"

---------- Post updated at 11:44 ---------- Previous update was at 10:45 ----------

bash 4:
Code:
#!/bin/bash
coproc TEST { sleep 2; ps -f ;echo "hello from coproc" ;}
var=$(cat <&${TEST[0]})
echo "$var"


Last edited by Scrutinizer; 03-26-2012 at 05:56 AM..
This User Gave Thanks to Scrutinizer For This Post:
# 6  
Old 03-26-2012
Quote:
Originally Posted by Scrutinizer
I would use mkfifo instead of mknod. You do not need the ( ) in this case.. If you have more than one write statement, it is better to use exec, otherwise
I agree with your mkfifo sugestion, but in regards to my usage of (), let me explain:

Suppose you want to extract a fixed amount of data, say, 20 bytes, from a device file which spits data out in asynchronous patterns, such as /dev/mouse.

The device file/dev/mouse will sometimes be spitting bytes out, and will sometimes not, depending on how the user moves the cursor around, so you really can't know when exactly you're going to get your 20 bytes from it.

So what do you do? You run dd to get 20 bytes from /dev/mouse, like so:

Code:
dd if=/dev/mouse bs=1 count=20

But this ofcourse freezes the execution of your script until /dev/mouse has produced the 20 required bytes. What do you do then?, well, you run it in the background:

Code:
dd if=/dev/mouse bs=1 count=20 &

But then, this only allows you to output the 20 bytes to stdout and, where's the fun in that? If you wanted to manipulate the 20 bytes in some way or another, you would need to either:
  1. Store them in a binary temp file, or
  2. Store them in a variable
The disadvantage of using binary temp files is that you waste slow HDD cycles and it just makes your code look plain ugly. So we decide to go with variable storage: it uses RAM instead, it's non intrusive with your filesystem and it doesn't carry all the cumbersome complications of checking for occupied filenames and the such. Thus, we unsuspectingly attempt to:

Code:
VAR=`dd if=/dev/mouse bs=1 count=20` &

Which obviously fails, because & runs your background processes in a child shell, which cannot alter it's parent's environment. At this point you can either give up and use the ugly temp.bin alternative:
Code:
dd if=/dev/mouse bs=1 count=20 of=/tmp/temp.bin.$$ &

Or...

3. Communicate with the parent from your background process using a fifo.

Like so:

Code:
TMPFIFO="/tmp/fifo.$$"
 
mkfifo $TMPFIFO
 
dd if=/dev/mouse bs=1 count=20 of=$TMPFIFO &

echo 'I can do something right after I tell dd to start listening'
echo 'to /dev/mouse, like telling my robotic arm to move the'
echo 'mouse around, or whatever :P!'
  
# This part WILL freeze the scrip though, at least
# until /dev/mouse is done with the 20 bytes.
VARIABLE=`cat $TMPFIFO`
rm $TMPFIFO

echo "Use \$VARIABLE for something... etc, etc: $VARIABLE"

This doesn't mess (so much) with your filesystem, uses only RAM, and is faster. I admit it shares with 1. the flaw of having to check for filenames... I only wish it could be perfect...

Anyway, that is why I needed my children talking back at their parents.

Thank you for your criticism, though, I truly appreciate your taking the time to read my post.

---------- Post updated at 01:06 PM ---------- Previous update was at 12:35 PM ----------

Quote:
Originally Posted by ygemici
Code:
#!/bin/bash

TMPF="/tmp/tmpf.$$"
mktemp $TMPF >/dev/null

(
echo 'value' > $TMPF
)

VARIABLE=`cat $TMPF`
echo $VARIABLE
rm $TMPF

mktemp huh... never heard of it, thanks for the tip!

Last edited by vomv1988; 03-26-2012 at 01:49 PM..
# 7  
Old 03-26-2012
@vomv1988: Thank you for the explanation. You started an interesting thread, I would not say it is criticism, but rather some hopefully helpful comments. Regarding the parentheses in your original script, I was only referring to them because I think they are superfluous...
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

Infinite "while" loop subshell loses current date variable

I have a simple script to log network connectivity to a set of systems. However, as expected the date appended to the log never changes because the new variable is lost when the loop starts again. Can someone clue me in on how to get around this issue? #!/bin/bash LOG=/tmp/netlog... (3 Replies)
Discussion started by: woodson2
3 Replies

2. Shell Programming and Scripting

How do I get variable defined in BASH subshell outside?

I'm a BASH shell user (relatively new) I need to get a variable calculated in a subshell, outside the subshell, when it completes. I can do it, by writing the variable into a file, and then reading the file again when outside the subshell. I've tried lots of things from exporting to environmental... (3 Replies)
Discussion started by: goreilly
3 Replies

3. Shell Programming and Scripting

Set/Export Env Vars from with Shell Script With Input Variable

I have a shell script I want to run that will set environment variables based on the value of an input variable submitted when the shell script is called. For example: $ mgenv.sh prod This would set environment variables for prod $ mgenv.sh test This would set environment variables... (1 Reply)
Discussion started by: brtaylor73
1 Replies

4. Shell Programming and Scripting

Exporting variables from subshell to parent shell

Hi, I was trying to do something where I would be able to export one local variable in a telnet subshell to its parent shell. I found something like this over here, but couldnt exactly understand it :(. I am referring to this part actually: #! /usr/bin/ksh exec 4>&1 tail -5 >&4 |& exec... (4 Replies)
Discussion started by: King Nothing
4 Replies

5. Shell Programming and Scripting

Makefile: Parent - Child Inheritance and export

Hi, I have a number of Makefiles, including a couple of files that I include in Makefiles, a few scripts that are executed through Makefiles, and I have problems with environment variables that are not inherited to the scripts properly. Simplified scenario: rootdir/Makefile: all: ... (1 Reply)
Discussion started by: Shompis
1 Replies

6. Shell Programming and Scripting

How to export a variable from a child process running in background to the parent

Hi All, I have a script which calls a child script with a parameter to be run in the background . childscript.ksh $a & Can any one suggest me how do i export a variable from the child script to parent script? Note that the child script is in background If the child script is in... (3 Replies)
Discussion started by: aixjadoo
3 Replies

7. Shell Programming and Scripting

full path of a file situated either in parent's dir. or parent's parent dir. so on...

hi experts(novice people can stay away as it is no child's game), i am developing a script which works like recycle bin of windows. the problem i am facing is that when ever i am trying to delete a file which is situated in parent directory or parent's parent directory i am unable to... (1 Reply)
Discussion started by: yahoo!
1 Replies

8. Shell Programming and Scripting

Environment Variable Parent PID

I have always used the "$$" environment variable to find the current process number. Is there any similar way or perhaps something else to easily find the parent process number? I realize I could do something like ps and grep for the process and cut or awk out the parent process but I wanted to... (1 Reply)
Discussion started by: scotbuff
1 Replies

9. UNIX for Dummies Questions & Answers

Export command giving Variable Name vs the Value set for the Variable

I'm having an issue when I export within my program. I'm getting the variable name, not the variable value. I have a configuration file (config.txt) that has the values of the variables set as so: set -a export ARCHIVEPOSourceDir="/interfaces/po/log /interfaces/po/data" export... (2 Replies)
Discussion started by: ParNone
2 Replies

10. Shell Programming and Scripting

Perl: export variable to shell

Hi, I am running a series of scripts and I need to transport a particular variable across many scripts. I thougt of defining an environmental variable which I could access through. But I found that the variable dies as soon as the script ends.. Currently I write this variable to a temporary... (2 Replies)
Discussion started by: oldtrash
2 Replies
Login or Register to Ask a Question