Scripting with Ruby
Stuart Palmer
RubyJax
13 June 2013
6/13/2013Scripting with Ruby
Why scripting?
 Perform regular tasks automatically
 Create daily reports, publish information, back up files, clear history
 Perform background tasks
 Send emails, share information with other systems
 Easily use operating system programs/utilities
 FTP, scp, mail, file storage
6/13/2013Scripting with Ruby
Traditional Scripting
 Shell scripts
 sh, bash, csh, ksh
 DOS batch files
 .bat
 SQL Jobs
 SQL scripts in database
6/13/2013Scripting with Ruby
Sample shell script
#!/bin/tcsh
#
# Expects one parameter in mm/dd/yyyy format
#
setenv TOP /opt/sp
setenv SBIN ${TOP}/sbin
setenv LOG ${TOP}/log
set logDir=${LOG}/trade­totals
#
# Convert mm/dd/yyyy to yyyymmdd
#
set yyyy=`echo $1 | cut ­c7­10`
set mm=`echo $1 | cut ­c1­2`
set dd=`echo $1 | cut ­c4­5`
set tradeDate=${yyyy}${mm}${dd}
set saveDir=${logDir}/${yyyy}
#
# Run the totals
#
fisql ­Uxxx ­Pxxx ­Ssss ­w140 > /tmp/total.out <<EOF
exec getTotals '$1'
go
quit
EOF
#
# See if there was any output
#
if ( ­z /tmp/total.out ) then
   rm ­f /tmp/total.out
   exit 0
endif
#
# Nice formatting
#
echo "" > /tmp/total.fax
echo "Totals for $1" >> /tmp/total.fax
echo "" >> /tmp/total.fax
#
# Get rid of isql junk
#
cat /tmp/total.out | grep ­v line1 | grep ­v '­­­' | grep ­v  
 "return stat" | egrep ­v ­e '^$' > /tmp/total.out1
#
# Get rid of tabs
#
sed ­e "s///" /tmp/total.out1 >> /tmp/total.fax
rm ­f /tmp/total.out /tmp/total.out1
#
# Send the file to the mail server for emailing
#
${SBIN}/email­to­finop.csh "Trade Totals for $1" /tmp/total.fax
#
# Save the file for prosperity
#
if ( ! ­d ${saveDir} ) then
    mkdir ${saveDir}
endif
mv ­f /tmp/total.fax ${saveDir}/total.${tradeDate}
6/13/2013Scripting with Ruby
What can Ruby do?
Ruby Standard Library
✔ Numbers and Math
✔ Strings
✔ Regular expressions
✔ Collections
✔ Dates and Times
✔ Files and Directories
✔ Networking
✔ Threads
6/13/2013Scripting with Ruby
My First Exposure to Ruby
require 'rubygems'
require 'roo'
require 'fileutils'
ss = Excel.new( "business_plan_cmbs.xls" )
ss.default_sheet = "Recommended"
puts ss.cell('B', 8)
'C'.upto('BJ') do |column|
  date      = ss.cell(2, column)
  monthnum  = ss.cell(3, column)
  yearnum   = ss.cell(4, column)
  
  interest  = ss.cell(8, column)
  amort     = ss.cell(9, column)
  other     = ss.cell(10, column)
  sum       = interest + amort + other
  puts "#{date} (#{monthnum}/#{yearnum})t#{sum}" 
end
6/13/2013Scripting with Ruby
Sending email
require 'net/smtp'
# Send email
Net::SMTP.start('mail.silveradosw.com', 25, 'www.silveradosw.com') do |smtp|
  smtp.open_message_stream('stuart@silveradosw.com', 'rubyjax@meetup.com') do |f|
    f.puts 'From: Stuart Palmer <stuart@silveradosw.com>'
    f.puts 'To: Ruby Jax <rubyjax@meetup.com>'
    f.puts "Date: #{DateTime.now.rfc2822}"
    f.puts 'Subject: Your Report for today'
    f.puts 'Message­ID: <ruby­1234@silveradosw.com>'
    lines.each do |line|
      f.puts line
    end
  end
