Linux Essentials
October 6, 2021 in linux

I’ve been working exclusively with .NET, Windows, and PowerShell for the past five years. As I make the transition to the wonderful world of Ruby and Rails, I realize that my Linux skills are virtually non-existent, and to become a good Rails developer, I need to understand Linux.

Last week, I got two classic books on Linux: How Linux Works by Brian Ward, and The Linux Command Line by William E. Shotts. This post tries to summarize some of the basics. Future posts will try to gradually explore the advanced concepts as I make my way through the books.

Useful Commands

cat displays the contents of a file, or concatenates the contents of multiple files.

touch creates a file if it doesn’t exist; updates the timestamp if it exists.

grep searches the term client in the provided file. -i for case-insensitive search and -n for printing line numbers next to the results. For example,

grep client -in /etc/ssh/sshd_config

less displays a large file one page at a time. Use the space bar to go forward and b to go back.

file tells the format of a file.

head/tail displays the top or bottom of the file. Pass -n for number of lines, head -5 file

reset re-initializes terminal. Especially useful after resizing the window or if a command results in scrambled window.

Environment Variables

NAME=akshay
export NAME
echo $NAME

I/O Redirection

To send the output of a command to a file, use >, which overwrites the existing content of the file. To append, use >>.

ls > file_name

To send the output of a command to the standard input of another command, use the pipe | character.

head /proc/cpuinfo | tr a-z

Processes

A process is a running program. Each process has a process ID (PID).

ps lists all the running processes.

  1. ps x Show all of your running processes.
  2. ps ax Show all processes on the system, not just the ones you own.
  3. ps u Include more detailed information on processes.
  4. ps w Show full command names, not just what fits on one line.

To check on a specific process, add the PID at the end of the ps command, e.g. ps u 1234

Background Process

Normally, after you run a command, you don’t get the prompt back until the process finishes. You can detach a process from the shell with the & which runs it as a background process. The shell returns immediately with the PID of the process.

If you want to keep a program running when you log out from a remote machine, use the nohup command.

File Modes & Permissions

Determine if a user can read, write, or run the file. View the permissions using ls -l command.

-rw-rw-r-- 1 ak ak  14 Oct  5 07:00 file_one

Leftmost character: - indicates a file, d indicates a directory.

rwx stands for read, write, and execute. From left to right, the permissions stand for a user, group, and other.

To modify the permissions, use the chmod command, e.g. chmod 644 file.

Mode Meaning Used For
644 user: r/w; group, other: read files
600 user: read/write; group, other: none files
755 user: read/write/execute; group, other: read/execute dirs, programs
700 user: read/write/execute; group, other: none dirs, programs
711 user: read/write/execute; group, other: execute dirs

Archiving and Compressing Files

gzip file compresses the file. To keep the original file, pass the -k flag.

gunzip uncompresses a .gz file.

However, gzip doesn’t create archives of files, i.e. it doesn’t pack multiple files and dirs into a single file. For that, use the tar command.

tar command creates an archive.

tar cfv archive.tar file1 file2

The c option requires creating the archive, the v option requests the verbose operation, and the f option takes an argument that sets the name of the archive to operate upon.

The following command instructs tar to store all files from the directory /etc into the archive file etc.tar, verbosely listing the files being archived:

tar cfv etc.tar /etc

To unpack a .tar file, use the x flag, which operates tar in extract mode.

tar xvf archive.tar

To unpack a compressed archive, first uncompress the file and then unpack.

gunzip file.tar.gz
tar xvf file.tar

Or, use the shortcut with the z option that does the same, i.e. tar zxvf file.tar.gz.

That’s it for now. In the future posts, we will tackle some of the more advanced concepts in Linux.

Learning the vi Editor
October 5, 2021 in linux

I tried learning vi quite a few times in the last several years. Each time, I gave up after learning the basics. Being a Windows .NET developer, I just couldn’t find that many use cases for it. On the handful of occasions I found myself editing files on my MacBook, nano was good enough. So I never really learned vi.

Now that I am programming full-time on Ruby and Rails and learning Linux, I realize that vi is an essential skill to have. So I finished the Gentle Introduction to vi chapter from The Linux Command Line, and happy to report that I feel much more comfortable editing files in vi now than just a day before.

