How to query for Ruby scripts currently running on Unix? - ruby

I have a few Ruby scripts: a.rb, b.rb and c.rb. These scripts are called from corresponding wrapper shell scripts: a.sh, b.sh and c.sh.
All these scripts are in a distributed environment:
`a.sh` and `a.rb` are on serverA
`b.sh` and `b.rb` are on serverB
`c.sh` and `c.rb` are on serverC
I need to write a script call.rb and its wrapper call.sh script, which should check for all the scripts currently running on the distributed environment.
I have the logic which will determine the different hosts that I have and how to communicate to these different hosts.
When any Ruby script is running, the command:
ps aux
shows:
ruby a.rb
I have no ideas on how to query for different scripts currently running. One thing to note is that there might be other Ruby scripts running in the system too, but I need to check only for a.rb, b.rb, or c.rb.

If you're doing a heartbeat check, or setting up a keep-alive check, why not have the files save their PID to a file at their startup, and then delete it when they quit?
The building blocks are:
$$ is the current process ID for a running script.
Ruby will run a block named BEGIN {} at start-up, before variables are defined. You can use that to create a PID file. Typically we use something like "#{ File.basename($0) }.pid" to create the filename.
Ruby will run a block named END {} at shut-down, as a last task. You can use that to remove the PID file.
Put the PID files in a well-known place. Where that is is left as an exercise for you to figure out for your OS.
Have your watchdog scan those, grab the PIDs, scan the process list for the PID IDs, possibly correlating them to the name of the pid file.
You can figure out more icing to put on your cake.

You can simply execute commands via SSH like this:
ssh user#host "ps -ef | grep '(ruby|[^.]+\.rb)'"
Grepping the output of ps for the script names would also work:
ps -ef | grep '(a.rb|b.rb|c.rb)'
Edit: If you don't want grep itself to show up in the process list, filter it like this:
ps -ef | grep '(a.rb|b.rb|c.rb)' | grep -v grep

If you want to solve this in Ruby, you could use a process monitoring tool like God. Monit, Bluepill or Eye

Related

Fetching the right PID from Process.spawn

I am creating a CLI application using ruby. This app receives a path to an executable, runs it, fetches the PID and collects stack trace samples every N milliseconds in order to profile the executable.
I use Process.spawn like this:
pid = Process.spwan(ENV, executable)
The problem with pid is that it's not the executable's, but it is the PID of sh -c <EXECUTABLE>.
In order to fetch the right PID I use pidof after Process.spawn like this:
target_pid = `pidof -s #{executable}`
and then I use target_pid for profiling.
Is there a cleaner way to get target_pid using Ruby?
If you don't need the shell then use either of these two forms of calling:
pid = Process.spwan(ENV, executable, '--arg1')
and if you have no arguments then you would need to use this format instead:
pid = Process.spwan(ENV, [executable, 'name of executable'])
If you need the shell then you need to modify your executable variable to do something along these lines
cmd & echo "pid=$!"; fg
which means run your command in the background, obtain the pid of it which you can somehow communicate to your ruby process, then put that process in the foreground again.

BASH commands: pkill/pgrep

I'm struggling with understanding the difference between using pgrep, as opposed to using ps | grep.
Apart from the fact that pgrep will only list the PID, what is the difference?
When I run an instance of kwrite in the background of my terminal, as well as opening one up using the GUI, why is the output given by ps | grep kwrite only one PID, when two instances of kwrite are running?
On a slightly different note, why would using pkill to kill a crashed instance of kwrite not be a good way of killing a process? The only explanation that I could come up with, is that it would kill all processes with the string "kwrite" in them, and that may not be only the instance of kwrite I wanted to kill.
Thank you for your help.
ps | grep will fork 2 processes, pgrep only one.
ps | grep whatever may also list grep whatever depending when ps exits, pgrep whatever will not.
ps will need additonal command-line switches to show up both kwrite processes. (see: man ps and try ps -ef next time)
By default, ps selects all processes with the same effective user ID (euid=EUID) as the current user and associated with the same terminal as the invoker.
Try running a handfull kwrite instances, preferably with important and unsaved data to find out, why killing the crashed one using pkill might not be the most clever idea.

Kill a child process that has detached from the shell

I want to control many different Sinatra apps from a central (Sinatra) app.
The problem I have is no matter which way I exec/spawn/fork the call to start it, I cannot get the pid of the Sinatra server so that I can kill (:int) it?
This is due to my shell exec string, which contains a few other commands first, so I get the pid of the first.
My command string is like
command = source ~/.profile; rbenv #{ver}; some_env=1234 ruby app.rb
So I get the pid of the sh process of the sourcing command.
The question is, how can I get the pid of the ruby command launched above?
I am currently using spawn, but have tried most others as well, but I don't think that is the problem!?
pid = Process.spawn(command)
pid # => 1234
The ruby app itself starts
$ ps aux
1234 sh -c . ~/.profile; shell_script
4567 shell_script
I want to know 4567!?
There's no easy way of getting your '4567', but you should be able to make your process have the same pid as Process.spawn returns.
Try ending your command with an exec rather than a straight call to ruby, i.e.:
source ~/.profile; rbenv #{ver}; export some_env=1234; exec ruby app.rb
you can check whether the process "shell_script" is a child of "sh -c . ~/.profile; shell_script".you can check this through "ps -axgf" command.
if it is a parent then u can use the group id of pid 1234 (get it form the output of ps -axgf) to kill the child with pid 4567 using this command .
kill -9 -1234(assumming 1234 is the group id)

How do I write a bash script to restart a service if it dies?

I have a program that runs as a daemon, using the C command fork(). It creates a new instance that runs in the background. The main instance exists after that.
What would be the best option to check if the service is running? I'm considering:
Create a file with the process id of the program and check if it's running with a script.
Use ps | grep to find the program in the running proccess list.
Thanks.
I think it will be better to manage your process with supervisord, or other process control system.
Create a cron job that runs every few minutes (or whatever you're comfortable with) and does something like this:
/path/to/is_script_stopped.sh && /path/to/script.sh
Write is_script_stopped.sh using any of the methods that you suggest. If your script is stopped cron will evaluate your script, if not, it won't.
To the question, you gave in the headline:
This simple endless loop will restart yourProgram as soon as it fails:
#!/bin/bash
for ((;;))
do
yourProgram
done
If your program depends on a resource, which might fail, it would be wise to insert a short pause, to avoid, that it will catch all system resources when failing million times per second:
#!/bin/bash
for ((;;))
do
yourProgram
sleep 1
done
To the question from the body of your post:
What would be the best option to check if the service is running?
If your ps has a -C option (like the Linux ps) you would prefer that over a ps ax | grep combination.
ps -C yourProgram

How can I find out what a command is executing in Terminal on MacOs

After I run a shell script (which call a bunch a other scripts depend on conditions. which is too complicated to understand), I can execute a command 'gdbclient' at my MacOS terminal.
But when I do 'which gdbclient' and 'alias gdbclient', it shows nothing.
Is there anyway for me to find out what 'gdbclient' is actually doing?
You can open up another terminal window and type: ps
That will list all the running processes.
If your script is running as a different user than the current one, you can use ps -ef to list all running processes.
If you know the PID of the process that ran your script, you can find all child processes via parent PID using ps -f | grep [pid]
You can use the Activity Monitor to check things out pretty thoroughly. To get the right privileges to see everything going on you can do:
sudo open /Applications/Utilities/Activity\ Monitor.app/
Dtrace can give you some helpful information: dtrace
to find process 'gdbclient':
ps aux | grep gdbclient
That wont tell you what it's "doing" but that it's running

Resources