end
6/13/2013Scripting with Ruby
File functions and FTP
require 'file'
require 'fileutils'
# Write to a file
report_file = File.new('/tmp/report­new', 'w')
lines.each do |line|
  report_file.puts line
end
report_file.close
FileUtils.mv('/tmp/report­new', '/opt/xxx/todays­report')
# FTP the file
ftp = Net::FTP.new('ftp.silveradosw.com')
ftp.login('stuart@silveradosw.com', 'xxx')
ftp.passive = true
ftp.chdir('Reports')
ftp.puttextfile('/tmp/report­new', 'todays_report')
ftp.close
6/13/2013Scripting with Ruby
File functions and FTP
require 'file'
require 'fileutils'
require 'net/ftp'
# Write to a file
report_file = File.new('/tmp/report­new', 'w')
lines.each do |line|
  report_file.puts line
end
report_file.close
FileUtils.mv('/tmp/report­new', '/opt/xxx/todays­report')
# FTP the file
ftp = Net::FTP.new('ftp.silveradosw.com')
ftp.login('stuart@silveradosw.com', 'xxx')
ftp.passive = true
ftp.chdir('Reports')
ftp.puttextfile('/tmp/report­new', 'todays_report')
ftp.close
6/13/2013Scripting with Ruby
Client / Server
require 'socket'
socket = TCPSocket.open('localhost', 3333)
socket.puts('hello')
socket.puts('what?')
socket.puts('done')
socket = TCPSocket.open('localhost', 3333)
socket.puts('quit')
require 'socket'
socket = TCPSocket.new('localhost', 3333)
done_listening = false
while !done_listening
  done_reading = false
  while !done_reading
    message = socket.read
    if message =~ /^quit$|^stop$/i
      puts "Received shutdown message."
      done_listening = true
      done_reading = true
    elsif message =~ /^done$/i
      puts "Received client end message."
      done_reading = true
    else
      puts "Read message: [#{message}]"
      socket.puts "OKn"
    end
  end
  socket.close
end
6/13/2013Scripting with Ruby
Threading
require 'thread'
done        = false
socket      = TCPServer.open(3333)
connections = Queue.new
processor   = Thread.new { process(connections, cfg) }
while !done
  # Block, waiting for a request
  client, client_sock_adr = socket.accept
  port, host, ipno = client.peeraddr[1..3]
  # Process the request
  begin
    message = client.readline
  rescue => ex
    client.close
    next
  end
  # Pass off the message and go wait for another one
  connections << OpenStruct.new(client: client, msg: message)
end
processor.join
socket.close
def process(connections, cfg)
  while !connections.empty?
    connection = connections.pop
    client = connection.get_client
    port, host, ipno = client.peeraddr[1..3]
    # Do stuff
  end
end
6/13/2013Scripting with Ruby
Database Access
require 'date'
require 'rubygems'
require 'dbi'
# Call database for data
dbhandle = DBI.connect("dbi:#{sss}", 'xxx', 'xxx')
rows = dbhandle.select_all("EXEC getTotals ?", 
ARGV[0])
if rows.nil? or rows.empty?
  puts "Nothing to report"
  exit
end
lines  = ['']
lines << "Your report for #{Date.today.to_s}"
lines << ''
rows.each do |row|
  lines << row['column_name']
