Rubyプログラム内で別のコマンドを起動する方法について.
主に popen
について書く
方法1: system()関数
system()関数にコマンドを文字列で与える.
最も簡単。
例1 引数無し
system("ls")
実行すると
ruby sys0.rb
a.txt b.txt c.txt sys0.rb sys1.rb sys2.rb
例2 引数あり
system("ls *.txt")
実行すると
ruby sys1.rb
a.txt b.txt c.txt
例3 終了ステータスの取得
Exit status (終了ステータス, 脱出ステータス)は $?
で取得できる
system("ls abc")
print $?, "\n"
実行すると
ruby sys2.rb
ls: cannot access abc: No such file or directory
pid 13715 exit 2
lsは失敗し終了ステータス2が得られている.
方法2 popen
実行したコマンド(子プロセス)の出力を得たり,入力したりできる.
要は,標準入出力にread/writeできる.
例1 結果を得る.標準出力からread
IO.popen("ls","r") do | io |
while io.gets do
print
end
end
実行すると
ruby popen0.rb
a.txt
b.txt
c.txt
popen0.rb
sys0.rb
sys1.rb
sys2.rb
例2 標準入出力にread/write
IO.popen("grep e","r+") do | io |
io.print "Hello,\n"
io.print "World!\n"
io.close_write
while io.gets do
print
end
end
実行すると
ruby popen1.rb
Hello,
方法3 fork and exec
例1 forkのみ
print "Start!\n"
child_pid = fork do
#以下 子プロセスのみが実行
print "I am a child. pid=", Process.pid, "\n"
sleep(1)
#以上 子プロセスのみが実行
end
#以下 親プロセスのみが実行
print "I am a parent. my pid=", Process.pid, ", my child's pid=", child_pid, "\n"
Process.waitpid(child_pid) #子プロセスの終了を待つ
実行すると
ruby fork0.rb
Start!
I am a parent. my pid=25527, my child's pid=25529
I am a child. pid=25529
例2 fork and exec
print "Start!\n"
child_pid = fork do
#以下 子プロセスのみが実行
exec("ls")
#以上 子プロセスのみが実行
#以下 実行されない
abc()
#以上 実行されない
end
#以下 親プロセスのみが実行
print "I am a parent. my pid=", Process.pid, ", my child's pid=", child_pid, "\n"
Process.waitpid(child_pid) #子プロセスの終了を待つ
実行すると
ruby fork1.rb
Start!
I am a parent. my pid=25801, my child's pid=25803
a.txt b.txt c.txt fork0.rb fork1.rb popen0.rb popen1.rb sys0.rb sys1.rb sys2.rb