SlideShare a Scribd company logo
Writing Well-behaved 
Unix Utilities 
Rob Miller • robm.me.uk • @robmil
Who are you? 
• Head of Digital at Big Fish 
• We’re a design, branding and 
marketing consultancy 
• Which is to say:
Who are you? 
• I’ve been programming in Ruby for 
several years now 
• But I don’t do much web development 
any more 
• My world is reporting, sysadmin, ops, 
general tools and utilities 
• Ruby is my tool of choice
The command-line 
spectrum 
• One-liner 
• Script 
• Application
The command-line 
spectrum 
• One-liner 
• Script 
• Application
What makes something 
an “application”? 
• Intended for use by others, or for the 
foreseeable future 
• General-purpose 
• Robust 
• Reusable 
• Built to last
An aside: “Unix” 
• A grouping of computer operating 
systems that behave in a relatively 
standard way 
• In practical terms: 
• Linux (Ubuntu, Debian, Fedora, etc.) 
• Mac OS X 
• BSDs (FreeBSD, OpenBSD, etc.)
The Unix Philosophy 
“…no single program or idea makes 
[Unix] work well. Instead, what makes it 
effective is the approach to 
programming… at its heart is the idea 
that the power of a system comes more 
from the relationships among programs 
than from the programs themselves.
The Unix Philosophy 
“Many UNIX programs do 
quite trivial things in isolation, 
but, combined with other 
programs, become general and 
useful tools.” 
— Brian Kernighan, 1984
The Unix Philosophy 
“This is the Unix philosophy: write 
programs that do one thing and do 
it well. Write programs to work 
together. Write programs to handle 
text streams, because that is a 
universal interface.” 
— Doug McIlroy, c. 1978
The Unix Philosophy 
• To summarise: good Unix applications 
play well with others 
• They respect conventions 
• They’re reusable and general in nature 
• They interact with other processes and 
accept interaction in standard ways 
(files, pipes, sockets)
In Ruby 
• What does this mean in the concrete? 
• How do we write Ruby applications 
that fit this philosophy? 
• Why is Ruby a great choice for writing 
command-line applications?
A good application…
• works with standard input and output 
• works with files 
• communicates via its exit status 
• respects resource limits 
• handles signals 
• accepts command-line options
…works with standard input 
and standard output 
• Pipelines are the foundation of Unix 
• The goal: 
$ grep foo bar | your-app | head 
• Assume that input will come from an 
arbitrary program, and that your 
output will be fed into one too
In Ruby 
$stdin.each do |line| 
puts some_modification(line) 
end 
• Processes input as a stream — handles 
arbitrarily large input (other streaming 
methods work too — each_char, 
read(bytes), etc.) 
• Outputs to $stdout, so can be 
redirected/piped by the user to a file/ 
another process
…works with files too 
• The goal: 
$ cat foo.txt bar.txt | your-app 
$ your-app foo.txt bar.txt 
• The ultimate flexibility. As 
implemented by cat, grep, and most 
other Unix utilities
In Ruby 
ARGF.each do |line| 
# process a line of input 
end 
• No more effort than reading from 
standard input 
• If ARGV is non-empty, its contents will 
be read as files 
• If it is empty, standard input will be 
used instead
…sets an exit status 
• The goal: 
$ your-app 
$ echo $? 
• Was the process successful or not? 
• 0 for success, >0 for failure — so you 
can communicate up to 255 different 
failure states
In Ruby 
if successful? 
exit 
else 
exit 1 
end 
• Use exit to stop execution of your script 
and return a successful exit status 
• Pass it an argument to alter the exit status 
• Document them!
…respects resource limits 
• Processes have resource limits 
• You should respect them, but you 
can also alter them if you need to 
(be reasonable!) 
• Avoid the dreaded Errno::EMFILE: 
Too many open files
In Ruby 
hard, soft = Process.getrlimit(:NOFILE) 
• Check what the limits of your current 
process are (both hard and soft) and take 
appropriate action 
• Here we check EMFILE, the limit of the 
number of file descriptors that we can 
have open at one time
In Ruby 
begin 
File.open(“foo.txt”) 
rescue Errno::EMFILE 
# Do something graceful! 
end 
• Actually handle resource-limit–related 
errors, and do something sensible 
• That might be: increase the limit and try 
the same operation again
In Ruby 
Process.setrlimit(:NOFILE, 4096) 
• Change the soft limit if you need to; you’re 
generally allowed to! 
• Applies to the current process and its 
children, including subshells — so you can 
make sure third-party code behaves too
…handles signals 
• The goal: to be able to communicate with our 
process using signals 
• Common signals: 
• SIGINT: interrupt (Ctrl+C) 
• SIGCHLD: when a child process terminates 
• SIGHUP: when the terminal is closed 
• SIGUSR1, SIGUSR2: custom signals
In Ruby 
trap :INT do 
# close database connection, 
# other necessary cleanup 
exit 
end 
• trap registers a handler for a particular 
signal (in this case SIGINT) 
• When that signal is sent, our block is 
executed
…accepts 
command-line options 
• The goal: 
$ your-app --verbose -o ‘file.txt’ 
• Allow our users to change behaviour 
based on arguments passed 
• Makes our options scriptable — not 
something that has to be chosen from a 
menu or read from a config file
In Ruby 
require “optparse” 
! 
options = { verbose: false } 
OptionParser.new do |opts| 
opts.banner = "Usage: app.rb [options]" 
! 
opts.on("-v", "--verbose") do |v| 
options[:verbose] = true 
end 
end.parse!
In Ruby 
• OptionParser, part of the standard library 
• Gives you: 
• Options, including short aliases 
• Automatic -h help output 
• Removes options from ARGV, so ARGF 
works as you expect 
• No need to use a Gem!
Wrapping Up