end
6/13/2013Scripting with Ruby
Other Useful Modules
● Log files
require 'logger'
log = Logger.new(STDOUT)
log.level = Logger::WARN
log.debug( 'Created logger' )
log.info( 'Program started' )
log.warn( 'Nothing to do!' )
● Configuration files
config = File.open( 'report.yaml' ) { |yf| YAML::load( yf ) }
config = JSON.parse( IO.read( 'report.json' ) )
6/13/2013Scripting with Ruby
Gems
● XML Generation
✔ nokogiri
● PDF Generation
✔ prawn
● Events / Timers
✔ eventmachine
6/13/2013Scripting with Ruby
Test First
● The usual test frameworks can be used
➢ rspec, test::unit, minitest
C:UsersStuartClientswhbbiwhbbireports> rspec ­c ­fs trade­totals­email­spec.rb
TradeTotalsEmail
  initialize
    should call BaseEmail::new
    should call BaseEmail#from with name and email when set in config
  set_sender
    should call BaseEmail#from with name and email
  set_recipients
    should call add_recipients with passed­in name/email array
    should call add_recipients with config name/email
  set_default_recipients
    should call add_to with config name and email
  add_recipients
    should call add_to with each passed­in name and email
  add_to
    should call BaseEmail:to when non­null name and email passed in
Finished in 0.018 seconds
8 examples, 0 failures
6/13/2013Scripting with Ruby
exit(0)
Stuart Palmer
Silverado Consulting, Inc.
stuart@silveradosw.com
(408)529-6891

More Related Content

PPTX
EXAMEN PRÁCTICO DE COMPUTACIÓN 2DO BIM
PDF
How To Calculate SDE
PPTX
Projectile motion part 1 wrap up
PPTX
Coaching
PDF
The Best Lessons From The Worst Fictional Leaders
PDF
HR's_Greatest_Opportunity
PPS
Laurel & hardy (catherine)
PPTX
Homes for Everyone Chapter Challenge Introduction
EXAMEN PRÁCTICO DE COMPUTACIÓN 2DO BIM
How To Calculate SDE
Projectile motion part 1 wrap up
Coaching
The Best Lessons From The Worst Fictional Leaders
HR's_Greatest_Opportunity
Laurel & hardy (catherine)
Homes for Everyone Chapter Challenge Introduction

Viewers also liked (13)

PPTX
oGIP national products
PPTX
עמותת והדרת
PPTX
הסמכות מטפל
PPT
DIABETIC FOOT. Dr.Ajit Kumar Varma
PPTX
Prepare to Preach (Session 1)
PPT
Sales Presentation
PDF
9 Step Business Sales Process
PPTX
Business leadership: How to be a good leader?
PDF
Solutions to Manage Hospital Parking Challenges and Customer Expectations
PPTX
Prepare to preach (ses 1)
PPTX
Automatic water level controller
PPT
Corporate Etiquette
PPTX
How to Create Engaging Data-driven stories
oGIP national products
עמותת והדרת
הסמכות מטפל
DIABETIC FOOT. Dr.Ajit Kumar Varma
Prepare to Preach (Session 1)
Sales Presentation
9 Step Business Sales Process
Business leadership: How to be a good leader?
Solutions to Manage Hospital Parking Challenges and Customer Expectations
Prepare to preach (ses 1)
Automatic water level controller
Corporate Etiquette
How to Create Engaging Data-driven stories
Ad

Similar to Ruby Scripting (20)

PPT
Leveraging Open Source to Manage SAN Performance
PDF
Chef - industrialize and automate your infrastructure
PDF
Logging in dockerized environment
PDF
Catalyst - refactor large apps with it and have fun!
PPT
PHP CLI: A Cinderella Story
PPTX
Replacing Cron Jobs with EBS Concurrent Requests: Abandoning Rube Goldberg
PPT
PHP 5 Sucks. PHP 5 Rocks.
PDF
Towards the perfect Drupal Dev Machine
PPT
루비가 얼랭에 빠진 날
PDF
Fluentd and Embulk Game Server 4
PDF
Questions On The Code And Core Module
ODP
Pro PostgreSQL, OSCon 2008
KEY
EG Reports - Delicious Data
PDF
Mojolicious
KEY
Rapid Prototyping FTW!!!
PDF
Project Automation
PDF
Scaling in Mind (Case study of Drupal Core)
PDF
Embulk, an open-source plugin-based parallel bulk data loader
PDF
Profiling PHP with Xdebug / Webgrind
PDF
2010 Smith Scripting101
Leveraging Open Source to Manage SAN Performance
Chef - industrialize and automate your infrastructure
Logging in dockerized environment
Catalyst - refactor large apps with it and have fun!
PHP CLI: A Cinderella Story
Replacing Cron Jobs with EBS Concurrent Requests: Abandoning Rube Goldberg
PHP 5 Sucks. PHP 5 Rocks.
Towards the perfect Drupal Dev Machine
루비가 얼랭에 빠진 날
Fluentd and Embulk Game Server 4
Questions On The Code And Core Module
Pro PostgreSQL, OSCon 2008
EG Reports - Delicious Data
Mojolicious
Rapid Prototyping FTW!!!
Project Automation
Scaling in Mind (Case study of Drupal Core)
Embulk, an open-source plugin-based parallel bulk data loader
Profiling PHP with Xdebug / Webgrind
2010 Smith Scripting101
Ad

