Lane Lane - 2 days ago 6
Linux Question

How to programmatically decompress .tar.xz file (without intermediates) in ruby running on ubuntu 14.04?

SO...

I am writing a ruby script to initialize a production host in order to run an application (create user groups, users, SSH keys, etc.) and I am stuck on installing NPM / Node. I don't want to use a package manager to install it, but rather simply grab the .tar.xz file for the version I want (in this case, 6.9.1) and unpack it to a location I want with the binaries added to my path. Currently, we will get this from Node downloads...

I have found this SO answer that I am using to try and get my script working. It looks like Ruby does not have an out of the box way to handle ".xz" files, but my Ubuntu distribution does have a later version of tar so it can handle "tar -xJf ...". I was thinking to do something along the lines of...

require 'fileutils'
require 'open-uri'

uri = "https://nodejs.org/dist/v6.9.1/node-v6.9.1-linux-x64.tar.xz"
source = open(uri)
data = system("cat", IO.binread(source), "|", "tar", "-xJf", "-")
# put data where I want using FileUtils


...I could definitely get this working with an intermediate file and more system commands (or even just a curl call for that matter, but I am trying to not use system calls where possible). I see there are Gems that I can use such as this, but I would like to not include any dependencies. Any thoughts on achieving an elegant solution?

Answer

system is too weak. You want IO::popen for this.

IO.popen(['tar', '-xJC', target_dir, '-f', '-'], 'wb') do |io|
  io.write(IO.binread(source))
end

popen will open a subprocess, and give you io connected to its stdin/stdout. No need for FileUtils, -C option tells tar where to put stuff.

Comments