More Related Content

PPTX
Node collaboration - sharing information between your systems
PPTX
Puppetcamp Melbourne - puppetdb
PDF
Real time fulltext search with sphinx
PDF
Building GUI App with Electron and Lisp
PDF
Using Sphinx for Search in PHP
PDF
Real time indexes in Sphinx, Yaroslav Vorozhko
PPTX
Sphinx - High performance full-text search for MySQL
PPTX
The tale of 100 cve's
Node collaboration - sharing information between your systems
Puppetcamp Melbourne - puppetdb
Real time fulltext search with sphinx
Building GUI App with Electron and Lisp
Using Sphinx for Search in PHP
Real time indexes in Sphinx, Yaroslav Vorozhko
Sphinx - High performance full-text search for MySQL
The tale of 100 cve's

What's hot (20)

PDF
Writing a fast HTTP parser
PDF
Logstash family introduction
PDF
Null Bachaav - May 07 Attack Monitoring workshop.
PDF
DrupalANDElasticsearch
PDF
Kafka Workshop
PPT
Logstash
PDF
fluent-plugin-beats at Elasticsearch meetup #14
PPT
ApacheCon NA 2011 report
PDF
Pharo Status Fosdem 2015
PDF
Infrastructure coders logstash
KEY
20120524 english lt2_pythontoolsfortesting
PDF
Woo: Writing a fast web server @ ELS2015
PDF
Dexador Rises
PDF
Ingestion from Kafka Using Gobblin
PDF
Clack: glue for web apps
PDF
Continuous Integration for Pharo Smalltalk Part 2 (Smalltalk and Travis CI)
PDF
Pharo Status ESUG 2014
PDF
Sphinx && Perl Houston Perl Mongers - May 8th, 2014
PDF
Woo: Writing a fast web server
PDF
Fluentd and AWS at classmethod
Writing a fast HTTP parser
Logstash family introduction
Null Bachaav - May 07 Attack Monitoring workshop.
DrupalANDElasticsearch
Kafka Workshop
Logstash
fluent-plugin-beats at Elasticsearch meetup #14
ApacheCon NA 2011 report
Pharo Status Fosdem 2015
Infrastructure coders logstash
20120524 english lt2_pythontoolsfortesting
Woo: Writing a fast web server @ ELS2015
Dexador Rises
Ingestion from Kafka Using Gobblin
Clack: glue for web apps
Continuous Integration for Pharo Smalltalk Part 2 (Smalltalk and Travis CI)
Pharo Status ESUG 2014
Sphinx && Perl Houston Perl Mongers - May 8th, 2014
Woo: Writing a fast web server
Fluentd and AWS at classmethod
Ad

