Ruby can be a really stupid language sometimes. Other times however, you run into problems for which Ruby is the greatest thing ever. That’s very much how my love hate relationship with Ruby is. Perhaps over time Swift will be able to take over some of the things I jump to Ruby for, but until that day, I’ll just keep doing what I’m doing.
Ruby is insanely popular for Ruby on Rails, which is essentially just a web server which favors convention over configuration. You can do a lot of stuff really quickly, but the more custom you want, the harder it gets. Or so I’ve read. I’ve only spent a few hours looking into it. Personally, I prefer Ruby for what it really is, a scripting language. When I get tired of having to remember which deep dark hole some file is that I have to edit once every 2 months, I write a Ruby script to open the file up in my editor. I know others may ask why I don’t just bookmark the file. To which I say, because. 1
More often than I expected, I’ve run across the need to do something in Ruby, and then execute a Bash command. After doing some research, I realized that the only reason I can remember how to do this, is because I remember which vague search term I typed into Google. So, in order to free up some of my brain space for more important stuff, I present to you: A Bunch of ways to Execute Shell Commands from Ruby2! (queue awesome music)
Backticks – `cmd`
This is one of the most common ways to execute shell commands. It’s also common usage in other languages, so it should be fairly easy to remember.
There’s two ways to this this, both of which are identical. Backticks are a little shorter, and %x{cmd} is a bit more verbose. It’s really just a style preference
1 2 |
`date` %x{date} |
This method returns the standard output of the command. It also sets $? to the process status.
1 2 3 4 |
value = `date` puts value puts $?.exitstatus |
System
This one is used a little less frequently. It returns true if the command executed successfully, false otherwise. This method will not redirect standard out/error in any way, it just executes the command and tells you if the command ran successfully. Glancing at the source, it looks like it takes the exit status into account when determining the return value.
1 2 3 4 5 6 7 8 9 |
value = system 'date' puts value #the system command outputs the date to stdout #the puts command outputs 'true' to stdout value = system 'echo', 'foo', 'bar' puts value #the system command outputs "foo bar" to stdout #the puts command outputs 'true' to stdout |
The documentation doesn’t explicitly state that it sets the $?, but it does appear to do so.
Exec
This is one that’s really useful for ssh scripts. For example, you want to have some Ruby code to find the full path to an ssh identity key, and then do the ssh command. Exec will replace the current process with the external command. When you call Exec, your Ruby will stop executing. No exceptions
1 2 |
exec 'date' puts 'this line will never be executed' |
1 2 3 4 5 |
#find the ssh key relative to the Ruby file cert = "#{File.dirname(__FILE__)}/keys/WordpressServer.pem" `chmod 400 #{cert}` exec "ssh some-user@encyclopediaofdaniel.com -i #{cert}" |
There are also 3rd party gems that allow you to do all sorts of things with stderr stdout redirection, but I’ve never had reason to use them.