I would like to change the name of the ruby process that gets displayed in the linux/unix top command. I have tried the
$0='miname'
approach but it only works with the ps command and in top the process keeps getting displayed as "ruby"
I would like to change the name of the ruby process that gets displayed in the linux/unix top command. I have tried the
$0='miname'
approach but it only works with the ps command and in top the process keeps getting displayed as "ruby"
Dave Thomas had an interesting post on doing this in rails. There's nothing rails specific about the actual process name change code. He uses the $0='name'
approach. When I followed his steps the name was changed in ps
and top
.
In the post he suggests using the c
keyboard command if your version of top doesn't show the short version of the command by default.
Ruby 2.1 introduced a Process.setproctitle
method for this purpose:
Process.setproctitle("My new title")
I don't think Ruby has the facility builtin (setproctitle(3)
). You should probably try to look at ruby-ffi and create the interface to setproctitle(3)
.
EDIT: I know you have your answer but I want to show you some code to use ffi:
require "ffi"
#
module LibC
extend FFI::Library
attach_function :setproctitle, [:string, :varargs], :void
end
LibC.setproctitle("Ruby: executing %s", :string, $0)
Does not work on OS X because setproctitle(3)
does not exist, works on FreeBSD.
The $0 = 'Foo' method works -- but many versions of top will require you to toggle command-line mode on with 'c'. We this very method here with rails and CentOS. Works a treat
I had a similar problem, updated the technique from the Dave Thomas post a little by putting it in a rack middleware, rather than the before/after pattern.
# Set the process title to the URI being processed
#- useful for debugging slow requests or those that get stuck
class Rack::SetProcessTitle
def initialize(app)
@app = app
end
def call(env)
$0 = env['REQUEST_URI'][0..80]
@status, @headers, @response = @app.call(env)
$0 = env['REQUEST_URI'][0..80] + '*'
[@status, @headers, @response]
end
end
Rails.configuration.middleware.insert_after Rack::Lock, Rack::SetProcessTitle
More words in the blog post: http://blog.actbluetech.com/2011/06/set-your-process-name-in-top-and-ps.html
I know Keltia already posted something very similar, but Linux doesn't have setproctitle(3). Linux has had this functionality in prctl() since version 2.6.9. I used Fiddle/DL since they are included by default with Ruby.
require("fiddle")
def set_process_name_linux(name)
Fiddle::Function.new(
Fiddle::Handle["prctl".freeze], [
Fiddle::TYPE_INT, Fiddle::TYPE_VOIDP,
Fiddle::TYPE_LONG, Fiddle::TYPE_LONG,
Fiddle::TYPE_LONG
], Fiddle::TYPE_INT
).call(15, name, 0, 0, 0)
end
def set_process_name_unknown(name)
warn("No implementation for this OS.".freeze)
end
def set_process_name(name)
case RUBY_PLATFORM.split("-".freeze)[1]
when "linux".freeze
set_process_name_linux(name)
else
set_process_name_unknown(name)
end
end
From @jessehz answer, following code work perfect on my linux X86_64. Ruby 1.9.3, 2.0, 2.1, 2.2, 2.3 is tested.
Perfect!
def set_process_name_linux(name)
handle = defined?(DL::Handle) ? DL::Handle : Fiddle::Handle
Fiddle::Function.new(
handle['prctl'.freeze], [
Fiddle::TYPE_INT, Fiddle::TYPE_VOIDP,
Fiddle::TYPE_LONG, Fiddle::TYPE_LONG,
Fiddle::TYPE_LONG
], Fiddle::TYPE_INT
).call(15, name, 0, 0, 0)
$PROGRAM_NAME = name
end
set_process_name_linux('dummy')