Viewers also liked (20)

PDF
WordPress and Git
PDF
Developing with WordPress and Git
PDF
Wordpress version control
PDF
Migrating a Site Quickly with SSH and WP-CLI (It's not as scary as you think!)
PDF
Enhance discovery Solr and Mahout
PPTX
Introduction to git & WordPress
PPTX
Introducing Git to your FTP workflow
DOC
Some basic unix commands
PPTX
Linux principles and philosophy
PPTX
Unix philosophy and principles
PPTX
Linux principles and philosophy
KEY
Mobile Knife Fighting at JSConf US
PPTX
Eduards Sizovs - Micro Service Architecture
PDF
Bringing the Unix Philosophy to Big Data
PPTX
Mocking Test - QA Ninja Conf 2016
PPTX
Unix Philosophy
ODP
Circuit breakers for Java: Failsafe, Javaslang-Circuitbreaker, Hystrix and Ve...
PDF
To Microservices and Beyond
PPTX
Mockito vs JMockit, battle of the mocking frameworks
PPTX
Using Hystrix to Build Resilient Distributed Systems
WordPress and Git
Developing with WordPress and Git
Wordpress version control
Migrating a Site Quickly with SSH and WP-CLI (It's not as scary as you think!)
Enhance discovery Solr and Mahout
Introduction to git & WordPress
Introducing Git to your FTP workflow
Some basic unix commands
Linux principles and philosophy
Unix philosophy and principles
Linux principles and philosophy
Mobile Knife Fighting at JSConf US
Eduards Sizovs - Micro Service Architecture
Bringing the Unix Philosophy to Big Data
Mocking Test - QA Ninja Conf 2016
Unix Philosophy
Circuit breakers for Java: Failsafe, Javaslang-Circuitbreaker, Hystrix and Ve...
To Microservices and Beyond
Mockito vs JMockit, battle of the mocking frameworks
Using Hystrix to Build Resilient Distributed Systems
Ad

Similar to Writing Well-Behaved Unix Utilities (20)

PPTX
Go fundamentals
PDF
Cucumber in Practice(en)
PDF
Julia Computing - an alternative to Hadoop
PDF
Introduction to multicore .ppt
PPTX
sl slides-unit-1.pptx
PPTX
Introduction to Python Programming
PPTX
MPI n OpenMP
PDF
OpenSAF Symposium_Python Bindings_9.21.11
PPT
Linux operating system by Quontra Solutions
PPTX
Algoritmi e Calcolo Parallelo 2012/2013 - OpenMP
PPTX
Cucumber presenation
PDF
How to write a well-behaved Python command line application
PPTX
Plc part 1
PPTX
Go: What's Different ?
PPTX
Reading Notes : the practice of programming
PDF
Are High Level Programming Languages for Multicore and Safety Critical Conver...
PPTX
Repeating History...On Purpose...with Elixir
PPT
computer languages
PDF
Class_X_PYTHON_J.pdf
PDF
The Ring programming language version 1.6 book - Part 6 of 189
Go fundamentals
Cucumber in Practice(en)
Julia Computing - an alternative to Hadoop
Introduction to multicore .ppt
sl slides-unit-1.pptx
Introduction to Python Programming
MPI n OpenMP
OpenSAF Symposium_Python Bindings_9.21.11
Linux operating system by Quontra Solutions
Algoritmi e Calcolo Parallelo 2012/2013 - OpenMP
Cucumber presenation
How to write a well-behaved Python command line application
Plc part 1
Go: What's Different ?
Reading Notes : the practice of programming
Are High Level Programming Languages for Multicore and Safety Critical Conver...
Repeating History...On Purpose...with Elixir
computer languages
Class_X_PYTHON_J.pdf
The Ring programming language version 1.6 book - Part 6 of 189

Recently uploaded (20)

PDF
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
PDF
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
PDF
System and Network Administration Chapter 2
PDF
Digital Strategies for Manufacturing Companies
PPTX
Operating system designcfffgfgggggggvggggggggg
PDF
AI in Product Development-omnex systems
PDF
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
PDF
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
PDF
wealthsignaloriginal-com-DS-text-... (1).pdf
PDF
How Creative Agencies Leverage Project Management Software.pdf
PPTX
history of c programming in notes for students .pptx
PDF
Which alternative to Crystal Reports is best for small or large businesses.pdf
PDF
2025 Textile ERP Trends: SAP, Odoo & Oracle
PPTX
Reimagine Home Health with the Power of Agentic AI​
PDF
System and Network Administraation Chapter 3
PDF
How to Migrate SBCGlobal Email to Yahoo Easily
PPTX
Introduction to Artificial Intelligence
PDF
Adobe Illustrator 28.6 Crack My Vision of Vector Design
PPTX
Essential Infomation Tech presentation.pptx
PDF
Softaken Excel to vCard Converter Software.pdf
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
System and Network Administration Chapter 2
Digital Strategies for Manufacturing Companies
Operating system designcfffgfgggggggvggggggggg
AI in Product Development-omnex systems
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
wealthsignaloriginal-com-DS-text-... (1).pdf
How Creative Agencies Leverage Project Management Software.pdf
history of c programming in notes for students .pptx
Which alternative to Crystal Reports is best for small or large businesses.pdf
2025 Textile ERP Trends: SAP, Odoo & Oracle
Reimagine Home Health with the Power of Agentic AI​
System and Network Administraation Chapter 3
How to Migrate SBCGlobal Email to Yahoo Easily
Introduction to Artificial Intelligence
Adobe Illustrator 28.6 Crack My Vision of Vector Design
Essential Infomation Tech presentation.pptx
Softaken Excel to vCard Converter Software.pdf

Writing Well-Behaved Unix Utilities

  • 1. Writing Well-behaved Unix Utilities Rob Miller • robm.me.uk • @robmil
  • 2. Who are you? • Head of Digital at Big Fish • We’re a design, branding and marketing consultancy • Which is to say:
  • 3. Who are you? • I’ve been programming in Ruby for several years now • But I don’t do much web development any more • My world is reporting, sysadmin, ops, general tools and utilities • Ruby is my tool of choice
  • 4. The command-line spectrum • One-liner • Script • Application
  • 5. The command-line spectrum • One-liner • Script • Application
  • 6. What makes something an “application”? • Intended for use by others, or for the foreseeable future • General-purpose • Robust • Reusable • Built to last
  • 7. An aside: “Unix” • A grouping of computer operating systems that behave in a relatively standard way • In practical terms: • Linux (Ubuntu, Debian, Fedora, etc.) • Mac OS X • BSDs (FreeBSD, OpenBSD, etc.)
  • 8. The Unix Philosophy “…no single program or idea makes [Unix] work well. Instead, what makes it effective is the approach to programming… at its heart is the idea that the power of a system comes more from the relationships among programs than from the programs themselves.
  • 9. The Unix Philosophy “Many UNIX programs do quite trivial things in isolation, but, combined with other programs, become general and useful tools.” — Brian Kernighan, 1984
  • 10. The Unix Philosophy “This is the Unix philosophy: write programs that do one thing and do it well. Write programs to work together. Write programs to handle text streams, because that is a universal interface.” — Doug McIlroy, c. 1978
  • 11. The Unix Philosophy • To summarise: good Unix applications play well with others • They respect conventions • They’re reusable and general in nature • They interact with other processes and accept interaction in standard ways (files, pipes, sockets)
  • 12. In Ruby • What does this mean in the concrete? • How do we write Ruby applications that fit this philosophy? • Why is Ruby a great choice for writing command-line applications?
  • 14. • works with standard input and output • works with files • communicates via its exit status • respects resource limits • handles signals • accepts command-line options
  • 15. …works with standard input and standard output • Pipelines are the foundation of Unix • The goal: $ grep foo bar | your-app | head • Assume that input will come from an arbitrary program, and that your output will be fed into one too
  • 16. In Ruby $stdin.each do |line| puts some_modification(line) end • Processes input as a stream — handles arbitrarily large input (other streaming methods work too — each_char, read(bytes), etc.) • Outputs to $stdout, so can be redirected/piped by the user to a file/ another process
  • 17. …works with files too • The goal: $ cat foo.txt bar.txt | your-app $ your-app foo.txt bar.txt • The ultimate flexibility. As implemented by cat, grep, and most other Unix utilities
  • 18. In Ruby ARGF.each do |line| # process a line of input end • No more effort than reading from standard input • If ARGV is non-empty, its contents will be read as files • If it is empty, standard input will be used instead
  • 19. …sets an exit status • The goal: $ your-app $ echo $? • Was the process successful or not? • 0 for success, >0 for failure — so you can communicate up to 255 different failure states
  • 20. In Ruby if successful? exit else exit 1 end • Use exit to stop execution of your script and return a successful exit status • Pass it an argument to alter the exit status • Document them!
  • 21. …respects resource limits • Processes have resource limits • You should respect them, but you can also alter them if you need to (be reasonable!) • Avoid the dreaded Errno::EMFILE: Too many open files
  • 22. In Ruby hard, soft = Process.getrlimit(:NOFILE) • Check what the limits of your current process are (both hard and soft) and take appropriate action • Here we check EMFILE, the limit of the number of file descriptors that we can have open at one time
  • 23. In Ruby begin File.open(“foo.txt”) rescue Errno::EMFILE # Do something graceful! end • Actually handle resource-limit–related errors, and do something sensible • That might be: increase the limit and try the same operation again
  • 24. In Ruby Process.setrlimit(:NOFILE, 4096) • Change the soft limit if you need to; you’re generally allowed to! • Applies to the current process and its children, including subshells — so you can make sure third-party code behaves too
  • 25. …handles signals • The goal: to be able to communicate with our process using signals • Common signals: • SIGINT: interrupt (Ctrl+C) • SIGCHLD: when a child process terminates • SIGHUP: when the terminal is closed • SIGUSR1, SIGUSR2: custom signals
  • 26. In Ruby trap :INT do # close database connection, # other necessary cleanup exit end • trap registers a handler for a particular signal (in this case SIGINT) • When that signal is sent, our block is executed
  • 27. …accepts command-line options • The goal: $ your-app --verbose -o ‘file.txt’ • Allow our users to change behaviour based on arguments passed • Makes our options scriptable — not something that has to be chosen from a menu or read from a config file
  • 28. In Ruby require “optparse” ! options = { verbose: false } OptionParser.new do |opts| opts.banner = "Usage: app.rb [options]" ! opts.on("-v", "--verbose") do |v| options[:verbose] = true end end.parse!
  • 29. In Ruby • OptionParser, part of the standard library • Gives you: • Options, including short aliases • Automatic -h help output • Removes options from ARGV, so ARGF works as you expect • No need to use a Gem!