Ruby Tips
実行中のプログラムのディレクトリを取得する
$PROGRAM_NAME と __FILE__ で少し変わる。
main.rb
require_relative 'tmp/load.rb'
puts File.expand_path(File.dirname($PROGRAM_NAME))
puts File.expand_path(File.dirname(__FILE__))
tmp/load.rb
puts File.expand_path(File.dirname($PROGRAM_NAME))
puts File.expand_path(File.dirname(__FILE__))
実行結果
ファイルが /home/dir/ にあるとすると
/home/dir/
/home/dir/tmp
/home/dir
/home/dir
と表示される。
ps で表示されるプログラム名を変更する
$PROGRAM_NAME に代入すれば良い。
#!/usr/bin/env ruby
p Process.pid
p $PROGRAM_NAME
$PROGRAM_NAME = "new program name"
sleep
を実行してから
ps aux | grep <PID>
とすると確認できる。
rubygems のファイルを autoload したい
rubygems の FileName が使用されるときに filename をロードしたい。
autoload :FileName, 'filename'
とするとエラーになる。エラーを回避するには
gem 'filename'
autoload :FileName, 'filename'
とする。
ソースファイルにデータを配列として記述する
「%w」を使うと便利。
data = %w|
60.234630000001 60.234650000001 0.000020000000
60.251240000000 60.251260000000 0.000020000000
60.584040100000 60.584040200000 0.000000100000
|.map { |s| s.to_f }
他のプロセスの情報を取得する
gem の sys-proctable を使えばできるようだ。
gem install sys-proctable
でインストールする。
require 'sys/proctable'
p Sys::ProcTable.ps(Process.pid)
で実行した ruby のプロセスの情報を取得する。 Sys::ProcTable::ProcTableStruct を返す。
p Sys::ProcTable.ps
とするとすべてのプロセスの情報を取得する。 Sys::ProcTable::ProcTableStruct の配列を返す。
データが何を表すかは
man proc
などで調べる。
Process.daemon 後の PID とディレクトリ
Process.daemon を実行したときに PID とディレクトリがどうなるのか気になったので調べた。
dir = File.expand_path(File.dirname(__FILE__))
open(File.join(dir, 'out.txt'), 'a+') do |f|
f.puts "before Process.daemon:\n PID=#{Process.pid}, Directory=#{Dir.pwd}"
end
Process.daemon
open(File.join(dir, 'out.txt'), 'a+') do |f|
f.puts "after Process.daemon:\n PID=#{Process.pid}, Directory=#{Dir.pwd}"
end
を /home/user_name/sample に保存して実行すると out.txt ができる。
before Process.daemon:
PID=3687, Directory=/home/user_name/sample
after Process.daemon:
PID=3692, Directory=/
のようになっていて PID とディレクトリは変更される。 ディレクトリの方は Process.daemon(nochdir=nil,noclose=nil) の nochdir で 制御できる。
fork したプロセスが defunct になって残らないようにする
fork したプロセスを Process.kill しても defunct になって残る。 http://blog.hybridism.com/?p=106 にあるように
Process.detach(pid)
Process.kill(:INT, pid)
のようにする必要がある。
文字列から定数名を作る
active_support の constantize メソッドを使う。
require 'active_support'
require 'active_support/core_ext/string'
s = 'Time'
p time_const = s.constantize
p time_const.new
シグナルを受け取って終了する
Signal.trap を設定する。
Signal.trap(:TERM) do
exit(0)
end
Signal.trap(:INT) do
exit(0)
end
どのシグナルに対応すれば良いのかは、よくわからなかった。
CPU の情報を得る
sys-cpu を使う。
gem install sys-cpu
でインストールする。
以前は
require 'sys/cpu'
で良かったと思うのだが変更されたのだろうか (2011-09-25)。
require 'linux/sys/cpu'
require 'pp'
pp Sys::CPU.cpu_stats
pp Sys::CPU.load_avg
pp Sys::CPU.model
pp Sys::CPU.processors
クラス変数とクラスのインスタンス変数
クラス変数は子クラスと共有されるが、 クラスのインスタンス変数は共有されない。
class Parent
@@class_var = :parent
@instance_var = :parent
def self.get(type)
case type
when :class
@@class_var
when :instance
@instance_var
else
nil
end
end
end
class Child < Parent
@@class_var = :child
@instance_var = :child
end
puts "Class variable"
p Parent.get(:class)
p Child.get(:class)
puts "Instance variable"
p Parent.get(:instance)
p Child.get(:instance)
を実行すると
Class variable
:child
:child
Instance variable
:parent
:child
となる。
ファイルの MD5 を求める
require 'digest/md5'
path = ARGV[0]
puts Digest::MD5.file(path).to_s
Object の marshal
Marshal できないオブジェクトを含まない場合は、 とくに何もしなくても Marshal.dump できる。 拡張ライブラリを作成したときなどの場合に marshal するには メソッドを定義する必要がある。
http://www.ruby-lang.org/ja/man/html/Marshal.html を読めば必要なことは書いてある。
Object#_dump と Class#_load
class TestMarshal
def _dump
...
end
def self.load(str)
...
end
end
のようにインスタンスメソッドとクラスメソッドを定義する。
Object#marshal_dump と Object#marshal_load
特異メソッドが定義されている場合に なんとか dump するために用いることができる(らしい)。