Of course, there’s a long way to go, but this book teaches you 20% of the shortcuts you’d be using 80% of the time, which is pretty neat. This post tries to summarize everything I learned, including why you should learn this editor.

Vim Editor

Why Learn vi

  • vi is always available. If you are working with a remote server, vi is guaranteed to be there.
  • vi is lightweight and fast. A skilled vi user never has to lift their fingers from the keyboard while editing.

vim is an enhanced replacement of vi that stands for vi improved, written by Bram Moolenaar.

Move Around

0 (zero)

To the beginning of the current line.

^

To the first non-whitespace character on the current line.

$

To the end of the current line.

G

To the end of the file.

gg

To the top of the file.

w

To the beginning of the next word or punctuation character.

W

To the beginning of the next word, ignoring punctuation characters.

b

To the beginning of the previous word or punctuation character.

B

To the beginning of the previous word, ignoring punctuation characters.

'n'G

To line number. For example, 1G moves to the first line of the file.

G

To the last line of the file.

Insert

i

Switch to the insert mode.

a

Append text at the cursor position.

A

Append text at the end of the line.

o

Insert a blank line below

O

Insert blank line above

Delete Text

(n)x

Delete the character the cursor is on. 3x for three characters.

dd

Delete the current line.

dW

Delete the word from the current cursor.

d$

Delete from the current cursor up to the end of the line.

d0

Delete from the cursor to the beginning.

dG

From the current line to the end of the file.

Cut, Copy, and Paste

All the d commands cut text.

(n)yy

Copy the current line. 5yy to copy the current line and next four lines.

yW

Copy the word from the cursor.

y$

Copy the line from the cursor.

yG

Copy from the line to the end of the file.

p

Paste text on the next line.

Search and Replace

fa

Searches the current line for character a and places the cursor there.

/Example

Searches for the word Example in the file. Press n to move to the next search term.

:%s/line/Line/gc

Replace all occurrences of line with Line with a confirmation.

Useful Commands

(n)u

Undo action. 5u to undo the last five actions.

J

join line, i.e. cut and paste the next line at the end of the current line.

:q

Exit vim. Press :q! to exit without saving.

:w new_file

Save as new_file.

:wq / ZZ

Save and exit.

Learning the Linux command line, like becoming an accomplished pianist, is not something that we pick up in an afternoon. It takes years of practice.

Hope it helps.

What's self?
September 29, 2021 in ruby

The Ruby interpreter executes each line inside an object - the self object. Here are some important rules regarding self.

  • self is constantly changing as a program executes.
  • Only one object can be self at a given time.
  • When you call a method, the receiver becomes self.
  • All instance variables are instance variables of self, and all methods without an explicit receiver are called on self.
  • As soon as you call a method on another object, that other object (receiver) becomes self.

At the top level, self is main, which is an instance of Object. As soon as a Ruby program starts, the Ruby interpreter creates an object called main and all subsequent code is executed in the context of this object. This context is also called top-level context.

puts self  # main
puts self.class  # class

In a class or module definition, the role of self is taken by the class or module itself.

puts self  # main

class Language
  puts self  # Language

  def compile
    puts self  # #<Language:0x00007fc7c191c9f0>
  end
end

ruby = Language.new
ruby.compile

When you call a method, Ruby looks up the method in the object’s ancestor chain, and then executes the method with the receiver as self.

Include-and-Extend
September 25, 2021 in ruby

Here’s a neat trick I learned today.

Typically, when a class includes a module, the module methods become instance methods on the including class. However, with just a little metaprogramming, a module can provide both instance and class methods to the including class. Here’s how that works.

module Taggable
  def self.included(base)
    puts "Taggable is included in #{base}..extending it now."
    base.extend(ClassMethods)
  end

  def save
    puts "instance method: Saving the post"
  end

  module ClassMethods
    def find(id)
      puts "class method: Finding post with the id #{id}"
    end
  end
end

class Post
  include Taggable

end

# Usage
Post.find(3)
post = Post.new
post.save 

# Output
# Taggable is included in Post..extending it now.
# class method: Finding post with the id 3
# instance method: Saving the post

Here, save is a regular method in the Taggable module that becomes an instance method for Post. On the other hand, find is a method defined in the Taggable::ClassMethods module, that becomes a class method on the Post class.

