Find a process ID by name - ruby

How can I find a pid by name or full command line in Ruby, without calling an external executable?
I am sending SIGUSR2 to a process whose command line contained ruby job.rb. I would like to do the following without the call to pgrep:
uid = Process.uid
pid = `pgrep -f "ruby job.rb" -u #{uid}`.split("\n").first.to_i
Process.kill "USR2", pid

How to do this depends on your operating system. Assuming Linux, you can manually crawl the /proc filesystem and look for the right command line. However, this is the same thing that pgrep is doing, and will actually make the program less portable.
Something like this might work.
def get_pid(cmd)
Dir['/proc/[0-9]*/cmdline'].each do|p|
if File.read(p) == cmd
Process.kill( "USR2", p.split('/')[1] )
end
end
end
Just be careful poking around in /proc.

A quick google search came up with sys_proctable, which should let you do this in a portable way.
Disclaimer: I don't use Ruby, can't confirm if this works.

Debian based systems find pid with pidof command.
Some kill proccess function with ruby:
def killPid(cmd)
pid=exec("pidof #{cmd}")
Process.kill "USR2", pid
end

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.

Terminal - Close all terminal windows/processes

I have a couple cli-based scripts that run for some time.
I'd like another script to 'restart' those other scripts.
I've checked SO for answers, but the scenarios were not applicable enough to mine, as I'm trying to end Terminal processes using Terminal.
Process:
2 cli-based scripts are running (node, python, etc).
3rd script is run and decides whether or not to restart the other 2.
This can't quit Terminal, but has to end current processes.
3rd script then runs an executable that restarts everything.
Currently none of the terminal windows are named, and from reading the other posts, I can see that it may be helpful to do so.
I can mostly set this up, I just could not find a command that would end all other terminal processes and close them.
There are a couple of ways to do this. Most common is having a pidfile.
This file contains the process ID (pid) of the job you want to kill
later on. A simple way to create the pidfile is:
$ node server &
$ echo $! > /tmp/node.pidfile
$! contains the pid of the process that was most recently backgrounded.
Then later on, you kill it like so:
$ kill `cat /tmp/node.pidfile`
You would do similar for the python script.
The other less robust way is to do a killall for each process and assume you are not running similar node or python jobs.
Refer to
What is a .pid file and what does it contain? if you're not familiar with this.
The question headline is quite general, so is my reply
killall bash
or generically
killall processName
eg. killall chrome

Check if process is running (using process name)

Is there anyway in Go to check if a proces is running by searching by process name? I see ways to do it with PID, however I don't have the PID to search by. Thanks.
http://www.faqs.org/faqs/unix-faq/faq/part3/section-10.html,
Find PID of a Process by Name without Using popen() or system()
No direct way available. You can use os/exec with pidof or pgrep to do this. Or read into procfs.

How do I kill a process whose PID is in a PID file?

I have a variable pidfile, that stores the PID of a process.
How can I kill the pid in pidfile programmatically using Ruby, assuming I just know the filename, and not the actual PID in it.
Process.kill(15, File.read('pidfile').to_i)
or even
Process.kill 15, File.read('pidfile').to_i
Now, you could also do something like:
system "kill `cat pidfile`" # or `kill \`cat pidfile\``
However, that approach has more overhead, is vulnerable to code injection exploits, is less portable, and is generally just more of a shell script wrapped in Ruby as opposed to actual Ruby code.

ruby list child pids

How can I get pids of all child processes which were started from ruby script?
You can get the current process with:
Process.pid
see http://whynotwiki.com/Ruby_/_Process_management for further details.
Then you could use operating specific commands to get the child pids. On unix based systems this would be something along the lines of
# Creating 3 child processes.
IO.popen('uname')
IO.popen('uname')
IO.popen('uname')
# Grabbing the pid.
pid = Process.pid
# Get the child pids.
pipe = IO.popen("ps -ef | grep #{pid}")
child_pids = pipe.readlines.map do |line|
parts = line.lstrip.split(/\s+/)
parts[1] if parts[2] == pid.to_s and parts[1] != pipe.pid.to_s
end.compact
# Show the child processes.
puts child_pids
Tested on osx+ubuntu.
I admit that this probably doesn't work on all unix systems as I believe the output of ps -ef varies slightly on different unix flavors.
Process.fork responds with the PID of the child spawned. Just keep track of them in an array as you spawn children. See http://ruby-doc.org/core/classes/Process.html#M003148.
Can be also done using sys-proctable gem:
require 'sys/proctable'
Sys::ProcTable.ps.select{ |pe| pe.ppid == $$ }
This is actually quiet complicated and is platform specific. You actually cannot find all sub-processes if they deliberately try to hide.
If you want to just kill spawned processes there are many options. For a test framework I chose two:
1. spawn processes with pgid => true
2. insert variable MY_CUSTOM_COOKIE=asjdkahf, then find procs with that cookie in environment and kill it.
FYI using ps to find out process hierarchy is very unreliable. If one process in the chain exits, then its sub-processes get a parent pid of 1 (on linux at least). So it's not worth implementing.

Resources