ruby

Ruby Script 삽질

작업을 단순화하려고 짰던 쉘스크립트(‘cygwin에서 expect 사용 시 에러 나는 경우‘)를 수정할 일이 생겼는데 이왕 고칠거 이 김에 Ruby 공부 겸해서 ruby 스크립트로 변경해 보기로 했다. 작업 흐름은 단순해서

  1. 업로드할 파일 목록을 적어 놓은 텍스트 파일을 읽어서
  2. 1에서 읽은 파일명들을 jar 로 묶어서
  3. 2에서 생성한 파일을 서버에 업로드하고
  4. 서버에 접속해서 몇가지 작업을 처리한다.

구현할 내용은 간단한데 Ruby 초짜다 보니 어쩔 수 없이 무한 삽질.

우선 File.open(…).readlines 에서의 문제

파일 읽은 내용을 jar 명령어의 실행 인자로 넘겨줘야 하는데 readlines 하면서 덧붙여지는 개행문자 때문에 실행 인자가 왜곡되는 현상 발생. 결국 line.chomp 식으로 처리해서 해결.

다음으로 외부 명령어 실행 문제.

jar 명령어를 실행시키기 위해 Ruby 매뉴얼 뒤져서 어렵사리 popen 을 이용해서 구현했다. 하지만 stdout 제어나 등등에서 부족한 점이 느껴져 다시 구글링해보니 popen4이 괜찮다 하길래 이걸 이용해보기로함 ( 참고 : ‘루비로 쉘 명령 내리는 방법 6가지‘ )

gem 이용해서 popen4 추가하고 테스트하는데 설치를 잘못했는지 아무리 해도 해당 라이브러리를 못찾아서 결국 포기하고 루비 표준 라이브러리에 포함되었다는 말만 믿고 popen3로 방향 선회.

popen3 를 이용해서 간단한 샘플 작성해서 테스트하는데 다음과 같은 에러가 또 난다.

`fork’: the fork() function is unimplemented on this machine (NotImplementedError)

알고 보니 popen3은 *NIX 계열에서만 사용 가능하단다. 윈도우 머쉰에서는 win32-open3를 사용해야 한다길래 win32-open3를 설치하고 샘플 코드 테스트. 다행히도 이건 예상보다 쉽게 성공.

파일 업로드 부분은 net/ftp 를 이용해서 쉽게 해결. 마지막으로 서버에 접속해서 명령 실행하기 위해 net/telnet 이용하는 부분이 남았는데

`waitfor’: timed out while waiting for more data (Timeout::Error)

라는 에러나면서 여기서 또 막힘.

‘waitfor’를 매뉴얼 등에서 찾아보니 명령어 입력을 위해 서버 프람프트를 인지시켜 줘야 되는 듯해서  Telnet.new의 인자로 ‘Prompt’ => />$/’와 같이 아주 간단한 패턴 매칭 구문 설정해줬더니 드디어 깔끔하게 실행된다.

아래는 꼬질하지만 이상의 삽질 끝에 만든 스크립트다. Ruby 조금만 다룰 줄 알아도 쉽게 개선할 부분 찾을 수 있을게다. 초짜를 위해 자유롭게 개선할 부분 지적해주길 부탁드린다.


#!/usr/bin/env ruby

require ‘net/ftp’
require ‘rubygems’
require “win32/open3”
require ‘net/telnet’

host_url = “….”
user_pw = “…”

target = ARGV[0]

BASE_CLASS_DIR=’d:/IDE/jdev_oaf/jdevhome/jdev/myclasses/’
Dir.chdir(BASE_CLASS_DIR)
$LOAD_PATH.unshift Dir.pwd

JAR_FILE = “test.jar”

if (File::exist?(JAR_FILE))
File.delete(JAR_FILE)
puts “Delete”
end

#uplist = File.open(“d:/work/oafup.lst”).readlines
uplist = File.open(‘d:/work/oafup.lst’, ‘r’){|file| file.readlines.collect{|line| line.chomp}}

#uplist = File.open(ARGV[0]).readlines
upfiles = “”

uplist.collect do | line |
upfiles += line.gsub(“.”, “\\”).gsub(/^/, “.\\”).concat(“.class “)
end

cmd = “jar cvMf #{JAR_FILE} #{upfiles}”

input, output, error = Open3.popen3(cmd)
err = error.gets # might be nil
if err
puts “Error running command ‘#{cmd}’: ” + err.chomp
next
end

out = output.readlines
puts out.to_s.strip

output.close
error.close

puts “to upload is done …”

if target == “2”
user_id=’…’
elsif target == “L”
user_id=’…’
end

REMOTE_BASE_DIR=”/#{user_id}/#{user_id}comn/java/”
puts REMOTE_BASE_DIR

ftp = Net::FTP.new(host_url)
ftp.login(user = user_id, passwd = user_pw)
ftp.chdir(REMOTE_BASE_DIR)
filesize = Float(File.size(JAR_FILE))
r_size = 0

ftp.putbinaryfile(JAR_FILE, File.basename(JAR_FILE)) { |data|
r_size += data.size
percent = (r_size/filesize)*100
printf(“Transfered : %i \r”, percent)

puts “Uploading a File to #{user_id} …”
}
ftp.close

tn = Net::Telnet.new(‘Host’ => host_url,
‘Prompt’ => />$/,
‘Telnetmode’ => true
) {|str| print str }
tn.login(user_id, user_pw) {|str| print str }
tn.cmd(“cd $JAVA_TOP”) {|str| print str }
tn.cmd(“jar tvf #{JAR_FILE}”) {|str| print str }
tn.cmd(“exit”) {|str| print str }
tn.close

puts “The test job is finished ….”

Advertisements

3 thoughts on “Ruby Script 삽질

  1. 항상 여러 가지 도와주셔서 감사할 따름입니다.
    도와주신 덕분에 마무리 잘 하였습니다.
    오늘 올리고, 다음 주 금요일 정도 출간 예정입니다.
    책 나오고 할 때, 뵙겠습니다.
    고맙습니다.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s