Getting value of variable set in subprocess script
I am writing a shell script that executes another script by fetching it over the network and piping its contents into sh (ftp -o - $script | sh; or wget -O - |sh). Since this bypasses putting the script on the filesystem, this means I can't source the script directly (using . ), but rather it gets executed in a subprocess.
So here is my problem: When it comes to Unix processes, information can usually flow only from parent to child (when the parent establishes the child's environment at invocation). But is there a way that the calling script can get a value of a variable that is set in the called script? Could using co-processes solve this, with like read -p?
I know I can fetch the script unto my hard drive, and then source it. Or I can pipe the contents of the script from the network, and save the data I need to a temporary file, and then my main program can get the data from that file. But is there a way to bypass the filesystem alltogether?
And an importnat point: the called script does a lot of stuff on its own. I don't want all of its standard output to come back as input to the calling script, but only the value of a particular variable.
This is pretty cool: The following procedure allows you to write a script that sends some "normal" output, ie, to the terminal, but other output to its calling program, so that the caller can recieve info from this child process. It uses co-processes and redirection to acheive this.
First, the code of the script meant to be executed as a co-process and return a value to its caller, as well as do normal script stuff and send its output to the screen/stdout. Save this in a file called "coproc":
Code:
#!/bin/ksh
## this script is designed to be a run as a coprocess,
## yet selectively pass some of its output back to the
## co-process invoker--which is what usually occurs with co-processes--
## yet have the output of other commands directed directly to user's
## terminal, and not sent as input to the calling program
## put commands whose output is meant to go to caller here;
## this is default behavior for a co-process, before I do any redirection
echo "This message from me, the co-porcess, is meant to go to caller, as my stdout is automatically sent to my caller."
## save coproc's default stdout to temp file descriptor for later retrieval,
## and redirect coproc's stdout to user's terminal;
## the user's termial is determined by using tty command in caller, and saving its value in
## a paramter that is passed to coprocess, here TTY
exec 3>&1 >$TTY
### Put the commands meant for the terminal, not the caller, here:
echo
echo "This is directly to terminal from the co-process."
echo "The command tty in the co-process yilds: \"$(tty)\". This is of no use"
echo "But I inherited variable \$TTY from my caller, and its value here is: $TTY"
## redirect coproc's output back to starting default, which is to caller, and close the temporary fd we created
exec >&3 3>&-
## again, commands whose output is meant to go to caller
echo "This is 2nd output meant to go to calling program."
## coproc's does its fancy logic, and yields a value that the caller cares about
## here this fancy logic is mimicked by using $RANDOM
RESULT_OF_COPROC_LOGIC=$RANDOM
echo "$RESULT_OF_COPROC_LOGIC"
Now here is the code of the calling program. Save this in a file called "coproc_caller", in the same dierectory as "coproc".
Code:
#!/bin/ksh
# this program *executes* another script--i.e., as a child subprocess, not as a
# sourced program, but yet is able to retrieve a value from this child
# process. Does this by creating the child process as a co-process
# determine which device file is user's terminal, save this in a
# variable, and pass this variable to all child processes by exporting it
# to the environment
export TTY=$(tty)
echo "The command tty in the caller yields: $(tty)"
# execute the script as a co-process; here I am executing it by piping its contents
# into a shell as its stdin, meant to mimick what could be done when script
# is on network (of course in this test my script is actuaally on filesystem,
# so I could have executed it simply by calling its name)
# (If script were on the network, the "cat" would here be ftp or wget)
cat ./coproc | ksh |&
# ./coproc |& # executes script from filesystem; should be identical to previous
# use read -p to read coproc's output
read -p
echo -e "\nFirst ouput of coproc is: $REPLY"
read -p
echo -e "\nThis is the 2nd read from coproc: $REPLY"
read -p NEEDED_VALUE
echo -e "\The real reason I executed coproc was so that it can do a bunch of stuff; but I also needed to get a value from it."
echo "I can store that value in a variabel to use it. That value is: $NEEDED_VALUE"
Now, execute coproc_caller, and here is its output:
Quote:
The command tty in the caller yields: /dev/ttyp0
First ouput of coproc is: This message from me, the co-porcess, is meant to go to caller, as my stdout is automatically sent to my caller.
This is directly to terminal from the co-process.
The command tty in the co-process yilds: "not a tty". This is of no use
But I inherited variable $TTY from my caller, and its value here is: /dev/ttyp0
This is the 2nd read from coproc: This is 2nd output meant to go to calling program.
The real reason I executed coproc was so that it can do a bunch of stuff; but I also needed to get a value from it.
I can store that value in a variabel to use it. That value is: 17409
So it works. But one more note: When I pipe the content of the coproc script into a shell, I get this error message after the code runs cleanly:
Quote:
./coproc_caller[17]: internal error: exchild: execute() returned
But I don't get this when my coproc_caller program executes the script by simply calling its name. Anyone have any suggestions what is going on? I think it may have to do with the fact that the co-process "operator" |& causes the entire pipeline to be part of the co-process. So e.g., cat $script | ksh |& causes the cat command also to be part of the coprocess. But then in this case, maybe the cat process gets entangled in the i/o redirectoins I set up in the co_proc script, but it can't handle these redirections. (By the way, the shell being used here is OpenBSD's version of pdksh, which is the standard shell on that OS.)
I originally had a script written in pure shell that I used to parse logs in real time and create a pipe delimited file that only contained errors. It worked but it was using a lot of memory (still not clear on why). I originally got around this by writing a wrapper for the script that ran on cron... (1 Reply)
Hi,
Will following set up work in bash script? I've got errors if assigning following binary command to a variable. But on the other hand, COMMAND="ls" works. Any explanation please? How can I assign binary command to a variable COMMAND then I can just call ${COMMAND}?
COMMAND="rsync"... (3 Replies)
greetings,
i have a sh script that calls a python script. the sh script sets an env variable BIN:
export BIN=bin64i need to get that BIN variable's value and use it within this python script. anyone know how to do this? thanx in advance. (5 Replies)
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)
first of all, thanks to all on this board, it has been a huge resource to answer most of my questions!
I am stuck on something that should really be simple, and was looking for some help.. I am using KSH on solaris and working on a script to move containers from server to server. Where i am... (4 Replies)
Can someone tell me why I'm getting error when I try to run this?
#!/bin/csh -f
source ~/.cshrc
#
set SQLPLUS = ${ORACLE_HOME}/bin/sqlplus
#
set count=`$SQLPLUS -s ${DB_LOGIN} << END
select count(1) from put_groups where group_name='PC' and description='EOD_EVENT' and serial_number=1;... (7 Replies)
hi all
i have joined new to the group.
i have set an variable in my bashrc file.
.bashrc
PROGHOME=/home/braf/braf/prog
export PROGHOME
but while using it in my shell script its path is not taken and i had to explicitly give the export command to set the path.
in my script... (8 Replies)
I want to check to see if a variable is set - and if not set it to something
ie. variable name test
I want to check if $test is set
then if there is nothing set against this currently - then set it to 0
Whats the best / shortest way of doing this in a script? (3 Replies)