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

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.

Related

Uniquely identify a unix process

I'm currently writing a bash script to kill a process and then start it again.
I'm using
ps -ef | grep Cp1252
to return the list of processes based on the file encoding.
Finding the process based on file encoding is not ideal, as other processes may also have this string.
I need to uniquely identify two processes, but they have quite generic process names:
/user/jdk/jdk1.6.0_43/bin/java
My question is, is there any way to add a flag or a unique identifier to a process?
Or indeed, is there any other way I can solve this issue?
Thanks,
Dearg
UPDATE
I found a solution to my problem, I found that I can use the PPID to uniquely identify each process. The command name of the process associated with the PPID is distinctive enough so that I can tell what is a normal Java process, and what it is that I want to restart.
Thanks for all your help anyway, it certainly helped me to narrow down the alternatives! :-)
You could write a helper script to start the process and record the pid in a file. Just make sure to delete the file when the process stops (which could be done by the wrapper again).
something like
#!/bin/bash
PIDFILE=/path/to/pid-file
COMMAND=YOUR_PROGRAMM_HERE
# optionally check if pid-file exists
if [ -e ${PIDFILE} ]; then
echo "${PIDFILE} already exists, assuming ${COMMAND} already running"
exit 1;
fi
${COMMAND} &
WAITPID="$!"
echo ${WAITPID} > "${PIDFILE}"
# cleanup on signal
trap "kill ${WAITPID}; rm ${PIDFILE}; exit" SIGINT SIGTERM SIGHUP
# optionally wait for the program to be done
wait ${WAITPID}
rm "${PIDFILE}"
so to restart your process, just read the pid from /path/to/pid-file and send the appropriate signal.
If you can modify the source code of the processes you run, I recommend adding an option to record the pid from within the process itself.

PID of the process that created the file

Can I get the pid of touch when it's creating a file? I've tried touch ID$! & but it doesn't display the pid correctly. It takes the command before touch. Any advices?
I suppose you could write a small C or Perl program that calls fork() and then uses one of the exec*() functions to invoke touch from the child process. The parent process would receive the child's PID as the result of the fork call.
You say in a comment that you want to insert the PID into the name of the file. I can't think of a way to invoke touch with its own PID as part of its comand-line argument; you won't know the PID soon enough to do that. I suppose you could rename the file after touching it.
But the PID of the touch process isn't particularly meaningful. The process will have terminated before you can make any use of it.
If you just want a (more or less) unique number as part of the file name, I can't think of any good reason that it has to be the PID of the touch process. You could just do something like:
NEW_PID=$(sh -c 'echo $$')
touch foo-$NEW_PID.txt
which gives you the PID of a short-lived shell process.
Note that PIDs are not unique; since there are only finitely many possible PIDs, they're re-used after a while. (I've been able to force a PID to be reused in less than a minute by forking multiple processes very quickly.)
This is touch rewritten in perl with the pid of the creating process as part of the filename
perl -e 'open(F,">".$$."myfile")||die $!'
If you really need that pid, it's a multi-step process:
f=$(mktemp)
touch $f &
wait $!
mv $f ./ID$!

Find a process ID by name

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

how to controller (start/kill) a background process (server app) in ruby

i'm trying to set up a server for integration tests (specs actually) via ruby and can't figure out how to control the process.
so, what i'm trying to do is:
run a rake task for my gem that executes the integration specs
the task needs to first start a server (i use webrick) and then run the specs
after executing the specs it should kill the webrick so i'm not left with some unused background process
webrick is not a requirement, but it's included in the ruby standard library so being able to use it would be great.
hope anyone is able to help!
ps. i'm running on linux, so having this work for windows is not my main priority (right now).
The standard way is to use the system functions fork (to duplicate the current process), exec (to replace the current process by an executable file), and kill (to send a signal to a process to terminate it).
For example :
pid = fork do
# this code is run in the child process
# you can do anything here, like changing current directory or reopening STDOUT
exec "/path/to/executable"
end
# this code is run in the parent process
# do your stuffs
# kill it (other signals than TERM may be used, depending on the program you want
# to kill. The signal KILL will always work but the process won't be allowed
# to cleanup anything)
Process.kill "TERM", pid
# you have to wait for its termination, otherwise it will become a zombie process
# (or you can use Process.detach)
Process.wait pid
This should work on any Unix like system. Windows creates process in a different way.
I just had to do something similar and this is what I came up with. #Michael Witrant's answer got me started, but I changed some things like using Process.spawn instead of fork (newer and better).
# start spawns a process and returns the pid of the process
def start(exe)
puts "Starting #{exe}"
pid = spawn(exe)
# need to detach to avoid daemon processes: http://www.ruby-doc.org/core-2.1.3/Process.html#method-c-detach
Process.detach(pid)
return pid
end
# This will kill off all the programs we started
def killall(pids)
pids.each do |pid|
puts "Killing #{pid}"
# kill it (other signals than TERM may be used, depending on the program you want
# to kill. The signal KILL will always work but the process won't be allowed
# to cleanup anything)
begin
Process.kill "TERM", pid
# you have to wait for its termination, otherwise it will become a zombie process
# (or you can use Process.detach)
Process.wait pid
rescue => ex
puts "ERROR: Couldn't kill #{pid}. #{ex.class}=#{ex.message}"
end
end
end
# Now we can start processes and keep the pids for killing them later
pids = []
pids << start('./someprogram')
# Do whatever you want here, run your tests, etc.
# When you're done, be sure to kill of the processes you spawned
killall(pids)
That's about all she wrote, give it a try and let me know how it works.
I have tried fork, but it has kind of problems when ActiveRecord is involved in both the processes. I would suggest Spawn plugin (http://github.com/tra/spawn). It does fork only but takes care of ActiveRecord.

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