95

I want my Ruby program to do different things on a Mac than on Windows. How can I find out on which system my program is running?

Andrew Marshall
  • 95,083
  • 20
  • 220
  • 214

11 Answers11

157

Use the RUBY_PLATFORM constant, and optionally wrap it in a module to make it more friendly:

module OS
  def OS.windows?
    (/cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM) != nil
  end

  def OS.mac?
   (/darwin/ =~ RUBY_PLATFORM) != nil
  end

  def OS.unix?
    !OS.windows?
  end

  def OS.linux?
    OS.unix? and not OS.mac?
  end

  def OS.jruby?
    RUBY_ENGINE == 'jruby'
  end
end

It is not perfect, but works well for the platforms that I do development on, and it's easy enough to extend.

Chloe
  • 25,162
  • 40
  • 190
  • 357
Aaron Hinni
  • 14,578
  • 6
  • 39
  • 39
28

I like this, most people use rubygems, its reliable, is cross platform

irb(main):001:0> Gem::Platform.local
=> #<Gem::Platform:0x151ea14 @cpu="x86", @os="mingw32", @version=nil>
irb(main):002:0> Gem::Platform.local.os
=> "mingw32"

update use in conjunction with "Update! Addition! Rubygems nowadays..." to mitigate when Gem::Platform.local.os == 'java'

sandstrom
  • 14,554
  • 7
  • 65
  • 62
jtzero
  • 2,204
  • 2
  • 25
  • 44
18

Either

irb(main):002:0> require 'rbconfig'
=> true
irb(main):003:0> Config::CONFIG["arch"]
=> "i686-linux"

or

irb(main):004:0> RUBY_PLATFORM
=> "i686-linux"
Vinko Vrsalovic
  • 330,807
  • 53
  • 334
  • 373
  • 1
    Don't you mean `Config::CONFIG[‘host_os’]`? – Andrew Grimm Apr 23 '10 at 13:45
  • 6
    "Use RbConfig instead of obsolete and deprecated Config" => ```RbConfig::CONFIG["arch"]``` – jtzero Oct 16 '13 at 18:19
  • 1
    @jtzero If you provide a more complete answer in the comments I'l update the answer written in 2008 – Vinko Vrsalovic Oct 16 '13 at 20:19
  • in ruby 1.9.3 (p327) its just that line, ruby has it by default `irb(main):002:0> require 'rbconfig' => false` – jtzero Oct 18 '13 at 14:09
  • When I did it, I got a statement saying that was depreciated. `(irb):10:in `irb_binding': Use RbConfig instead of obsolete and deprecated Config.` So I used that, `RbConfig::CONFIG.each` and listed all the different values. Maybe you can find something in there to help you find what you're looking for. – FilBot3 Dec 02 '13 at 18:34
  • `RUBY_PLATFORM` is fine. From `Config::CONFIG` though only `target_os` and `host_os` work reliably. As with jruby only they indicate linux. – akostadinov Jun 13 '15 at 18:53
11

I have a second answer, to add more options to the fray. The os rubygem, and their github page has a related projects list.

require 'os'

>> OS.windows?
=> true   # or OS.doze?

>> OS.bits
=> 32

>> OS.java?
=> true # if you're running in jruby.  Also OS.jruby?

>> OS.ruby_bin
=> "c:\ruby18\bin\ruby.exe" # or "/usr/local/bin/ruby" or what not

>> OS.posix?
=> false # true for linux, os x, cygwin

>> OS.mac? # or OS.osx? or OS.x?
=> false
jtzero
  • 2,204
  • 2
  • 25
  • 44
7

Try the Launchy gem (gem install launchy):

require 'launchy'
Launchy::Application.new.host_os_family # => :windows, :darwin, :nix, or :cygwin 
Ryan McGeary
  • 235,892
  • 13
  • 95
  • 104
6

Update! Addition! Rubygems nowadays ships with Gem.win_platform?.

Example usages in the Rubygems repo, and this one, for clarity:

def self.ant_script
  Gem.win_platform? ? 'ant.bat' : 'ant'
end
olleolleolle
  • 1,918
  • 16
  • 20
6

For something readily accessible in most Ruby installations that is already somewhat processed for you, I recommend these:

  1. Gem::Platform.local.os #=> eg. "mingw32", "java", "linux", "cygwin", "aix", "dalvik" (code)
  2. Gem.win_platform? #=> eg. true, false (code)

