アイオーエススィックス!
Ruby の Process::spawn で返ってくる pid でハマったので、後世にこのことを残してから死のうと思いました。
はまる原因はこの仕様にあった。 http://doc.ruby-lang.org/ja/1.9.3/method/Kernel/m/spawn.html
この形式では command が shell のメタ文字
* ? {} [] <> () ~ & | \ $ ; ' ` " \n
を含む場合、shell 経由で実行されます。 そうでなければインタプリタから直接実行されます。
なるほど。
たとえばレコーダーでrecpt1をspawnするとき
pid = Process::spawn("recpt1 --b25 --strip 20 1800 20.ts")だと、これは recpt1 のプロセスIDが返ってくるけど、実際プログラムだとだいたい変数にはいっていて、ファイル名なんかは番組名でつけちゃったりしてナニかあると困るのでクォテーションするわけで、
pid = Process::spawn("recpt1 --b25 --strip #{channel} #{duration} '#{filename}'")
こうすると、コマンドは shell 経由での実行になり pid は sh -c のものになっている。
んで、あとで recpt1ctl --pid で pid 指定してコントロールしようとしても上手く行かない。
まぁ、シグナル送るだけならプロセスグループ指定して pid を負値にすればいい
# 途中で終了させる例 pid = Process::spawn("recpt1 --b25 --strip #{channel} #{duration} '#{filenam}'", :pgroup => true) ... Process::kill(:INT, -pid)
のだけれど、動的に録画時間伸ばしたいぜっていうときは recpt1ctl 使うのでちょっと困る。
幸い recpt1 は自分の pid を stderr に出力してくれるので、こんなふうにするといいかもしれない。
#!/usr/bin/ruby1.9.1 channel = 20 duration = 60 filename = "hoge.ts" pt1pid = nil err, out = IO::pipe pid = Process::spawn("recpt1 --b25 --strip #{channel} #{duration} '#{filename}'", :err => out) puts "pid: #{pid}" loop do ret = IO::select([err], nil, nil, 5) if ret line = err.gets if /pid = (\d+)/ =~ line puts "recpt1 pid: #{$1}" pt1pid = $1 break end else # タイムアウト break end end out.close if pt1pid system("recpt1ctl --pid #{pt1pid} --extend 60") # 1分伸ばす Process::waitpid(pid) else puts "recpt1 is seems not running" end
実行結果
% ./ptest pid: 14781 recpt1 pid: 14783 Pid = 14783 Extend 60 sec %
ioいるならまぁ IO::popen でもいいけど。
あと recpt1 を & で起動して echo $! を参照するという技もあるけど sh -c がすぐ終了して waitpid が使えなくなるので、recpt1 の終了を検知するのが面倒になる。でもなんか方法あるかもしんないけどハラ減った。
結局のところ、spawn の引数に気をつければいいだけなんで、こんなバッドノウハウ的なことやらんでも次のコードで十分。
#!/usr/bin/ruby1.9.1 require 'tempfile' require 'fileutils' channel = 20 duration = 60 filename = "hoge.ts" temp = Tempfile.new(nil, '.') pid = Process::spawn("recpt1 --b25 --strip #{channel} #{duration} #{temp}", :err => "/dev/null") Process::waitpid(pid) FileUtils::mv(temp, filename)
まぁプロセスが何を録画しているのかわからなくなるけど、そのへんは工夫次第。
0 件のコメント:
コメントを投稿