Silencing bundler in an inline script

Bundler can be used in inline scripts, which is awesome! Here is how to silence Bundler so that your script doesn’t start with Bundler’s output, and a workaround for a little gotcha when silencing output.

Tags : Bundler Ruby

Published: March 13, 2024

Ruby is great for writing shell scripts: OptionParser makes it a breeze to parse options, and File and Dir utilities are much cleaner than shelling out to read or check for files.

But even if standard Ruby offers a lot of functionality out-of-the-box, you may want to use gems. And bundler has your back for that! Just require bundler/inline and list gems in a gemfile block, like you’re used to in a Ruby app.

You can instruct Bundler to download the latest version of each gem by passing true as the first parameter to gemfile. Your script will take a little longer to run though, so leave the default unless you really need this. If you don’t wan to see the usual bundle install output, you can additionally pass quiet: true to gemfile.

Basic inline script example:

#!/usr/bin/env ruby

require "bundler/inline"
gemfile do
  source "https://rubygems.org"
  # Add all the gems you want here. For instance: gem "colorize"
end

Force download but don’t print bundle install output:

#!/usr/bin/env ruby

require "bundler/inline"
gemfile(true, quiet: true) do
  source "https://rubygems.org"
  # Add all the gems you want here. For instance: gem "colorize"
end

There’s one gotcha though: if your script is killed while downloading gems, your terminal will no longer show what you type! Pretty rare, but it happened to me so I guess I’m not the only one.

Luckily, there’s an easy workaround, which is to clean up before the script exits. Ruby allows us to respond to signals received by the script using Signal.trap, which is exactly what we need here.

# Allow cancelling without error
Signal.trap("SIGINT") do
  # Reset terminal output if the script quits while installing gems using the quiet option
  system "stty echo"
  # Force outputting a newline
  puts ""
  # Revert any pending operation…
  # Indicate that the script terminated gracefully
  exit true
end