Both these and every other platform checking script I know is based on interpreting these underlying variables:

  1. RbConfig::CONFIG["host_os"] #=> eg. "linux-gnu" (code 1, 2)
  2. RbConfig::CONFIG["arch"] #=> eg. "i686-linux", "i386-linux-gnu" (passed as parameter when the Ruby interpreter is compiled)
  3. RUBY_PLATFORM #=> eg. "i386-linux-gnu", "darwin" - Note that this returns "java" in JRuby! (code)
    • These are all Windows variants: /cygwin|mswin|mingw|bccwin|wince|emx/
  4. RUBY_ENGINE #=> eg. "ruby", "jruby"

Libraries are available if you don't mind the dependency and want something a little more user-friendly. Specifically, OS offers methods like OS.mac? or OS.posix?. Platform can distinguish well between a variety of Unix platforms. Platform::IMPL will return, eg. :linux, :freebsd, :netbsd, :hpux. sys-uname and sysinfo are similar. utilinfo is extremely basic, and will fail on any systems beyond Windows, Mac, and Linux.

If you want more advanced libraries with specific system details, like different Linux distributions, see my answer for Detecting Linux distribution in Ruby.

sondra.kinsey
  • 583
  • 7
  • 18
  • 1
    I'd welcome more precise explanations or links to how `RUBY_PLATFORM` or `RbConfig::CONFIG["host_os"]` are populated. Looking at the code, it's still not clear to me. – sondra.kinsey Mar 14 '19 at 18:02
4
require 'rbconfig'
include Config

case CONFIG['host_os']
  when /mswin|windows/i
    # Windows
  when /linux|arch/i
    # Linux
  when /sunos|solaris/i
    # Solaris
  when /darwin/i
    #MAC OS X
  else
    # whatever
end
Pikachu
  • 774
  • 13
  • 15
  • I guess this should be `case Config::CONFIG['host_os']` ? – equivalent8 Mar 05 '15 at 17:40
  • actually in ruby 2 it should be `RbConfig::Obsolete::CONFIG['host_os']` ...+no need to include the `Config` – equivalent8 Mar 05 '15 at 17:45
  • Change the `include` or both types of Modules, and then this is the best answer IMO. Notice how he `include`'d the Module, so no need for RbConfig or Config. – FilBot3 May 31 '16 at 20:35
2

We have been doing pretty good so far with the following code

  def self.windows?
    return File.exist? "c:/WINDOWS" if RUBY_PLATFORM == 'java'
    RUBY_PLATFORM =~ /mingw32/ || RUBY_PLATFORM =~ /mswin32/
  end

  def self.linux?
    return File.exist? "/usr" if RUBY_PLATFORM == 'java'
    RUBY_PLATFORM =~ /linux/
  end

  def self.os
    return :linux if self.linux?
    return :windows if self.windows?
    nil
  end
adamliesko
  • 1,887
  • 1
  • 14
  • 21
0

Using the os gem, when loading different binaries for IMGKit

# frozen_string_literal: true
IMGKit.configure do |config|
  if OS.linux? && OS.host_cpu == "x86_64"
    config.wkhtmltoimage =
      Rails.root.join("bin", "wkhtmltoimage-linux-amd64").to_s
  elsif OS.mac? && OS.host_cpu == "x86_64"
    config.wkhtmltoimage =
      Rails.root.join("bin", "wkhtmltoimage-macos-amd64").to_s
  else
    puts OS.report
    abort "You need to add a binary for wkhtmltoimage for your OS and CPU"
  end
end
Dorian
  • 7,749
  • 4
  • 38
  • 57
-7

When I just need to know if it is a Windows or Unix-like OS it is often enough to

is_unix = is_win = false
File::SEPARATOR == '/' ? is_unix = true : is_win = true
dimus
  • 8,712
  • 10
  • 45
  • 56
  • 1
    File::SEPARATOR gives / in windows, so this doesn't work – peter Apr 12 '14 at 13:09
  • 3
    Bad practice all around. If you want to know what the file separator is, use `File::SEPARATOR`. It's best to duck-type the platform just like developing in Ruby. But if you have to know whether the platform is Windows, ask the question instead of trying to infer it. – Robin Daugherty Jul 20 '14 at 17:03