in the first subshell I have a query on a database which is waiting on a correct response, if database is slow then
the simultaneous subshell running will have commands sleep and kill -$$ and send an email to me as an alert DB is going slowly!
Thanks. Let me know what your thoughts are.
---------- Post updated at 06:24 PM ---------- Previous update was at 06:14 PM ----------
Guys,
I will attempt your ideas today before eofday.
I however have probably not explained this properly:
I understand two subshells or 1 subshell and main command going same time.
BUT, I need to add a mail function in both.
what I am attempting is that: If the sleep 5 in subshell gets to end and the subshell its in kills -- -$$ ALL before my other main or simultaneous shell is doing some intensive/timeconsuming calculation against a SQL DATABASE -- Then Send and alert mail-s
I just need probably help getting errors directed taking everything into account in a mail command rather then how to terminate both shells.
So basically my logic is:
()
&
()
----
Shell1-
(do intensive calculations and
initialize variables for mail alert
Send mail
kill -- -$$
)
subShell2
(Sleep 5-10 depend
send mail alert if
finishes sleep saying something like (HEY WATCHOUT DATABASE SLOW, OR CRASHED!)
kill -- -$$
)
can someone elaborate how I can remove all possible errors from a mail -s function and ignore them cause in my tests yesterday I noted that thats where the hanging up is occurring, mail -s ONLY, the logic I think might be alright unless im missing something.
Again: if anyone knows how to dev/null mail properly can you add it to a simple echo blah/sleep5/sendmail/kill -- -$$ everything good while other subshell goes with (a sleep -faster time then 1st shell/ alert mail/and kill -- -$$ with other subshell
I can get one subshell to mail alerts by switching sleep times around but other wont.
Thus in the grand scheme of things,
-if my db is slow at responding -and sending an email with the variables I get from DB -and kill before other shell
-the other subshell will -sleep on side and after send mail and then kill all
Again, I'm not sure what 'kill -- -$$' is even trying to do. -- is not a valid option for kill, and killing your own shell would kill everything, leaving it not able to do anything. And -(number) would tell kill it's some strange kind of signal, not a process ID.
This is different from our suggestions how? Wait up to 5 seconds then kill, and if it had to be killed, email?
Once again, this logic doesn't make sense. & on a line by itself is meaningless, and -- why bother making a second subshell? You already have two shells, and you never background the second one anyway.
Oh, I see -- you are trying to launch two scripts simultaneously. Each will kill the other if it finishes first.
This doesn't seem a good way to solve the problem, really. That's the very definition of "race condition". Even assuming good conditions, who can say whether one will kill the other in time? Who can say whether they will die cleanly?
And there's no point! It's an over-complicated, extra-wasteful, extra-sloppy, extra-error-prone version of the exact same algorithm: "Wait up to x seconds, then kill and send email".
If you're trying to avoid some sort of problem with this convoluted method, it'd be nice to know what problem, so that we can show you how to actually avoid it.
I don't know what you're even trying to say here.
I will make my solution more complete in the hope you will actually try it:
#!/bin/bash
(
echo "Hi!"
# Using 'exec' means less mess if something goes wrong,
# since the subshell is replaced wholly by it.
exec sleep 1000
# Less stderr noise if you use 'disown'.
# If your shell doesn't have disown, it doesn't need it.
) & disown
PID="$!" # The PID of the background process
MAXTIME=5
X=0 ; while [ "$X" -lt "$MAXTIME" ]
do
let X=X+1
# If the process is done, quit immediately
ps "$PID" 2>&1 >/dev/null || exit
echo "$X seconds, $PID still exists" >&2
sleep 1
done
# The query hasn't finished in 5 seconds, so kill it.
kill "$PID" >/dev/null 2>&1 || exit
ERECIPIENT3="email.com"
# echo "Connection on status: is Down"|mail -s "Subject:" "${ERECIPIENT3}" >/dev/null 2>/dev/null
sleep 1 # Wait a second for it to die
# Kill it with a more severe signal and exit if it doesn't exist
kill -QUIT "$PID" >/dev/null 2>&1 || exit
sleep 1
# Try and kill it again with an unblockable signal, quit if it doesn't exist
kill -9 "$PID" # Last resort
exit
If 'mail' is hanging, it might be a good idea to find out why.
hey Corona, thanks for the detailed help.
So basically I am trying out your script however I have a question about $! 's- functionality.
does it pick from within the script the most recent shell script or does it grab from all running scripts.
I am wonderring cause the documentation on it is confusing me. and the way we schedule linux scripts we have many running simultaneously and any clarification you can give me on $! would help clear my worries about it. - I am still googling
but does it grab from the entire history linux processes running at the time or will it only grab from within the script.
I will post my final script later so you guys can look and see what I was trying in the first place.
and FYI- the reason I am seperating the DB-connections is that the system hangs on lets say the first variable assignment which is a query from the DB.
--Your solution seems to cover it so thanks, -will be testing it for a day or so to see it on my dev environment. -I will proably use once I understand the scope of $!
Thanks.
---------- Post updated at 10:50 AM ---------- Previous update was at 10:30 AM ----------
I understand $! grabs from inside script can someone confirm??
$! is the process ID of whatever you backgrounded (i.e, ran with &) most recently inside the current shell.
So if you did ( .... ) & you would get the process ID of the subshell.
If you did sleep 1000 & you would get the process ID of sleep without any subshell involved at all.
etc.
BASH also has another meaning for "!", which relates to the shell history -- but, like aliases, this does not happen inside a shell script, only in live interactive terminal sessions.
You might want to comment out the echo inside that loop before deploying. I'm not sure where all those debug statements will end up, if anywhere. Don't want them piling up in some neglected logfile
Will do and thanks for the heads up!
is there a any logs in specific your thinking of? i'm just curious.
what causes the pileup ? termination of the script ?
I don't know, that depends on what's running it. That's why any programs you write should make as little noise as possible unless they actually have anything important to say.
If it's run by an init script, it might end up somewhere in /var/log.
If it's run by cron, any program output from that gets automatically emailed to user@hostname via the server's own MTA... or dumped in $HOME/dead.letter if none's available. (Meaning, if it is cron-ed, it might be possible to simplify that script by letting cron do the mailing for it.)
etc.
It might go nowhere at all. It's not THAT big a deal in the end. I just don't want you to end up with a slowly growing file under /var/log which will get ignored for 10 years until the partitions full... Or a confused customer wondering why they're suddenly getting 3 emails full of nonsense a day