assigning values to variables in the background

Dan Nelson dnelson at allantgroup.com
Wed Jan 16 03:44:24 UTC 2013


In the last episode (Jan 16), Nikos Vassiliadis said:
> On 1/15/2013 9:30 PM, Greg Larkin wrote:
> > On 1/15/13 12:42 PM, Nikos Vassiliadis wrote:
> >> A bit of an OT question. I am writing a bourne shell script that
> >> collects data from a router.  Since netstat & vmstat can run for a
> >> numbers of iterations I thought I would use just that:
> >>
> >> stats() ( nstats=`netstat -I ng0 -q 1 60 | tail -1` &
> >> rawdata=`vmstat -c 2 60 | tail -1` wait ...
> >>
> >> The logic was: 1. run the first process in the bg 2. run the second
> >> process 3. wait to make sure the first process has finished 4.
> >> continue further
> >>
> >> It makes perfect sense why this doesn't work. Both commands run in
> >> the foreground.
> >>
> >> I am going to split the time between netstat and vmstat. So, it
> >> will be 30 seconds of netstat and 30 seconds of vmstat.
> >>
> >> But I am still interested/curious how one should go for this using
> >> the shell. So, can this be done without files? Any thoughts?
> >
> > As far as I can tell, the backticks are what's causing the problem. 
> > Even though you put the first command in the background (maybe with the
> > & inside the backticks, though), the assignment to the nstats variables
> > causes the script to block.
> >
> > If you switch to using temp files, you may have more luck, e.g.:
> >
> > netstat -w 1 -I ng0 -q 60 | tail -1 > /tmp/netstat.$$ &
> > npid=`echo $!`
> > vmstat -w 2 -c 60 | tail -1 > /tmp/vmstat.$$ &
> > vpid=`echo $!`
> > wait $npid
> > nstats=`cat /tmp/netstat.$$`
> > rm -f /tmp/netstat.$$
> > wait $vpid
> > rawdata=`cat /tmp/vmstat.$$`
> > rm -f /tmp/vmstat.$$`

npid=$! is cleaner (no need to fork a subshell just to echo a variable), but
you don't even need that.  You can use just a single "wait" command to wait
for both processes to finish, then extract the output of both tempfiles.

> Yes, this looks probably like something I will use too.
> 
> Just for the fun of it and using a separator(Robert's idea), I came up
> with this:
> 
> > delay=10
> >
> > a=$(
> >   (
> >     echo netstat `netstat -I ng0 -q 1 $delay | tail -1` netstat
> >   ) &
> >   (
> >     echo vmstat `vmstat -c 2 $delay | tail -1` vmstat
> >   )
> > )
> >
> > echo $a

This works, but now you have both lines of info in a single variable, and it
may be more work to split the lines back out (also note that you can't
predict which line will be first).  If you want to stick with shell, either
zsh or bash would make short work of parsing this.

-- 
	Dan Nelson
	dnelson at allantgroup.com


More information about the freebsd-questions mailing list