This works because Ruby provides a hook method Module.included(base) that is invoked whenever another module or a class includes the module containing the above method.

module A
  def A.included(mod)
    puts "#{self} included in #{mod}"
  end
end

module Enumerable
  include A
end
 # => prints "A included in Enumerable"

Now, when Post class includes Taggable module, included is invoked, and the Post class is passed as the base argument. Then, we extend Post with ClassMethods, which adds the methods defined in the ClassMethods as the class methods on the Post class.

def self.included(base)
  puts "Taggable is included in #{base}..extending it now."
  base.extend(ClassMethods)
end

As a result, Post gets both instance methods like save and class methods like find.

This include-and-extend trick gives you a nice way to structure the library. With a single include, your class gets access to instance and class methods defined in a well-isolated module. Rails heavily used this pattern, which was later encoded into a feature called concerns, which I will explore in a future post.

Proc vs. Lambda
September 24, 2021 in ruby

Though they might look the same, the Proc and Lambdas have few differences.

The first key difference is that the return keyword means different things. In a lambda, return just returns from the lambda. In a proc, return behaves differently. Rather than return from the proc, it returns from the scope where the proc itself was defined:

def run_proc
  p = proc { return 10 }
  p.call
  20
end

def run_lambda
  p = lambda { return 10 }
  p.call
  20
end

result = run_proc
puts result		# 10

result = run_lambda
puts result		# 20

The second difference between procs and lambdas concerns the way they check their arguments. If the proc is a lambda, Ruby will check that the number of supplied arguments matches the expected parameters.

Generally speaking, lambdas are more intuitive than procs because they’re more similar to methods. They’re pretty strict about arity, and they simply exit when you call return. For this reason, many Rubyists use lambdas as a first choice unless they need the specific features of procs.

from: Metaprogramming Ruby 2

Bindings in Ruby
September 23, 2021 in ruby

A Binding is a whole scope packaged as an object. It allows you to encapsulate and carry the scope around. Later, you can execute a piece of code in the context of that binding, using eval.

The Kernel#binding method returns the current binding object. A binding object encapsulates the variables, methods, and self.

You can pass a binding object as the second argument of the Kernel#eval method, establishing the environment for the evaluation. Kernel#eval takes a string that contains Ruby code, executes it, and returns the result.

eval %q(
  def run(task)
    puts "running task: #{task}"
  end
)

run "compile"

# Output
# running task: compile

The following example illustrates how eval returns a different value for the language for different bindings.

language = "JavaScript"

puts eval("puts language", binding)  # JavaScript

def get_binding
  language = "C-Sharp"
  binding
end

net_binding = get_binding
puts eval("puts language", net_binding)  # C-Sharp

class Ruby
  def get_binding
    language = "Ruby"
    binding
  end
end

rails_binding = Ruby.new.get_binding
puts eval("puts language", rails_binding)  # Ruby

Ruby provides a constant called TOPLEVEL_BINDING that returns the binding of the top-level scope. Use it to access the top-level scope from anywhere in the program.

def run_ruby
  puts "running inside main"
end

class Ruby

  def run_ruby
    puts "running inside Ruby"
  end

  def exec
    eval "run_ruby", binding  # running inside Ruby
    eval "run_ruby", TOPLEVEL_BINDING  # running inside main
  end
end

Ruby.new.exec

At its core, irb is a simple program that parses standard input or a file and passes each line to eval. Even pry does something similar.

from: Metaprogramming Ruby 2

Modify Objects In-Place
September 22, 2021 in ruby

Every time you create or copy something in memory, you add work for GC. Here are some tips from the book Ruby Performance Optimization to write code without using too much memory.

Modify strings in-place.

Instead of making a changed copy, you change the original string. Look for “bang!” functions, such as trim!, gsub!, slice! etc. Use them when you don’t need the original string.

require_relative "./wrapper" # see above for wrapper script

def modify_strings_in_place
  str = "X" * 1024 * 1024 * 10
  measure("copy") { tmp = str.downcase }
  measure("in-place") { str.downcase! }
end

modify_strings_in_place

# Output
# {"3.0.2":{"gc":"disabled","time":0.01,"gc_count":0,"memory":"10 MB"}}
# {"3.0.2":{"gc":"disabled","time":0.01,"gc_count":0,"memory":"0 MB"}}

