มี server นึง (เขียนด้วย C/C++) ในบริษัทผมที่ผมต้องใช้งาน ต้องขอข้อมูลจากมันเป็นประจำ การที่จะเอา software เต็มๆ ไปขอข้อมูลจากมันบางทีก็เป็นเรื่องยุ่งยาก เขาก็เลยมีตัว test connection (เขียนด้วย C/C++ เช่นกัน) ไว้ทดสอบขอข้อมูลจาก server ตัวนั้นเพื่อดูว่ามันได้ข้อมูลไหม หรือเราลงถูกรึเปล่า ทีนี้ไอ้ตัว simple tool ตัวนี้มันใช้ยากพอดูเลย
$> ./runaction -s <server service> -h <server IP/Host> -e <encryption ไหม ตอบได้ yes/no> -p <server port> -f <file ใส่ชื่อ item ที่จะขอ>
จะเห็นว่าชื่อ parameter มันยาก แถมผมต้อง save ชื่อ item ที่จะขอลง file ถ้าจะขอหลาย item ก็ต้องเคาะบรรดทัดไปเรื่อยๆ แบบนี้
$> cat item.txt facebook oracle ibm
แล้วก็ต้องใส่ item.txt ลงไปใน -f ข้างบน แล้ว server ก็จะส่งข้อมูลของ facebook, oracle และ ibm มาให้ แถมยังต้องใส่ env variable “ACTION_PATH” ไปที่ folder ของตัว simple tool นั้นอีก
ที่นี้ผมมีเรื่องที่จะต้องเปลี่ยน item บ่อยๆ เพื่อทดสอบอะไรบางอย่าง เลยอยากจะให้ใส่ชื่อ item ลงใน command เลยไม่ต้องไปสร้าง file เอง แถมทดสอบกับ server เดียวกันซ้ำๆ ก็ใส่ค่า default ไปเลย สรุป requirement ได้ดังนี้
- ผมใส่ชื่อ item เป็น facebook,apple,vodaphone แล้วมันไปสร้าง file ชื่อ item ให้
- มี default host, service, port, encryption ผมไม่จำเป็นต้องใส่ถ้าต่อกับ default server แต่ถ้าผมจะต่อกับ server ตัวอื่น ก็ต้องใส่ parameter อะไรไปในรูปแบบที่ง่ายกว่านี้
- เฉพาะ item เป็น field ที่ต้องใส่เสมอ
จาก Requirement ข้างบน เลยเขียน script ง่อยๆ มาครอบ เริ่มที่ python ที่ผมถนัดโดยใช้ Argparse ที่เนยซดแนะนำ
#!/usr/local/bin/python import os import sys import argparse parser = argparse.ArgumentParser() parser.add_argument('--host',help='input Host IP [optional]',type=str, default='127.0.0.1') parser.add_argument('--service',help='input Host Service [optional]',type=str, default='ABC') parser.add_argument('--port',help='input Host Port [optional]',type=str, default='8880') parser.add_argument('--encrypt',help='input Host encryption [optional]',type=str,choices=['yes','no'],default='yes') parser.add_argument('item',type=str) args = parser.parse_args() ric_file = './tmp_item.txt' addN = lambda value: '%s\n'%(str(value)) with open(ric_file,'w') as foutput: for ric in args.item.split(','): foutput.write(addN(ric)) strCMD="" os.putenv("ACTION_PATH","/home/ply/software/action") strCMD='./runaction -s %s -h %s -e %s -p %s -f %s '%(args.service,args.host,args.encrypt,args.port,ric_file) print strCMD os.system(strCMD)
ข้อสังเกตุ
- lambda addN นี่โผล่มาใน version แรกที่รองรับแค่ item เดียวเพราะถ้าไอ้ text file ไม่ตบบรรทัดใหม่ให้ tool แม่งเจ๊ง -*- ตอนนี้เลยไม่รู้ว่าต้องใส่รึเปล่า
- จริงๆ ลองใช้ parser.add_argument(‘item’,nargs=”*”) แล้วจะได้ array [“item1″,”item2″,”item3”,…] เลยแต่มันรองรับแค่ space delimeter แบบ facebook ibm intel เท่านั้น ใช้ลูกน้ำไม่ได้ เลยย้อนกลับมาสั่ง split แม่ม
อีกภาษานึงที่ผมพยายามหัดมานานมากกกแล้วแต่ยังเขียนไม่เป็นสักทีคือ ruby ก็เลยลองเขียน code ข้างบนด้วย ruby กับ OptionParser logic ก็ลอกมาง่ายๆ เพราะมันตรงไปตรงมาอยู่แล้ว
#!/usr/local/bin/ruby require 'optparse' options={:host=>'127.0.0.1',:service=>'ABC',:port=>'8880',:encrpyt=>'yes',:file=>[]} optparse = OptionParser.new do |opts| opts.banner = "Usage: simple.rb [options]" opts.separator "," opts.on("--host host","input Host IP [optional]") { |host| options[:host]=host } opts.on("--service service","input Host Service [optional]") { |service| options[:service]=service } opts.on("--port port","input Host Port [optional]") { |port| options[:port]=port } opts.on("--protocol OPT",[:yes,:no],"'input Host encrypt [optional]") do |encrpyt| options[:encrpyt]=encrpyt end opts.on("-f a,b,c",Array,"Input Items name") { |f| options[:file]=f } end.parse! ric_file = './tmp_item.txt' File.open(ric_file,'w') do |file| options[:file].each { |ric| file.puts ric } end ENV['ACTION_PATH']='/home/ply/software/action' strCMD = "./runaction -s #{options[:service]} -h #{options[:host]} -e #{options[:encrpyt]} -p #{options[:port]} -f #{ric_file}" exec(strCMD)
ข้อสังเกตุ
- ส่วนตัวคิดว่า argparse ใน python ใช้ง่ายกว่า ruby optparse แต่ optparse ก็ทำให้ผมรับข้อมูลมาเป็น array ได้ตรงไปตรงมากว่า
- optparse บน windows แม่งรับ array ไม่ได้ ไปลองบน linux แล้ว work -*-
- วิธีที่ ruby จะรับ shell command มี 4 วิธี แต่ผมลองแล้ว work แค่ exec แฮะ
- ยังหาวิธีทำ require argument ไม่ได้ -*- ต้องหาทางกันต่อไป
และแล้วชีวิตผมก็ง่ายขึ้นมาระดับนึงอ่ะนะ
Reblogged this on veer.