Ruby 2.1.0 リファレンスマニュアル > ライブラリ一覧 > 組み込みライブラリ > Kernelモジュール > spawn
spawn(command, options={}) -> Integer
[permalink][rdoc]spawn(env, command, options={}) -> Integer
引数を外部コマンドとして実行しますが、生成した 子プロセスの終了を待ち合わせません。生成した子プロセスのプロセスIDを返します。
この形式では command が shell のメタ文字
* ? {} [] <> () ~ & | \ $ ; ' ` " \n
を含む場合、shell 経由で実行されます。 そうでなければインタプリタから直接実行されます。
[SEE_ALSO] Kernel.#system,Kernel.#exec
spawn(program, *args) -> Integer
[permalink][rdoc]spawn(env, program, *args, options={}) -> Integer
引数を外部コマンドとして実行しますが、生成した 子プロセスの終了を待ち合わせません。生成した子プロセスのプロセスIDを返します。
env に Hash を渡すことで、exec(2) で子プロセス内で ファイルを実行する前に環境変数を変更することができます。 Hash のキーは環境変数名文字列、Hash の値に設定する値とします。 nil とすることで環境変数が削除(unsetenv(3))されます。
# FOO を BAR にして BAZ を削除する pid = spawn({"FOO"=>"BAR", "BAZ"=>nil}, command)
親プロセスは Process.#waitpid で子プロセスの終了を待ち合わせるか もしくは Process.#detach で子プロセスを切り離すかしてください。 そうでないとゾンビプロセスが残る場合があります。
この形式で呼び出した場合、空白や shell のメタキャラクタも そのまま program の引数に渡されます。 先頭の引数が2要素の配列であった場合、第1要素の文字列が実際に 起動するプログラムのパスであり、第2要素が「みせかけ」のプロ グラム名になります。 また、第1要素はフルパスで指定しなくても環境変数 PATH から探します。
Hash を options として渡すことで、起動される子プロセスの
などを変更できます。環境変数のクリアなども指定できます。
以下のオプションが指定できます。
これを true にすると、envで指定した環境変数以外をすべてクリアします。 false だとクリアしません。false がデフォルトです。
引数に true or 0 を渡すと新しいプロセスグループを作成し、そこで動きます。 整数を渡すと、指定したプロセスグループに属します nil を渡すとプロセスグループを変更しません。デフォルトは nil です。
resource limit を設定します。詳しくは Process.#setrlimit を見て ください。引数には整数、もしくは整数2つの配列を渡します。
指定した文字列をカレントディレクトリにします。
指定した整数を umask に設定します。
Hash のキーに子プロセス側のファイルデスクリプタを、 対応する値に親プロセス側のファイルデスクリプタや ファイル名を指定することでリダイレクトを実現できます。
これを true に設定すると リダイレクトされていない、0(stdin), 1(stdout), 2(stderr) 以外の ファイルデスクリプタをすべて閉じます。 true がデフォルトです。
Hash のキー(子プロセス側)には以下のいずれかが指定できます。
配列を渡すことで複数のファイルデスクリプタを同時にリダイレクトできます。
Hash の値(親プロセス側)には以下のいずれかが指定できます。
ファイルデスクリプタを表すためには、以下が利用できます。
「:unsetenv_others」を使うと、envで指定したもの以外の環境変数を クリアします。
# すべての環境変数をクリア pid = spawn(command, :unsetenv_others=>true) # FOO だけ pid = spawn({"FOO"=>"BAR"}, command, :unsetenv_others=>true)
「:pgroup」でプロセスグループを指定できます。
# true, 0 で新しいプロセスグループを作りそのリーダーになります。 pid = spawn(command, :pgroup => true) # 整数を渡すとそのグループに所属します。 pid = spawn(command, :pgroup => 10)
「:rlimit_core」「:rlimit_cpu」などで、resource limit を指定します。 詳しくは Process.#setrlimit を見てください。 このオプションには 整数 or 整数2つの配列、を渡すことができます。 それぞれ Process.#setrlimit の引数が2個、3個の場合に対応します。
# 現プロセスの core の resource limit を取得 cur, max = Process.getrlimit(:CORE) # 一時的に子プロセスの core dump を止める pid = spawn(command, :rlimit_core=>[0,max]) # disable core temporary. # 子プロセスで core dump を出せるようにする pid = spawn(command, :rlimit_core=>max) # enable core dump # 子プロセスで core dump を出せなくする pid = spawn(command, :rlimit_core=>0) # never dump core.
「:chdir」で子プロセスのカレントディレクトリを変更できます。
pid = spawn(command, :chdir=>"/var/tmp")
「:umask」で子プロセスの umask を指定できます。
pid = spawn(command, :umask=>077)
リダイレクトは様々なやりかたが使えます。 Hash のキーが子プロセス側、値が親プロセス側です。
# 以下の例はすべて stderr を stdout にリダイレクトします pid = spawn(command, :err=>:out) pid = spawn(command, 2=>1) pid = spawn(command, STDERR=>:out) pid = spawn(command, STDERR=>STDOUT)
この例では子プロセス側の stdout には触れていないので、 親プロセスから引き継がれます。
Hash の値にはファイル名も指定できます。
pid = spawn(command, :in=>"/dev/null") # read mode pid = spawn(command, :out=>"/dev/null") # write mode pid = spawn(command, :err=>"log") # write mode pid = spawn(command, 3=>"/dev/null") # read mode
stdout と stderr をリダイレクトした場合は、 ファイルは write mode で open されます。それ以外の場合は read mode で open されます。
ファイルのフラグ(write/read mode)やパーミッションを明示したい 場合は、配列を用います。
# なにも指定がなければデフォルトで read mode が使われる。 pid = spawn(command, :in=>["file"]) # read mode で file を open し、リダイレクトする。 pid = spawn(command, :in=>["file", "r"]) # write mode で file を open し、リダイレクトする。 # パーミッションはデフォルトで 644。 pid = spawn(command, :out=>["log", "w"]) # 0644 assumed # write mode、パーミッション 0600 でファイルをオープンし、リダイレクトする。 pid = spawn(command, :out=>["log", "w", 0600]) # flagを文字列でなくビットで指定する pid = spawn(command, :out=>["log", File::WRONLY|File::EXCL|File::CREAT, 0600])
配列で複数のファイルデスクリプタを同時にリダイレクトできます。
# stdout と stderr を "log" ファイルにリダイレクト pid = spawn(command, [:out, :err]=>["log", "w"])
複数のファイルデスクリプタを合わせてリダイレクトするには、 [ :child, FileDescriptor ] を使うこともできます。 これは子プロセス側で FileDescriptor にリダイレクトすることを意味します。 これはファイルデスクリプタを直接指定するのと異なるということに 注意してください。 例えば、
:err => :out
とすると、子プロセスの stderr を親プロセスの stdout にリダイレクトします。
:err => [:child, :out]
とすると、子プロセスの stderr を子プロセスの stdout にリダイレクトします。 これを用いて、IO.popen で、子プロセスの stderr と stdout を混ぜる例を以下に示します。
io = IO.popen(["sh", "-c", "echo out; echo err >&2", :err=>[:child, :out]]) p io.read #=> "out\nerr\n
spawn と IO.popen では デフォルトでは非標準的なファイルデスクリプタ(3以降)をすべて閉じます。 「:close_others」オプションでこの挙動を制御できます。 標準的ファイルデスクリプタ(0,1,2)は :close で明示的に閉じない 限り、このオプションの影響を受けません。
pid = spawn(command, :close_others=>true) # close 3,4,5,... (default) pid = spawn(command, :close_others=>false) # don't close 3,4,5,...
これを利用して spawn を IO.popen のように使うことができます。
# similar to r = IO.popen(command) r, w = IO.pipe pid = spawn(command, :out=>w) # r は子プロセスで閉じられる w.close
「:close」を使ってファイルデスクリプタを明示的に閉じることもできます。
f = open(foo) # f は継承されない # system は :close_others=>false がデフォルトなのでそれ以外は継承される system(command, f=>:close) # don't inherit f.
spawn で特定のファイルデスクリプタだけを継承したい場合は、 io => io という形のオプションを指定します。
# valgrind は --log-fd というオプションでログの出力先を指定できます。 # これで指定したファイルデスクリプタは親プロセスから # 子プロセスに継承されなければならないため、 log_w=>log_w とします。 log_r, log_w = IO.pipe pid = spawn("valgrind", "--log-fd=#{log_w.fileno}", "echo", "a", log_w=>log_w) log_w.close p log_r.read
ファイルデスクリプタを入れ替えることもできます。
# stdout と stderr を入れ替えリダイレクト pid = spawn(command, :out=>:err, :err=>:out)
このような相互参照を解決するため、spawnの内部で新しい ファイルデスクリプタを作り、利用します。
:close_others と :close オプションが意味を持つのは、 子プロセスに閉じていないファイルデスクリプタが全て渡される環境 (Unix 系統の環境)のみです。 例えば Windows では元々子プロセスにはファイルデスクリプタ 0 1 2 のみ 渡されるので :close_others や :close オプションは意味を持ちません。
[SEE_ALSO] Kernel.#system,Kernel.#exec