Recently uploaded (20)

PPTX
Chapter 5: Probability Theory and Statistics
PDF
Taming the Chaos: How to Turn Unstructured Data into Decisions
PDF
sustainability-14-14877-v2.pddhzftheheeeee
PDF
1 - Historical Antecedents, Social Consideration.pdf
PDF
Microsoft Solutions Partner Drive Digital Transformation with D365.pdf
PDF
Univ-Connecticut-ChatGPT-Presentaion.pdf
PDF
TrustArc Webinar - Click, Consent, Trust: Winning the Privacy Game
PDF
August Patch Tuesday
PDF
CloudStack 4.21: First Look Webinar slides
PDF
How ambidextrous entrepreneurial leaders react to the artificial intelligence...
PDF
DASA ADMISSION 2024_FirstRound_FirstRank_LastRank.pdf
PPTX
observCloud-Native Containerability and monitoring.pptx
PDF
Video forgery: An extensive analysis of inter-and intra-frame manipulation al...
PDF
Hybrid horned lizard optimization algorithm-aquila optimizer for DC motor
PPT
What is a Computer? Input Devices /output devices
PPT
Geologic Time for studying geology for geologist
PDF
Transform Your ITIL® 4 & ITSM Strategy with AI in 2025.pdf
PPTX
Group 1 Presentation -Planning and Decision Making .pptx
PDF
Developing a website for English-speaking practice to English as a foreign la...
PPTX
Benefits of Physical activity for teenagers.pptx
Chapter 5: Probability Theory and Statistics
Taming the Chaos: How to Turn Unstructured Data into Decisions
sustainability-14-14877-v2.pddhzftheheeeee
1 - Historical Antecedents, Social Consideration.pdf
Microsoft Solutions Partner Drive Digital Transformation with D365.pdf
Univ-Connecticut-ChatGPT-Presentaion.pdf
TrustArc Webinar - Click, Consent, Trust: Winning the Privacy Game
August Patch Tuesday
CloudStack 4.21: First Look Webinar slides
How ambidextrous entrepreneurial leaders react to the artificial intelligence...
DASA ADMISSION 2024_FirstRound_FirstRank_LastRank.pdf
observCloud-Native Containerability and monitoring.pptx
Video forgery: An extensive analysis of inter-and intra-frame manipulation al...
Hybrid horned lizard optimization algorithm-aquila optimizer for DC motor
What is a Computer? Input Devices /output devices
Geologic Time for studying geology for geologist
Transform Your ITIL® 4 & ITSM Strategy with AI in 2025.pdf
Group 1 Presentation -Planning and Decision Making .pptx
Developing a website for English-speaking practice to English as a foreign la...
Benefits of Physical activity for teenagers.pptx