Use the shift operator << to append strings, instead of using +=.

When you use +=, Ruby creates an intermediate string and assigns it to the original string after appending.

def append_to_string
  measure do
    x = "foo"
    100_000.times { x += "bar" }
  end

  measure do
    x = "foo"
    100_000.times { x << "bar" }
  end
end

append_to_string

# Output
# {"3.0.2":{"gc":"disabled","time":9.42,"gc_count":0,"memory":"6412 MB"}}
# {"3.0.2":{"gc":"disabled","time":0.01,"gc_count":0,"memory":"-2 MB"}}

Modify Arrays in-place.

Do not create a modified copy of the same array unless really necessary.

def modify_array_in_place
  data = Array.new(100) { "x" * 1024 * 1024 }

  measure { data.map { |str| str.upcase } }
  measure { data.map { |str| str.upcase! } }
end

modify_array_in_place

# Output
# {"3.0.2":{"gc":"disabled","time":0.12,"gc_count":0,"memory":"100 MB"}}
# {"3.0.2":{"gc":"disabled","time":0.1,"gc_count":0,"memory":"0 MB"}}

Hope that helps.

Class Metaprogramming in Ruby
September 21, 2021 in ruby

A Ruby class definition is just regular code that runs. When you use the class keyword to create a class, you aren’t just dictating how objects will behave in the future. You are actually running code.

You can put any code in a class definition, and it returns the value of the last statement, just like methods and blocks do.

name = class Ruby
  puts "Hello world"
  creator = "Matz"
end

puts name

# Output
Hello world
Matz

Inside the class definition, the class itself takes the role of the self.

klass = class Ruby
  self
end

puts klass		# Ruby
puts klass.new		# <Ruby:0x00007fbd25854af0>

To access variables defined outside the class definition (i.e., flattening the scope), use class_eval. Inside, you can also define new methods dynamically on the class, using define_method.

ror = "Ruby on Rails"

class Ruby; end

Ruby.class_eval do
  puts ror

  define_method(:run) do
    puts "Hello, from the new method"
  end
end

Ruby.new.run

# Output
# Ruby on Rails
# Hello, from the new method

Instance variables of a class (class instance variables) are different from the instance variables of that class’s objects. If you come from Java or C#, it’s tempting to think that the class instance variables are just the static fields of the class. Instead, they’re just regular instance variables of an object of class Class.

The following example illustrates this. The class Ruby is an object of the class Class, whereas rb is an object of the class Ruby.

class Ruby
  # ror is a instance variable of class 'Ruby'
  @ror = "Ruby on Rails" 

  def self.rails
    puts @ror
  end

  def initialize
    # language is an instance variable of 'a Ruby object'
    @language = "Ruby" 
  end

  def execute
    puts @language
  end
end

rb = Ruby.new

# valid code
Ruby.rails
rb.execute

# invalid code
Ruby.execute
rb.rails

# Output
#
# Ruby on Rails
# Ruby
# undefined method `execute' for Ruby:Class
# undefined method `rails' for #<Ruby:0x00007ff1...

Singleton Methods

When you define a method on a class, e.g. Ruby.rails, it’s also known as a singleton method of a class.

Here’s the syntax to define singleton method on an object. Here, object can be an object reference, a class name, or self.

def object.method_name
  # method body
end

Singleton Classes

A singleton class is where an object’s singleton methods live, whether that object is a class name or an object reference. You can access the singleton class by calling singleton_class method on the object.

The superclass of the singleton class of an object is the object’s class.

The superclass of the singleton class of a class is the singleton class of the class’s superclass.

from: Metaprogramming Ruby 2

Callable Objects
September 20, 2021 in ruby

There are at least three places in Ruby where you can package code to be executed later. In a block, a proc/lambda, and a method.

Block

A block is a chunk of code you can associate with method invocations, almost as if they were parameters. You can use code blocks to implement callbacks, pass around chunks of code, and implement iterators.

Here are two different ways to define blocks. We use the first version with braces for single-line blocks and do/end for multi-line blocks.

# this is a code block
{ puts "hello" } 

# this is also a code block
do
  puts "hello"
  puts "hello world"
end

