我想要更改在Linux/Unix top命令中显示的Ruby进程名称。我尝试了
$0='miname'
这个方法只适用于使用 ps 命令,而在 top 命令中该进程一直显示为 "ruby"。
我想要更改在Linux/Unix top命令中显示的Ruby进程名称。我尝试了
$0='miname'
这个方法只适用于使用 ps 命令,而在 top 命令中该进程一直显示为 "ruby"。
戴夫·托马斯在他的博客文章中提到了如何在Rails中实现进程名称修改。关于进程名称更改的代码,与Rails本身无关。他使用了$0='name'
方法。当我按照他的步骤进行操作后,在ps
和top
命令中都看到了进程名称的更改。
在此帖子中,他建议使用键盘命令c
,如果您的top版本默认不显示命令的简短版本。
Ruby 2.1 引入了一个Process.setproctitle
方法来实现这个目的:
Process.setproctitle("My new title")
Process.setproctitle
确实会更改我在ps -ef
中看到的内容,而$0 =“something”
(或$PROGRAM_NAME =“something”
)却不会。 - Nathan Long$0="My new title"
相同,它只是改变了ps输出,不能与pgrep或pkill一起使用。 - zw963setproctitle(3)
)。你应该尝试查看ruby-ffi并创建与setproctitle(3)
的接口。
编辑:我知道你已经得到了答案,但是我想向你展示一些使用ffi的代码:
require "ffi"
#
module LibC
extend FFI::Library
attach_function :setproctitle, [:string, :varargs], :void
end
LibC.setproctitle("Ruby: executing %s", :string, $0)
因为在OS X上不存在setproctitle(3)
,所以无法工作,但在FreeBSD上可以。
我曾经遇到过类似的问题,参考了Dave Thomas的文章并稍微改进了一下技术方法,将其放在一个Rack中间件中,而不是使用before/after模式。
# 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
博客文章中的更多内容:http://blog.actbluetech.com/2011/06/set-your-process-name-in-top-and-ps.html
使用 $0 = 'Foo' 方法可以实现目标 -- 但是在很多版本的 top 中,你需要通过 'c' 命令行模式来切换。我们在 rails 和 CentOS 中使用这种方法非常有效。
我知道Keltia已经发布了非常类似的内容,但Linux没有setproctitle(3)函数。自2.6.9版本以来,Linux已经在prctl()中实现了这个功能。我使用Fiddle / DL,因为它们默认包含在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
根据@jessehz的回答,以下代码在我的Linux X86_64上完美运行。 已测试Ruby 1.9.3、2.0、2.1、2.2、2.3。
完美!
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')