Ruby Scripting

  • 1. Scripting with Ruby Stuart Palmer RubyJax 13 June 2013
  • 2. 6/13/2013Scripting with Ruby Why scripting?  Perform regular tasks automatically  Create daily reports, publish information, back up files, clear history  Perform background tasks  Send emails, share information with other systems  Easily use operating system programs/utilities  FTP, scp, mail, file storage
  • 3. 6/13/2013Scripting with Ruby Traditional Scripting  Shell scripts  sh, bash, csh, ksh  DOS batch files  .bat  SQL Jobs  SQL scripts in database
  • 4. 6/13/2013Scripting with Ruby Sample shell script #!/bin/tcsh # # Expects one parameter in mm/dd/yyyy format # setenv TOP /opt/sp setenv SBIN ${TOP}/sbin setenv LOG ${TOP}/log set logDir=${LOG}/trade­totals # # Convert mm/dd/yyyy to yyyymmdd # set yyyy=`echo $1 | cut ­c7­10` set mm=`echo $1 | cut ­c1­2` set dd=`echo $1 | cut ­c4­5` set tradeDate=${yyyy}${mm}${dd} set saveDir=${logDir}/${yyyy} # # Run the totals # fisql ­Uxxx ­Pxxx ­Ssss ­w140 > /tmp/total.out <<EOF exec getTotals '$1' go quit EOF # # See if there was any output # if ( ­z /tmp/total.out ) then    rm ­f /tmp/total.out    exit 0 endif # # Nice formatting # echo "" > /tmp/total.fax echo "Totals for $1" >> /tmp/total.fax echo "" >> /tmp/total.fax # # Get rid of isql junk # cat /tmp/total.out | grep ­v line1 | grep ­v '­­­' | grep ­v    "return stat" | egrep ­v ­e '^$' > /tmp/total.out1 # # Get rid of tabs # sed ­e "s///" /tmp/total.out1 >> /tmp/total.fax rm ­f /tmp/total.out /tmp/total.out1 # # Send the file to the mail server for emailing # ${SBIN}/email­to­finop.csh "Trade Totals for $1" /tmp/total.fax # # Save the file for prosperity # if ( ! ­d ${saveDir} ) then     mkdir ${saveDir} endif mv ­f /tmp/total.fax ${saveDir}/total.${tradeDate}
  • 5. 6/13/2013Scripting with Ruby What can Ruby do? Ruby Standard Library ✔ Numbers and Math ✔ Strings ✔ Regular expressions ✔ Collections ✔ Dates and Times ✔ Files and Directories ✔ Networking ✔ Threads
  • 6. 6/13/2013Scripting with Ruby My First Exposure to Ruby require 'rubygems' require 'roo' require 'fileutils' ss = Excel.new( "business_plan_cmbs.xls" ) ss.default_sheet = "Recommended" puts ss.cell('B', 8) 'C'.upto('BJ') do |column|   date      = ss.cell(2, column)   monthnum  = ss.cell(3, column)   yearnum   = ss.cell(4, column)      interest  = ss.cell(8, column)   amort     = ss.cell(9, column)   other     = ss.cell(10, column)   sum       = interest + amort + other   puts "#{date} (#{monthnum}/#{yearnum})t#{sum}"  end
  • 7. 6/13/2013Scripting with Ruby Sending email require 'net/smtp' # Send email Net::SMTP.start('mail.silveradosw.com', 25, 'www.silveradosw.com') do |smtp|   smtp.open_message_stream('stuart@silveradosw.com', 'rubyjax@meetup.com') do |f|     f.puts 'From: Stuart Palmer <stuart@silveradosw.com>'     f.puts 'To: Ruby Jax <rubyjax@meetup.com>'     f.puts "Date: #{DateTime.now.rfc2822}"     f.puts 'Subject: Your Report for today'     f.puts 'Message­ID: <ruby­1234@silveradosw.com>'     lines.each do |line|       f.puts line     end   end end
  • 8. 6/13/2013Scripting with Ruby File functions and FTP require 'file' require 'fileutils' # Write to a file report_file = File.new('/tmp/report­new', 'w') lines.each do |line|   report_file.puts line end report_file.close FileUtils.mv('/tmp/report­new', '/opt/xxx/todays­report') # FTP the file ftp = Net::FTP.new('ftp.silveradosw.com') ftp.login('stuart@silveradosw.com', 'xxx') ftp.passive = true ftp.chdir('Reports') ftp.puttextfile('/tmp/report­new', 'todays_report') ftp.close
  • 9. 6/13/2013Scripting with Ruby File functions and FTP require 'file' require 'fileutils' require 'net/ftp' # Write to a file report_file = File.new('/tmp/report­new', 'w') lines.each do |line|   report_file.puts line end report_file.close FileUtils.mv('/tmp/report­new', '/opt/xxx/todays­report') # FTP the file ftp = Net::FTP.new('ftp.silveradosw.com') ftp.login('stuart@silveradosw.com', 'xxx') ftp.passive = true ftp.chdir('Reports') ftp.puttextfile('/tmp/report­new', 'todays_report') ftp.close
  • 10. 6/13/2013Scripting with Ruby Client / Server require 'socket' socket = TCPSocket.open('localhost', 3333) socket.puts('hello') socket.puts('what?') socket.puts('done') socket = TCPSocket.open('localhost', 3333) socket.puts('quit') require 'socket' socket = TCPSocket.new('localhost', 3333) done_listening = false while !done_listening   done_reading = false   while !done_reading     message = socket.read     if message =~ /^quit$|^stop$/i       puts "Received shutdown message."       done_listening = true       done_reading = true     elsif message =~ /^done$/i       puts "Received client end message."       done_reading = true     else       puts "Read message: [#{message}]"       socket.puts "OKn"     end   end   socket.close end
  • 11. 6/13/2013Scripting with Ruby Threading require 'thread' done        = false socket      = TCPServer.open(3333) connections = Queue.new processor   = Thread.new { process(connections, cfg) } while !done   # Block, waiting for a request   client, client_sock_adr = socket.accept   port, host, ipno = client.peeraddr[1..3]   # Process the request   begin     message = client.readline   rescue => ex     client.close     next   end   # Pass off the message and go wait for another one   connections << OpenStruct.new(client: client, msg: message) end processor.join socket.close def process(connections, cfg)   while !connections.empty?     connection = connections.pop     client = connection.get_client     port, host, ipno = client.peeraddr[1..3]     # Do stuff   end end
  • 12. 6/13/2013Scripting with Ruby Database Access require 'date' require 'rubygems' require 'dbi' # Call database for data dbhandle = DBI.connect("dbi:#{sss}", 'xxx', 'xxx') rows = dbhandle.select_all("EXEC getTotals ?",  ARGV[0]) if rows.nil? or rows.empty?   puts "Nothing to report"   exit end lines  = [''] lines << "Your report for #{Date.today.to_s}" lines << '' rows.each do |row|   lines << row['column_name'] end
  • 13. 6/13/2013Scripting with Ruby Other Useful Modules ● Log files require 'logger' log = Logger.new(STDOUT) log.level = Logger::WARN log.debug( 'Created logger' ) log.info( 'Program started' ) log.warn( 'Nothing to do!' ) ● Configuration files config = File.open( 'report.yaml' ) { |yf| YAML::load( yf ) } config = JSON.parse( IO.read( 'report.json' ) )
  • 14. 6/13/2013Scripting with Ruby Gems ● XML Generation ✔ nokogiri ● PDF Generation ✔ prawn ● Events / Timers ✔ eventmachine
  • 15. 6/13/2013Scripting with Ruby Test First ● The usual test frameworks can be used ➢ rspec, test::unit, minitest C:UsersStuartClientswhbbiwhbbireports> rspec ­c ­fs trade­totals­email­spec.rb TradeTotalsEmail   initialize     should call BaseEmail::new     should call BaseEmail#from with name and email when set in config   set_sender     should call BaseEmail#from with name and email   set_recipients     should call add_recipients with passed­in name/email array     should call add_recipients with config name/email   set_default_recipients     should call add_to with config name and email   add_recipients     should call add_to with each passed­in name and email   add_to     should call BaseEmail:to when non­null name and email passed in Finished in 0.018 seconds 8 examples, 0 failures
  • 16. 6/13/2013Scripting with Ruby exit(0) Stuart Palmer Silverado Consulting, Inc. stuart@silveradosw.com (408)529-6891