kiyun@mirror.tmc.com (KiYun Roe) (03/20/91)
I've been encountering a problem with some of my shell scripts and SIGHUP that I don't understand. I run a lot of scripts overnight. These are usually named xsomething.sh. They may generate temporary files which I want to clean up. Here's what I want to use to start them off: #! /bin/sh type=`expr $0 : '.*x\(.*\)\.sh'` exec > x$type.log 2>&1 trap "rm -f /tmp/p$$.* ; exit" 0 1 2 13 15 This automatically redirects stdout and stderr to a log file and cleans up some temp files on exit or certain signals. The problem is that I log back in the next day and find out that the script has long finished its real work, but it's forking like crazy, trying to do the rm. I guess each time it tries to do the rm it receives a SIGHUP which forks another subshell to do the rm. I don't understand this. First, I thought that the -f flag would keep rm quiet, so I don't understand why it has to interact with the terminal at all. Second, I thought the exec > .. 2>&1 would redirect all output, but it doesn't. If I do "xsomething.sh >& save.out &" before I log out (I use tcsh), when I log back in save.out contains a Hangup message for each subshell and xsomething.log (the automatic log file) doesn't contain anything. Finally, most of the times there are temporary files to cleanup, so the globbing and rm should work normally. I can't figure out whether this is a bug in our version of sh or whether things are "supposed" to work this way. ---- KiYun Roe kiyun@mirror.TMC.COM Mirror Systems 2067 Massachusetts Avenue Cambridge, MA 02140 Telephone: 617-661-0777
tif@doorstop.austin.ibm.com (Paul Chamberlain) (03/21/91)
In article <53767@mirror.tmc.com> kiyun@mirror.tmc.com (KiYun Roe) writes: > trap "rm -f /tmp/p$$.* ; exit" 0 1 2 13 15 > >... but it's forking like crazy, Isn't this when you have to do this: trap "rm -f /tmp/p$$.* ; trap 0; exit" 0 1 2 13 15 If 0 is trapped when you try to exit, you trap, and so on ... Paul Chamberlain | I do NOT speak for IBM. IBM VNET: PAULCC AT AUSTIN 512/838-9748 | ...!cs.utexas.edu!ibmchs!auschs!doorstop.austin.ibm.com!tif
]) (03/22/91)
Here's how I handle tempfiles... Assume I need two of them and that I'll use $$ as part of the filename to allow for multiple copies of the script to run simultaneously. --- start junk (a sh or ksh script) --- : # Make and load a couple of temp files and trap for them to # be removed automagically on exit. TEMP1=/usr/tmp/junk1.$$ TEMP2=/usr/tmp/junk2.$$ trap 'rm -f $TEMP1 $TEMP2' 0 1 2 3 14 15 ls > $TEMP1 2>$TEMP2 echo "number of files: \c"; wc -l < $TEMP1 [ -s $TEMP2 ] && echo "number of error messages: \c"; wc -l < $TEMP2 --- end junk (a sh or ksh script) --- The thing about the trapped command is that you don't need to issue an exit from within the command-series. The sh (or ksh) will simply execute the command on its merry way out. Don't use $$ in filenames of tempfiles without loading the resulting filename into a simple variable. $$ changes value when you fork a subshell, for instance. This *might* be what led (combined with the exit in the trapped command-series) to the cascade of processes. ...Kris -- Kristopher Stephens, | (408-746-6047) | krs@uts.amdahl.com | KC6DFS Amdahl Corporation | | | [The opinions expressed above are mine, solely, and do not ] [necessarily reflect the opinions or policies of Amdahl Corp. ]
kiyun@mirror.tmc.com (KiYun Roe) (03/26/91)
Thanks to everyone who tried to help me with my problem. I determined that the problem was in a call to isatty(0) inside /bin/rm. To recap, I have a bunch of shell scripts that start off something like this: #! /bin/sh type=`expr $0 : '.*x\(.*\)\.sh'` exec > x$type.log 2>&1 trap "rm -f /tmp/p$$.* ; exit" 0 1 2 13 15 If I start one of these off in the background and log back on, I find that it has gone into an infinite SIGHUP loop. Apparently, what is happening is that /bin/rm calls isatty(0) which leads to a SIGHUP, which the shell traps, which calls /bin/rm, etc. I'm guessing at this, but I compiled a version of rm without the isatty(0) call and the script worked fine. (BTW, /bin/rm calls isatty to automatically set the -f option if the input isn't a terminal. I don't know if that's standard or unique to Pyramid Unix.) Some of you suggested that executing exit inside a trap handler would cause an infinite loop. Well, it doesn't on my machine, and I can't see how it would generate Hangup messages which was the most perplexing part of my problem. However, I would be interested in knowing if it really does cause an infinite exit loop under a different version of Unix. Anyway, here's the prolog I'm using for this particular class of scripts now: #! /bin/sh type=`expr $0 : '.*x\(.*\)\.sh'` exec > x$type.log 2>&1 trap "exec rm -f /usr/tmp/p$$.* < /dev/null" 0 1 2 13 15 I hope the exec will take care of any infinite loops, and redirecting stdin to /dev/null should keep rm out of trouble.
kiyun@mirror.tmc.com (KiYun Roe) (03/26/91)
In article <d2wB01ev46cG00@amdahl.uts.amdahl.com> krs@amdahl.uts.amdahl.com (Kris Stephens [Hail Eris!]) writes: >The thing about the trapped command is that you don't need to issue >an exit from within the command-series. The sh (or ksh) will simply >execute the command on its merry way out. My experience is that if I don't put an exit within the trap command series, the script doesn't exit when it receives a signal. It just cleans up the temp files and then continues to execute. I use a trap handler so that I can clean-up before aborting on a signal, not to keep the signal from aborting the script. So, the issue is whether an exit in the trap 0 handler will cause any harm (loop), but I've never had any problem with that. -- ---- KiYun Roe kiyun@mirror.TMC.COM Mirror Systems 2067 Massachusetts Avenue Cambridge, MA 02140 Telephone: 617-661-0777
]) (03/27/91)
In article <53902@mirror.tmc.com> kiyun@mirror.UUCP (KiYun Roe) writes: >In article <d2wB01ev46cG00@amdahl.uts.amdahl.com> krs@amdahl.uts.amdahl.com (Kris Stephens [Hail Eris!]) writes: >>The thing about the trapped command is that you don't need to issue >>an exit from within the command-series. The sh (or ksh) will simply >>execute the command on its merry way out. > >My experience is that if I don't put an exit within the trap command >series, the script doesn't exit when it receives a signal. It just >cleans up the temp files and then continues to execute. I use a trap >handler so that I can clean-up before aborting on a signal, not to keep >the signal from aborting the script. > >So, the issue is whether an exit in the trap 0 handler will cause any >harm (loop), but I've never had any problem with that. Okay, it ain't clear to me from reading ksh.1. If I.... trap 'echo "signalled"' 0 1 2 3 14 15 in a script (not in a function of the script), it *is* clear that 0 will echo "signalled" and exit. It's not clear to me what will happen on signals 1 2 3 14 15, though. Should this work to (a) echo "signalled" and (b) exit, without recursion: trap 'echo "signalled"; exit' 0 1 2 3 14 15 where by "without recursion" I mean successive firings on the trap? What would the exit code be if the trap is taken by execution of an 'exit 1' in the script? Would it be 0 because the echo was a success? Should I, instead, do: trap 'echo "signalled"' 0 trap 'echo "signalled"; exit' 1 2 3 14 15 to avoid a possible recursion and protect the exit code? Anyone *really* know? ...Kris -- Kristopher Stephens, | (408-746-6047) | krs@uts.amdahl.com | KC6DFS Amdahl Corporation | | | [The opinions expressed above are mine, solely, and do not ] [necessarily reflect the opinions or policies of Amdahl Corp. ]
lml@cbnews.att.com (l.mark.larsen) (03/30/91)
In article <c8C901q64a9q00@amdahl.uts.amdahl.com> krs@amdahl.uts.amdahl.com (Kris Stephens [Hail Eris!]) writes: # In article <53902@mirror.tmc.com> kiyun@mirror.UUCP (KiYun Roe) writes: # >In article <d2wB01ev46cG00@amdahl.uts.amdahl.com> krs@amdahl.uts.amdahl.com (Kris Stephens [Hail Eris!]) writes: # >>The thing about the trapped command is that you don't need to issue # >>an exit from within the command-series. The sh (or ksh) will simply # >>execute the command on its merry way out. This is only true of the 0 (aka EXIT in ksh) "interrupt" - as KiYun pointed out in his reply. # Okay, it ain't clear to me from reading ksh.1. If I.... # # trap 'echo "signalled"' 0 1 2 3 14 15 # # in a script (not in a function of the script), it *is* clear that 0 # will echo "signalled" and exit. It's not clear to me what will happen # on signals 1 2 3 14 15, though. # # Should this work to (a) echo "signalled" and (b) exit, without recursion: # # trap 'echo "signalled"; exit' 0 1 2 3 14 15 # # where by "without recursion" I mean successive firings on the trap? # What would the exit code be if the trap is taken by execution of an # 'exit 1' in the script? Would it be 0 because the echo was a success? No, it would be 0 because no argument is supplied to the exit. # Should I, instead, do: # # trap 'echo "signalled"' 0 # trap 'echo "signalled"; exit' 1 2 3 14 15 # # to avoid a possible recursion and protect the exit code? This won't protect the exit code either. # # Anyone *really* know? Well, let me give it my best shot... Think of traps as being like signal handlers in C under UNIX(TM). If you don't catch the signal, the default action is to terminate the program. The same is true of a shell script. You can ignore signals in a program. To do the same in a shell script, you set the action to the null string: trap "" 1 2 3 15 # ignore some interrupts Finally, you can call some user-defined signal handler which can do pretty much anything you want. In a shell script, the same is true. (For the remainder of my message, I'll be talking about ksh88e, which is what I use. The principles are generally true with earlier versions of ksh or with the Bourne shell.) I have used traps quite a bit and had occasion to explore their behavior rather thoroughly. First of all, the book states that, if several events ("interrupts") occur at about the same time, they are handled in the following order: DEBUG ERR all true interrupts (in numerical order) EXIT The EXIT trap is called whenever you 'exit' explicitly or the script finishes executing in some fashion. Note that the shell also provides the -e flag which is similar to, but separate from, the ERR trap. This flag takes precedence over the real interrupts and causes an exit to occur, which will trigger any EXIT trap. By the same token, DEBUG is similar to, but different from, the -x flag. With these ideas in mind, it is possible to do many interesting things. One other point about traps and true interrupts (e.g., SIGINT): two or more in a row can cause the trap to be started multiple times (depending on how close together the interrupts are and how long it takes to execute the trap action), so I think it is best to reset the trap first thing to ignore future interrupts: trap 'trap "" 1 2 3 15; rm -f $TMPFILE; exit 1' 1 2 3 15 Finally, I usually prefer to set all my traps at once (whenever the action is the same) but this can cause the EXIT trap to be called twice if a true interrupt occurs. It also would cause the script to always exit with a value of 1. To get around this, I take advantage of the fact that the trap action is expanded at execution time, so I do something like this (note: you must use single quotes (or something equivalent) to protect against the expansion of $RET at the time the trap is set): RET=1 trap 'trap "" 1 2 3 15; rm -f $TMPFILE; trap 0; exit $RET' 0 1 2 3 15 # the script does its thing and at the end or before an explicit call to # exit, I put: RET=0 So, what happens is that the call to 'rm -f $TMPFILE' is made just once, regardless of whether the script terminates normally or not. Also, the script exits with a value indicative of what caused it to terminate. I've noted one funny thing that I think is a bug (inherited from the Bourne shell?): If SIGINT is sent with the traps as noted above, then $? is set to 129 rather than 1 (or even 130). The ksh book states $? is the value of the last command executed and that it is 128 plus the signal number when an interrupt terminated the command. In this case though, the last command executed by the script is 'exit $RET', so I think the value of $? should be 1. If the script terminates due to some other signal (e.g., SIGHUP) the value of $? is indeed 1. Hope this helps... L. Mark Larsen lml@atlas.att.com
peter@ficc.ferranti.com (Peter da Silva) (04/03/91)
In article <c8C901q64a9q00@amdahl.uts.amdahl.com> krs@amdahl.uts.amdahl.com (Kris Stephens [Hail Eris!]) writes: > trap 'echo "signalled"' 0 > trap 'echo "signalled"; exit' 1 2 3 14 15 No, you should do: trap 'echo "signalled"; exit' 0 trap exit 1 2 3 14 15 Because (at least on some versions of the shell) the exit in the trap N triggers the trap 0, and you will get two "signalled" messages. -- Peter da Silva. `-_-' peter@ferranti.com +1 713 274 5180. 'U` "Have you hugged your wolf today?" Ewige Blumenkraft.