A block is typically associated with a call to a method, by putting the block at the end of the source line containing the method call. The method can then invoke the block using the yield keyword in Ruby.

def greet(name)
  puts "hey, #{name}"
  yield
end

greet("Matz") { puts "Thanks for creating Ruby" }

greet("David") do 
  puts "Thanks for creating Rails"
end

You can also pass arguments to the call to yield, and Ruby will pass them to the block.

def add(a, b)
  sum = a + b
  yield sum
end

add(3, 4) { |sum| puts "result: #{sum}" }

add(3, 4) do |sum|
  puts "result: #{sum}"
end

Proc

A Proc object encapsulates a block, allowing us to store the block in a local variable, pass it around, and execute it later.

There are four ways to convert a block into a Proc object.

  • Pass a block to a method whose last parameter starts with &.
def foo(p1, p2, &block)
  puts block.inspect
end

# #<Proc:0x00007fd9ff119848 main.rb:5>
foo(1, 3) { "a block" }

# nil
foo(3, 4)
  • Call Proc.new or Kernel#proc, associating it with a block.
block = Proc.new { |arg| puts "a block with argument: #{arg}" }
block_new = proc { |arg| puts "shorthand block with argument: #{arg}" }

#<Proc:0x00007fa532035ac8 main.rb:1>
puts block.inspect
  • Call the method Kernel#lambda and associate a block with it. Notice the appended (lambda) when you inspect the object.
block = lambda { |arg| puts "a block with argument: #{arg}" }

#<Proc:0x00007fa77f04d8b8 main.rb:1 (lambda)>
puts block.inspect
  • Using the -> syntax.
block_arrow = -> (arg) { puts arg }

# #<Proc:0x00007fb388830fc0 main.rb:7 (lambda)>
puts block_arrow.inspect

Once you have a Proc object, you can execute its code by invoking its methods call, yield, or [].

block = proc { |arg| puts "a block with argument: #{arg}" }

# a block with argument: 10
block.call 10

Lambda

The Proc objects created with the lambda syntax (3rd and 4th option above) are called lambdas. To check if a Proc object is a lambda, call the Proc#lambda? method on it.

block = proc { |arg| puts "a block with argument: #{arg}" }
puts block.lambda?		# false

block_lamb = lambda { |arg| puts "a block with argument: #{arg}" }
puts block_lamb.lambda?		# true

block_arrow = -> (arg) { puts "a block with argument: #{arg}" }
puts block_arrow.lambda?		# true

The lambdas differ from the Proc objects created any other way. We will see the differences in a future post.

Method

The Kernel#method returns a method itself as a Method object. You can later execute this method object by invoking the call method on it, similar to a Proc.

class Animal
  def greet
    puts "Hello World"
  end
end

bunny = Animal.new
greet_method = bunny.method(:greet)
greet_method.call   # Hello World

You can convert a Method to a Proc by calling Method#to_proc. You can also convert a block to a method by using define_method and associating the block with it.

An important difference between the lambdas and methods is that Ruby evaluates a lambda in the scope it’s defined it. In contrast, a Method is evaluated in the scope of its object.

from: Metaprogramming Ruby 2

Scope Flattening
September 18, 2021 in ruby

In C# and Java, variables from the outer scope are visible to the inner scope. In Ruby, scopes are sharply separated, and nested visibility is not allowed. As soon as the control enters a new scope, i.e. a class, module, or a method, the previous bindings are replaced by a new set of bindings.

The following example illustrates the above point. When the program control enters the class Runner, the variable num falls out of scope and is no longer visible inside the class or the method.

num = 1

class Runner
  puts "#{num} from class"

  def run
    puts "#{num} from method"
  end
end

Runner.new.run

# (NameError): undefined local variable or method `num' for Runner:Class

A workaround is to use Ruby’s powerful meta-programming features. In Ruby, you can define new classes and methods on the fly, using Class.new and define_method, respectively, and passing a block.

num = 1

Runner = Class.new do
  puts "#{num} from class"

  define_method :run do
    puts "#{num} from method"
  end
end

Runner.new.run

# Output
# ==============
# 1 from class
# 1 from method

Replacing the scope gates (class, method, etc.) with a method call allows one scope to see variables from the outside scope. This is also known as “flattening the scope”.

from: Metaprogramming Ruby 2