Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game. |
Notices |
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
|
|
06-21-2009, 09:54 PM
|
#1
|
LQ Guru
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594
|
bash `kill`: process 'B' silently dies; but process 'A' = `kill` spews back debris!
Yesss....
I'm dealing with a couple weird little ' bash-isms' here this evening.
Here's the situation (the first one anyway):
Process 'A' is a forked off TAIL command, simply following a logfile and dumping the tailed output to another file.
When I fork it from the bash script, I grap the PID from '$!' and save it to a pidfile.
Process 'B' is a forked off function in this bash script, which again, after forking it I grab the PID and save it to a pidfile; like so (very simplified):
Code:
#!/bin/bash
silly_function_name () {
sleep 10000
blah blah
}
case $1 in
start)
tail -f /some/log > some/file &
echo $! > pidfile_A
silly_function_name &
echo $! > pidfile_B
;;
stop)
kill `cat pidfile_A`
kill `cat pidfile_B`
;;
esac;
exit 0
OK, so I run the script, which has a START and STOP argument I can send to it, like so:
sh# ./script start
..so far so good.
sh# ./script stop
..now, the crap: function fork dies silently with no feedback from `kill`; but killing the TAIL command fork returns the likes of:
Code:
[1] 35242 Terminated tail -f /some/file >some/other/file
to the console. I don't want that.
Now, I should mention that this effect does NOT happen if I start a tail fork from the command-line, and then kill it with `kill 1234` ; it dies silently with no feedback. But when I run the script, voila! ugly feedback from kill, but ONLY from killing the tail command, not from killing the function that was forked.
Also, I've tried directing STDERR and STDOUT to /dev/null or to a file, and I've tried trapping the feedback in a $variable, and I've tried piping it into other stuff, but nothing supresses the 'Terminated' message.
Anyone have any insight?
Heres situation 2:
Assuming the same script as above; the function in the script contains a 'sleep' command. When I start the script, and the function forks, I can look at `ps ax` and I can see the function's process itself, and I can also see that a sleep thread has been created by it. That's all fine and dandy, however when I stop the script, or kill the function with `kill 1234` the sleep thread remains in the ps list. It isn't zombified, it's 'sleeping'.
Why is it still there??
Since it was within the function, I like to think that killing the function itself, would terminate the sleep thread as well.
Why not??
Sasha
Last edited by GrapefruiTgirl; 06-22-2009 at 07:48 PM.
Reason: changed function name for clarity
|
|
|
06-22-2009, 08:22 AM
|
#2
|
LQ Guru
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594
Original Poster
|
I have come up with a solution, or a work-around, for situation one.
by changing the `kill` statement to:
Code:
pid=`cat $pidfile`
kill $pid > /dev/null 2>&1 &
wait
the 'Terminated..' line is eliminated. Not sure if I need to background the kill statement (but in the real-life context in which it's being used, it works); the main issue was *probably/possibly* that I was doing the shell redirection improperly.
Situation TWO from my first post still astounds and amazes and I haven't figured out why the `sleep` thread doesn't terminate when its parent process dies.
Sasha
|
|
|
06-22-2009, 03:48 PM
|
#3
|
Senior Member
Registered: Mar 2004
Location: england
Distribution: Mint, Armbian, NetBSD, Puppy, Raspbian
Posts: 3,515
|
plus, function is a keyword.
Code:
Functions are declared using this syntax:
[ function ] name () compound-command [ redirections ]
|
|
|
06-22-2009, 07:50 PM
|
#4
|
LQ Guru
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594
Original Poster
|
Thanks for the heads-up re: 'function'
Quote:
Originally Posted by bigearsbilly
plus, function is a keyword.
Code:
Functions are declared using this syntax:
[ function ] name () compound-command [ redirections ]
|
Thanks Billy, I hadn't even thought of that.
In the real-world program I am working on, the function is not actually named 'function' -- that was a poor choice of function names in my example, and I have corrected it.
So, the sleep thread problem still exists as it did.
Sasha
|
|
|
06-22-2009, 09:15 PM
|
#5
|
Member
Registered: Feb 2006
Distribution: Debian Sid
Posts: 792
|
I piddled (no pun intended) with this a little today and my sid system doesn't issue the warning when I run the stop option. I understand that your script is more complex than the description that you gave but it seems odd that Slackware and Debian would behave differently. Maybe it's a bash shell option like "notify" that is set differently. Dunno.
Here's the code that I ran (pretty much exactly like your example):
Code:
!/bin/bash
bar () { sleep 300; }
case $1 in
start)
tail -f /var/log/syslog > tail_output &
echo $! > pidfile_A
bar &
echo $! > pidfile_B
;;
stop)
kill `cat pidfile_A`
kill `cat pidfile_B`
;;
esac;
exit 0
Code:
./foo.sh start
ps -aux
user 10151 0.0 0.1 3100 552 pts/1 S 20:44 0:00 tail -f /var/log/syslog
user 10152 0.0 0.1 4864 960 pts/1 S 20:44 0:00 /bin/bash
user 10153 0.0 0.0 3076 504 pts/1 S 20:44 0:00 sleep 300
Code:
cat pidf*
10151
10152
Code:
./foo.sh stop
ps -aux
user 10089 0.0 0.4 4864 2072 pts/1 Rs 20:41 0:00 /bin/bash
user 10153 0.0 0.0 3076 508 pts/1 S 20:56 0:00 sleep 300
As I said, if stop is run there is no output. It kills two processes and leaves the sleep process running. My guess is that it has to spawn a shell in order to put the function in the background and that is what is captured with "$!". I don't think a normal function call is a process.
Really no solution offered above but I thought that I would share my experiences with you.
Finally to the point of my post: I did find some interesting discussion about killing parent and child processes right here on LQ (where else?) but I haven't tried any of the suggestions: link link
|
|
|
06-22-2009, 09:29 PM
|
#6
|
LQ Guru
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594
Original Poster
|
@ norobro,
Thanks for taking the time to do some experimenting on the subject. It is most interesting: as we see, the same thing happens on your system regarding the sleep command/thread.. It stays alive until it times out. Weird. I could kill it, but sheesh, it's looking like I'm creating quite a pile of pidfiles to deal with, for one rather small script
As you speculated, possibly different versions of BASH are in play, or different BASH configurations on different systems. FWIW my current BASH is version 3.1.17(2), not the one that came with my Slack OS.
The outputs from the script when I stop/kill it are not really detrimental or serious, but I am super-detail-oriented, perhaps too much so sometimes (obsessive with detail ? ?) heh heh. Maybe I'm too picky; but something I find annoying is when a script has executed completely and returns the prompt to the user, then suddenly some more output spews forth from the remaining backgrounded process. I don't like it.
Well, it has been a long and tiresome day for me; I will have to look at those two threads you linked to above, but it will be tomorrow. I'm about thru for today.
Thanks again for the input and testing!
Sasha
|
|
|
06-23-2009, 05:08 AM
|
#7
|
Senior Member
Registered: Mar 2004
Location: england
Distribution: Mint, Armbian, NetBSD, Puppy, Raspbian
Posts: 3,515
|
well, on the command line
bash and ksh
both produce terminated whether backgrounded as
a function or as a straight command.
I tried the script (apart from changing it to #!/bin/bash
and /var/log/messages -- I get no terminated messages.
when you call a function it spawns a new shell this is the number
returned in $!. sleep also spawns a new process. so you are killing the
shell not the sleep.
an interactive shell passes signals on to it's children, this would imply that a non-interactive
shell does not. I would assume a function to be a non interactive shell.
even though, if you do a sleep & and exit the shell it still doesn't die (the sleep)
the plit thockens
|
|
|
06-23-2009, 09:26 AM
|
#8
|
Member
Registered: Feb 2006
Distribution: Debian Sid
Posts: 792
|
Quote:
Originally Posted by bigearsbilly
I tried the script (apart from changing it to #!/bin/bash
|
This typo is a pretty easily caught. Think I should edit my post?
Quote:
Originally Posted by bigearsbilly
well, on the command line
bash and ksh
both produce terminated whether backgrounded as
a function or as a straight command.
|
Looking back, I misread or misunderstood GrapefruiTgirl's op. I thought that she was getting the terminated message from her script.
If you don't background the function and instead "bg" the sleep, GrapefruiTgirl's script works like a charm. So it seems that in order to "bg" something that doesn't normally require a separate process, bash has to spawn a shell. Thus creating the issue of being able to kill the parent process and all child processes.
|
|
|
06-23-2009, 09:39 AM
|
#9
|
LQ Guru
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594
Original Poster
|
..something so simple.. er... not!
Quote:
Originally Posted by bigearsbilly
well, on the command line
bash and ksh
both produce terminated whether backgrounded as
a function or as a straight command.
|
.. and it's HARD to shut up the ' Terminated' message.. /dev/null doesn't seem to absorb it.
Quote:
I tried the script (apart from changing it to #!/bin/bash
and /var/log/messages -- I get no terminated messages.
|
I get the impression you are subtly telling me something in the above, re: changing the shell statement to #!/bin/bash .. so?
Quote:
when you call a function it spawns a new shell this is the number
returned in $!. sleep also spawns a new process. so you are killing the
shell not the sleep.
|
Right.
Quote:
an interactive shell passes signals on to it's children; this [what we're learning here] would imply that a non-interactive
shell does not. I would assume a function to be a non interactive shell.
|
Sounds good to me, and seems correct.
Quote:
even though, if you do a sleep & and exit the shell it still doesn't die (the sleep)
|
Correct, the sleep does not die. It sleeps until it awakes, at which point it vaporizes. That's exactly what's pesky about this sleep thing.
Here's some console output to ponder (just executed in the console-- no deliberately spawned shells or scripts, and ignore the orange for a moment.). It's early here for me, so I'm not fully 'online' yet. :
Code:
sh-3.1# sleep 1000 &
[1] 23664
sh-3.1# kill 23664
sh-3.1#
[1]+ Terminated sleep 1000
sh-3.1# sleep 1000 &
[1] 23704
sh-3.1# kill 23704 > /dev/null 2>&1
sh-3.1#
[1]+ Terminated sleep 1000
sh-3.1# sleep 1000 &
[1] 23891
sh-3.1# kill 23891 > /dev/null 2>&1 &
[2] 23940
[1]- Terminated sleep 1000
[2]+ Done kill 23891 >/dev/null 2>&1
sh-3.1# sleep 1000 &
[1] 23971
sh-3.1# kill 23971 & > /dev/null 2>&1
[2] 24033
[1]- Terminated sleep 1000
[2]+ Done kill 23971
sh-3.1#
Notes/observations:
1) The line I bolded does not appear until I hit another keystroke (like pres RETURN at the prompt).
2) The 'Terminated' report is returned no matter what I do to try to hide it.
3) If I do the above examples from within a SCRIPT, the 'Terminated' report can be hidden, BUT:
3a) doing that like:
Code:
kill `cat $pidfile`
or
kill `cat $pidfile` &
wait
both spew back the Terminated line every time.. However, here's some in-script examples for comparison:
Code:
in-script examples 1 (returns 'Terminated' line no matter where/how I redirect output)
kill `cat $pidfile` > /dev/null 2>&1
kill `cat $pidfile` > /dev/null 2>&1 &
in-script example 2 (same result)
var=`cat $pidfile`
kill $var > /dev/null 2>&1
in-script example 3 (same result)
var=`cat $pidfile`
kill $var > /dev/null 2>&1 &
in-script example 4 (same result)
var=`cat $pidfile`
kill $var > /dev/null 2>&1 &
in-script example 5 (THIS HIDES the 'Terminated' line,
BUT ONLY if the wait command is after it, presumably
because the 'Terminated' message is delivered to the imaginary console
created by forking the KILL command, and the WAIT command
keeps output confined to that imaginary console, returning only
AFTER the 'Terminated' message has been displayed in that imaginary console;
This is the same as the orange example earlier.)
var=`cat $pidfile`
kill $var > /dev/null 2>&1 &
wait
In my real-life script, here's what it looks like (and it works great, despite being round-a-bout IMO).
note that elsewhere in the script, some_function () was forked, and $! was saved as $function_pid
Code:
sleep_pid=`ps ax | grep $(pgrep -P $function_pid) | gawk '{/^.[:digit:]+[ ]$/;print $1}'`
kill $function_pid > /dev/null 2>&1 &
wait;
kill $sleep_pid > /dev/null 2>&1 &
wait;
it works perfect.
I dunno if me or anyone can make much sense out of this post as a whole; as I said, it's early; I'm still on the first coffee.
Sasha
PS - I don't know how/why this thread is in the 'NON *NIX' programming forum.. Seems *NIXy enough to me..
|
|
|
06-23-2009, 09:42 AM
|
#10
|
LQ Guru
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594
Original Poster
|
Oh -- and @ norobro,
Those links you gave at the bottom of youe earlier post DID lead me to the working solution I have now in my actual real script. Some of the examples did NOT work for me as they did for the user(s) in those posts, but I managed to adjust what I read there and get a working result.
Link #2 was the more helpful to me. Thank you again.
Sasha
|
|
|
All times are GMT -5. The time now is 10:06 PM.
|
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
|
Latest Threads
LQ News
|
|