[plug] Bash "Processing" Script

Bernd Felsche bernie at innovative.iinet.net.au
Sat Jun 12 00:55:34 WST 2004


On Friday 11 June 2004 23:06, Bernard Blackham wrote:
> On Fri, Jun 11, 2004 at 01:53:51PM +0800, Jay Turner wrote:
> > while [ true ]
> > do
> > 	sleep 3
> > 	echo -n "."
> > done
> >
> > Am I reading it correct that the 'while' is in the background
> > printing dots, until we kill the 'while' process

> 'while' is not a process. It is a control construct within the shell
> script - the process executing it is bash (or zsh, etc). You can

Piping or backgrounding a flow contruct creates a sub-process.

This creates inconvenience when doing something like:

	OIFS="$IFS"
	IFS=":"
	cat /etc/passwd |
	while read uname pwd uid gid gcos home shell ; do
	  if [ $uid -eq 0 ] ; then
	    root=$uname
	    break
	  fi
	done
	IFS="$OIFS"
	echo $root

Variables set in the other process will not be available in the
parent. Note that I've set the shell's input field separator to
the colon which separates fields in the /etc/passwd file.

If you need only get one value out of the flow construct,
then you can encapsulate the flow construct and the piping in a
"back-tick" command substitution construct e.g.

	root=`IFS=":" ; cat /etc/passwd |
		while read uname pwd uid gid gcos home shell ; do
		  if [ $uid -eq 0 ] ; then
		    echo $uname
		    break
		  fi
		done`

Similarly, one could use the 'set' command to set up a new "argument
list" to the shell program. e.g.

	set -- `IFS=":" ; cat /etc/passwd |
		while read uname pwd uid gid gcos home shell ; do
		  [ $uid -eq 0 ] && echo $uname
		done`
	echo $*

[Don't be distracted by the && (and) contruct. Look it up in the
manual :-)]

Anyway; I digress.
	
> break out of the while loop using a 'break' command however, so you
> could write Bernd's script in at least two other ways :

> dd <dd params> &
> DD_PID=$!
> while : ; do
>     sleep 3
>     echo -n "."
>     ps $DD_PID >/dev/null || break
> done
> (ps returns non-zero if it can't find the process and hence will
> break out of the loop)

Ahhh. one of the other 8.999999 million ways to skin this cat. :-)

Running ps is somewhat wasteful. A  "kill -0 $DD_PID" would test for
the background process much more efficiently.  kill doesn't actually
send a signal or terminate the process. The zero option tests for
the process ID's existence.

kill is also "cheap" as it's a builtin in most modern shells;
whereas ps is usually an external command. When I were a lad, kill
wasn't builtin and if you ran out of process table entries, you
couldn't kill anything. You had to sit tight and wait for something
to finish or crash the system.

> or even
>
> dd <dd params> &
> DD_PID=$!
> while ps $DD_PID > /dev/null ; do
>     sleep 3
>     echo -n "."
> done
> (as above, the loop only continues while the dd process exists)

dd <dd params> &
DD_PID=$!
while kill -0 $DD_PID 2>/dev/null ; do
	sleep 3
	echo -n "."
done

Redirection from the kill prevents an ugly error message for a
non-existent process from appearing.

-- 
/"\ Bernd Felsche - Innovative Reckoning, Perth, Western Australia
\ /  ASCII ribbon campaign | I'm a .signature virus!
 X   against HTML mail     | Copy me into your ~/.signature
/ \  and postings          | to help me spread!





More information about the plug mailing list