[RUBY] 루비에서 Process/command 실행하기(Execute Process and command)

C언어부터 ruby, python 등등 여러가지 언어 중 하나라도 해보셨다면 정말 반가운 함수가 있습니다. 바로 system() 함수(C언어 기준)인데요, 이 함수를 통해 시스템에 명령을 내리거나 새로운 프로세스를 생성할 수 있는 함수이지요. 이 함수로 많은 노가다 작업이 줄게되지요.

오늘은 Ruby에서 system()과 같이 다른 프로세스를 실행하거나 명령을 실행할 수 있는 방법에 대해 이야기하려합니다.

ruby는 우와하죠. debian의 think correctly 말고도 맘에 드는게 생긴듯..

Run process/command 1: IO.popen()

다른 프로세스 실행하기, 그 1번째는 바로 IO.popen 입니다. 저도 정말 자주 사용하는데, 은근히 편리합니다. popen 함수는 다른 언어에서도 많이 사용하는 함수입니다. process를 열 수 있는 함수인데 ruby에서는 IO 하단에 메소드로 존재합니다.


.popen([env,], mode = "r"[, opt]) ⇒ IO
.popen([env,], mode = "r"[, opt]) {|io| ... } ⇒ Object

간단하게 사용법을 보면 첫번째 인자값으로 실행할 프로세스 or 명령 , 그다음 프로세스로부터 데이터를 읽어올 것인지 등을 정하는 옵션값으로 정의됩니다.


iozzz = IO.popen("top","r")

이런식으로 popen으로 실행하려는 프로세스(top)를 읽어 데이터를 r(read)하도록 합니다. irb로 보면 return 값이 실행 결과가 아닌 주소값으로 들어가게 되죠.

irb(main):001:0> IO.popen(“top”,”r”) => #<IO:fd 9>

top가 정상적으로 실행되는지 확인해볼까요?

#> ps -aux | grep top root 2546 0.1 0.0 26312 3132 pts/1 S+ 18:30 0:00 top

넵 잘 돌고있네요 : )

또한 몇가지 트릭을 통해 좀 더 편리하게 사용할 수 있습니다.


# set IO encoding
IO.popen("nkf -e filename", :external_encoding=>"EUC-JP") {|nkf_io|
  euc_jp_string = nkf_io.read
}

# merge standard output and standard error using
# spawn option.  See the document of Kernel.spawn.
IO.popen(["ls", "/", :err=>[:child, :out]]) {|ls_io|
  ls_result_with_error = ls_io.read
}

# spawn options can be mixed with IO options
IO.popen(["ls", "/"], :err=>[:child, :out]) {|ls_io|
  ls_result_with_error = ls_io.read
}

IO 값에 대해서 encoding을 하는 등 여러가지 형태로 사용할 수 있겠죠.

Run process/command 2: system()

대망의 system 함수입니다. 어딜가나 존재합니다. 이 방식은 Kernel에 있는 system 함수를 이용하며 subshell을 호출해서 동작합니다. return 값은 단순하게 명령값이 있는지 없는지 true/false로 구별하여줍니다.


stat = system("echo 'hahwul'")

Run process/command 3: exec()

다음은 exec 입니다. 이친구도 system과 같이 어떤 언어든 대체로 존재하며 kenel에 존재합니다. system 함수와 거의 비슷하지만 차이가 있다면 return 값을 주지않아 우리가 명령에 실패하였는지 성공하였는지 알 수 없습니다.


exec( "echo 'hwul'" )

Run process/command 4: #(Kernel)

이번 방법은 바로 #을 이용한 명령 실행입니다. 이 방법도 많이들 사용하시는 것 같습니다.


value = `echo 'hwul'`
value = `#{cmd}`

Run process/command 5: %x(Built-in syntax)

#과 나름 비슷한 방법이죠. %x 즉 Built-in syntax를 이용한 방법입니다. 아래와 같은 형식으로 사용할 수 있습니다.


%x( cmd )

조금 예시로 보여드리면 이렇죠.


value = %x( echo 'hwul' )
value = %x[ #{cmd} ]

Run process/command 6: open3 library . Open3.popen()

사실 이 방법은 2번정도 위치에 나왔어야했는데.. 작성하다보니 맨 뒤에 쓰게 되었네요. ruby안에 존재하는 open3 라이브러리를 이용한 방법입니다. 제가 알기론 IO.popen보다 더 많은 기능(?)을 사용할 수 있다고 하네요.

함수를 보면 아래와 같습니다.


popen3(*cmd, &block)

IO.popen과 유사하게 명령과 옵션을 주어 사용할 수 있습니다. 예시를 보죠.


Open3.popen3("pwd", :chdir=>"/") {|i,o,e,t|
  p o.read.chomp #=> "/"
}

Open3 라이브러리는 굉장히 쓸 수 있는 부분이 많습니다. 다만 프로세스 실행을 위한 popen3 메소드만 보았구요. 자세한 내용은 ruby-doc 참고해주세요. http://ruby-doc.org/stdlib-1.9.3/libdoc/open3/rdoc/Open3.html

Reference

http://www.rubydoc.info/stdlib/core/IO.popen http://ruby-doc.org/stdlib-1.9.3/libdoc/open3/rdoc/Open3.html