I am trying to setup Kibana with Supervisord using Bundler. Installing the Kibana dependencies with Bundler was no problems at all. I tried running bundle exec ruby kibana.rb and it worked. I also tried killing it with Ctrl-C while watching the processes that spawn in htop, and it worked.
However, when killing bundler using supervisord (or signals like SIGINT or SIGTERM for that matter) the two children spawned by it survives. So, if restarting the kibana job in supervisord, the restart will fail as the ports the restarted job will try to allocate are already in use.
From what I can find, bundler exec shouldn't fork and from what I can tell, it doesn't. It just doesn't behave as I expect when it gets signals.
What can I do? Switching from bundler could be a solution, but it is not desirable.
I solved it. I wrote the little run_kibana bash helper below (found at another Stack Overflow thread):
function kill_kibana() {
echo "Trapped termination of Kibana subprocessess"
pkill -TERM -P $1
}
bundle exec ruby kibana.rb &
pid=$!
trap "kill_kibana $pid" SIGINT SIGTERM SIGKILL SIGQUIT
wait $pid
And it works like a charm. Might be reasonable to extend it to send the actual signal that was trapped in the kill_kibana() function.
Related
I'm sure this is really simple, but it's biting me in the face anyway, and I'm a little frustrated and stumped.
So, I have a script which I've managed to boil down to:
#!/bin/sh
sleep 50 | echo
If I run that at the command line, and hit Ctrl-C it stops, like I would expect.
If I send it sigint, using kill, it does nothing.
I thought that was strange, since I thought those should have been the same.
Then, if I send it sigterm, then it also dies, but if I look in ps, the sleep is still running.
What am I missing, here?
This is obviously not the real script, which runs python, and it's more of a problem when it keeps running after start-stop-daemon tries to kill the daemon.
Help me people. I'm dumb.
The reason this happens is that the Ctrl-C is delivered to the sleep process, whereas the sigint you are sending is delivered only to the script itself. See Child process receives parent's SIGINT for details on this.
You can verify this yourself by using strace -p when hitting ctrl-c or sending sigint; strace will tell you what signals are delivered.
EDIT: I don't think you are dumb. Processes and how they work are seemingly simple, but the details are often complicated, and even experts get confused by this sort of thing.
I did the same thing I written script named as test.sh with below containt.
#!/bin/sh
sleep 50 | echo
After executing , I did Ctrl-C -> its working fine means closing it.
Again executed and in another terminal i checked the PID by ps -ef|grep test.sh after finding the pid , i did kill <pid> and it killed the process , to verify again i executed ps -ef|grep test.sh and didnt get any pid.
I have a long-running command (sidekiq, if you must know) that depends on another long-running processes (redis-server, as you may have guessed from the previous parenthetical).
I'd like to write a Bash (well, okay, Zsh actually) alias to start redis-server in the background, then run sidekiq and, when I use ctrl-C to interrupt sidekiq, to kill the background Redis job. If it's relevant, I'm on a Mac and only need to support OS X.
So what I'm looking for is something like:
redis-server & ; sidekiq ; kill $!
Unfortunately, my interrupt of the sidekiq command also prevents the kill from occurring. Is there any way to do this?
Bonus points if this can be a one-liner alias and not a function. Double bonus points if I don't have to write to any files in advance (like turning on the daemonize flag in /usr/local/etc/redis.conf).
Maybe this:
#!/bin/zsh
redis-server &
redispid=$!
trap 'kill $redispid' INT
sidekiq
/bin/sh -version
GNU sh, version 1.14.7(1)
exitfn () {
# Resore signal handling for SIGINT
echo "exiting with trap" >> /tmp/logfile
rm -f /var/run/lockfile.pid # Growl at user,
exit # then exit script.
}
trap 'exitfn; exit' SIGINT SIGQUIT SIGTERM SIGKILL SIGHUP
The above is my function in shell script.
I want to call it in some special conditions...like
when:
"kill -9" fires on pid of this script
"ctrl + z" press while it is running on -x mode
server reboots while script is executing ..
In short, with any kind of interrupt in script, should do some action
eg. rm -f /var/run/lockfile.pid
but my above function is not working properly; it works only for terminal close or "ctrl + c"
Kindly don't suggest to upgrade "bash / sh" version.
SIGKILL cannot be trapped by the trap command, or by any process. It is a guarenteed kill signal, that by it's definition cannot be trapped. Thus upgrading you sh/bash will not work anyway.
You can't trap kill -9 that's the whole point of it, to destroy processes violently that don't respond to other signals (there's a workaround for this, see below).
The server reboot should first deliver a signal to your script which should be caught with what you have.
As to the CTRL-Z, that also gives you a signal, SIGSTOP from memory, so you may want to add that. Though that wouldn't normally be a reason to shut down your process since it may be then put into the background and restarted (with bg).
As to what do do for those situations where your process dies without a catchable signal (like the -9 case), the program should check for that on startup.
By that, I mean lockfile.pid should store the actual PID of the process that created it (by using echo $$ >/var/run/myprog_lockfile.pid for example) and, if you try to start your program, it should check for the existence of that process.
If the process doesn't exist, or it exists but isn't the right one (based on name usually), your new process should delete the pidfile and carry on as if it was never there. If the old process both exists and is the right one, your new process should log a message and exit.
I'm using Ruby 1.9.2-p180 on Ubuntu 12.04. I don't understand why the following code doesn't work. The expected behaviour is that I should see the text: "TRAPPED" on my screen when I run the code, and the program should terminate. But the ruby program doesn't terminate when I run it and nothing is printed on the screen. What am I missing?
pid = fork do
exec "trap 'echo TRAPPED' TERM; while :; do :; done"
end
Process.kill("TERM", pid)
Process.wait(pid)
The reason why it did not work as expected was that the kill was delivered before the exec commenced. Introducing a little sleep before delivering the kill ensures that the program will behave as expected.
I want to write a shell script that spawns several long-running processes in the background, then hangs around. Upon receiving SIGTERM, I want all the subprocesses to terminate as well.
Basically, I want a "master process".
Here's what I got so far:
#!/bin/sh
sleep 600 &
PID1="$!"
sleep 600 &
PID2="$!"
# supposedly this should kill the child processes on SIGTERM.
trap "kill $PID1 $PID2" SIGTERM
wait
The above script fails with trap: 10: SIGTERM: bad trap.
Edit: I'm using Ubuntu 9.04
This works for me:
trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT
kill -- -$$ sends a SIGTERM to the whole process group, thus killing also descendants.
Specifying signal EXIT is useful when using set -e (more details here).
Joe's answer put me on the right track.
I also found out I should trap more signals to cover my bases.
Final script looks like this:
#!/bin/sh
sleep 600 &
PID1="$!"
sleep 600 &
PID2="$!"
trap "kill $PID1 $PID2" exit INT TERM
wait
I suspect your /bin/sh is not a Bash (though you tagged the question as 'Bash').
From the message I guess it's a DASH. Check its manual or just fix your shebang if you need to write Bash code.
This script looks correct and works for me as expected.
How do you send the SIGTERM signal to the "master process"?
Maybe you should execute kill -l to check which signals are supported.
As the error message suggests you send signal "10" which your system doesn't seem to recognize.
And next time you should add operating system, shell version, kernel, ... for such a question