[comp.unix.questions] Csh & foreach causing fork problems

880274d@aucs.AcadiaU.ca (Ralph Doncaster) (03/25/91)

I'm having problems with a script I made to mail all the students on our
system.   I often get a "fork: no more processes" error.
I assume this is because foreach starts a new process for each argument it is
given.
How can I solve this problem?
Here is the script:

#!/bin/csh
# bm (batch mailer) by Ralph Doncaster, Jan 25/91
# script to mail message to all accounts in /u/student
# usage: bm subject file
if ($#argv) then
	foreach i(`/bin/ls /u/student`)
		mail -s $1 $i < $2
		sleep 1
	end
	echo "Sending message file " $1 "to all accounts in /u/student."
else
	echo "Usage: bm subject file"
endif

-- 
+---------------------------------------------------------------------------+
|Ralph Doncaster        I don't have anything interesting to put in my .sig |
|880274d@AcadiaU.CA     330 CHI, Acadia U., Wolfville, NS B0P 1X0  542-3010 |
|UUCP: {uunet|watmath|utai}!cs.dal.ca!aucs!880274d  BITNET: 880274d@Acadia  |   +---------------------------------------------------------------------------+

rickert@mp.cs.niu.edu (Neil Rickert) (03/25/91)

In article <1991Mar24.201730.14808@aucs.AcadiaU.ca> 880274d@aucs.acadiau.ca (Ralph Doncaster) writes:
>I'm having problems with a script I made to mail all the students on our
>system.   I often get a "fork: no more processes" error.
>I assume this is because foreach starts a new process for each argument it is
>given.
>
>#!/bin/csh
>if ($#argv) then
>	foreach i(`/bin/ls /u/student`)
>		mail -s $1 $i < $2
>		sleep 1
>	end

 Your problem is not really that 'foreach' is starting up a new process.
It is that 'mail' (which I presume is /usr/ucb/mail) is starting a new
process to put the delivery into the background.

 The real question is:

	Why on earth are you doing this?

 Why not send a single message to multiple recipients?  For example,
	mail -s $1 `/bin/ls /u/student` < $2
or even build the mail with the subject header (and perhaps a
'To: all-students:;' header)  in a file, and submit it to
/bin/mail with the list of recipients, or add a Bcc: header and submit
the message directly to sendmail with the -t operand.  Either way, only one
message is sent to multiple users, which should be considerably more efficient
and will certainly require less processes.

-- 
=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
  Neil W. Rickert, Computer Science               <rickert@cs.niu.edu>
  Northern Illinois Univ.
  DeKalb, IL 60115                                   +1-815-753-6940

phil@ux1.cso.uiuc.edu (Phil Howard KA9WGN) (03/26/91)

rickert@mp.cs.niu.edu (Neil Rickert) writes:

> Your problem is not really that 'foreach' is starting up a new process.
>It is that 'mail' (which I presume is /usr/ucb/mail) is starting a new
>process to put the delivery into the background.

> The real question is:

>	Why on earth are you doing this?

> Why not send a single message to multiple recipients?  For example,
>	mail -s $1 `/bin/ls /u/student` < $2

The usual reason for not doing this is that the header will end up having
a huge list of addresses that have to be skipped over to read the mail.
It is most annoying.

>or even build the mail with the subject header (and perhaps a
>'To: all-students:;' header)  in a file, and submit it to
>/bin/mail with the list of recipients, or add a Bcc: header and submit
>the message directly to sendmail with the -t operand.  Either way, only one
>message is sent to multiple users, which should be considerably more efficient
>and will certainly require less processes.

[FEWER processes]

If this successfully supresses the headers, great.  I suspect it might
require BCC: to do it.  An alternative might be to use the "-v" option
on mail.  That will cause /usr/ucb/mail to wait until the mail is actually
delivered or queued before exiting.  The disadvantage to this is that it
can take quite a while if hosts are not answering.  I usually stuff this
into the background anyway (logging output to a temp file, too).

Neil, can you confirm which of your methods actually avoids sending all
the headers to recipients?  I might like to use your ideas if so.
-- 
 /***************************************************************************\
/ Phil Howard -- KA9WGN -- phil@ux1.cso.uiuc.edu                              \
\ Lietuva laisva -- Brivu Latviju -- Eesti vabaks                             /
 \***************************************************************************/

hyc@hanauma.jpl.nasa.gov (Howard Chu) (03/26/91)

In article <1991Mar24.201730.14808@aucs.AcadiaU.ca> 880274d@aucs.acadiau.ca (Ralph Doncaster) writes:
>I'm having problems with a script I made to mail all the students on our
>system.   I often get a "fork: no more processes" error.
>I assume this is because foreach starts a new process for each argument it is
>given.
>How can I solve this problem?
>Here is the script:
>
>#!/bin/csh
># bm (batch mailer) by Ralph Doncaster, Jan 25/91
># script to mail message to all accounts in /u/student
># usage: bm subject file
>if ($#argv) then
>	foreach i(`/bin/ls /u/student`)
>		mail -s $1 $i < $2
>		sleep 1
>	end
>	echo "Sending message file " $1 "to all accounts in /u/student."
>else
>	echo "Usage: bm subject file"
>endif

I'd replace this with an alias, something like:
	alias bm '(cd /u/student; set list=(*); mail -s \!:1 $list < \!:2)'

Note that in any case, you must quote the subject that you specify if it's
going to be more than 1 word.
-- 
  -- Howard Chu @ Jet Propulsion Laboratory, Pasadena, CA
	Disclaimer: How would I know, I just got here!