Am trying to lock one executable script to make sure it doesn't run second time when there is another process running. Here is my code,
if $0 == __FILE__
if File.new(__FILE__).flock(File::LOCK_EX | File::LOCK_NB)
main()
end
end
and getting below error,
# ruby /tmp/test.rb
/tmp/test.rb:397:in `flock': Bad file number - /tmp/test.rb (Errno::EBADF)
from /tmp/test.rb:397:in `<main>'
#
Am using ruby version 1.9.3,
# ruby --version
ruby 1.9.3p551 (2014-11-13 revision 48407) [sparc-solaris2.11]
#
But its working perfect in Linux environments.
Found the solution. In Solaris we need to open file with read/write mode only then the exclusive lock will happen.
if $0 == __FILE__
if File.new(__FILE__, 'r+').flock(File::LOCK_EX | File::LOCK_NB)
main()
end
end
Related
I write a ruby script in a .rb file. It uses latest Ruby features (version 2.7). Is there any way to force this .rb file can only be executed in a specific Ruby version range? For example, the first line of a .rb file could be:
#! ruby 2.7+
# This .rb file can only be run with Ruby version 2.7 or above
Use the gem semantic to handle parsing the current Ruby version:
require 'semantic'
# Require >= 2.7 < 3
exit unless Semantic::Version.new(RUBY_VERSION).satisfies?('~> 2.7')
# Require >= 2.7, including 3 and above
exit unless Semantic::Version.new(RUBY_VERSION).satisfies?('>= 2.7')
This requires you to use bundler and a Gemfile with your app.
Other comparators are listed in the source code for the gem:
if ['<', '>', '<=', '>='].include?(comparator)
satisfies_comparator? comparator, pad_version_string(other_version_string)
elsif comparator == '~>'
pessimistic_match? other_version_string
else
tilde_matches? other_version_string
end
This will allow you to fine-tune your version requirements.
Naively,
unless RUBY_VERSION[0, 3] == "2.7"
puts "You need 2.7")
exit
end
Running an installed gem is much slower than running its local source counterpart.
Installed gem:
$ time wmctile switch_to Thunderbird
real 0m0.682s
user 0m0.491s
sys 0m0.091s
Local source:
$ time ./work/wmctile/bin/wmctile switch_to Thunderbird
real 0m0.197s
user 0m0.118s
sys 0m0.064s
Why? Could it be because of RVM, or is this a "feature" of Ruby gems in general? Is there a way to speed it up?
This is the generated bin file:
$ which wmctile
/home/some_user_name/.rvm/gems/ruby-2.1.2/bin/wmctile
$ cat $( which wmctile )
#!/usr/bin/env ruby_executable_hooks
#
# This file was generated by RubyGems.
#
# The application 'wmctile' is installed as part of a gem, and
# this file is here to facilitate running it.
#
require 'rubygems'
version = ">= 0"
if ARGV.first
str = ARGV.first
str = str.dup.force_encoding("BINARY") if str.respond_to? :force_encoding
if str =~ /\A_(.*)_\z/ and Gem::Version.correct?($1) then
version = $1
ARGV.shift
end
end
gem 'wmctile', version
load Gem.bin_path('wmctile', 'wmctile', version)
RVM puts the proper directories for your Ruby version and gemset in the path whenever the RVM Ruby is set. My PATH begins with this:
/Users/kbennett/.rvm/gems/ruby-2.3.0/bin
/Users/kbennett/.rvm/gems/ruby-2.3.0#global/bin
/Users/kbennett/.rvm/rubies/ruby-2.3.0/bin
/Users/kbennett/.rvm/bin
So, I think it's the OS and not Ruby itself that is responsible for the delay. You could test this by putting a simple shell script file in that gem bin directory, and calling it with and without its absolute location to see if you get the same difference.
This code broke on Ruby 2.1
class Test
def to_s()
"hi"
end
end
puts [Test.new(), Test.new()].to_s
Ruby 1.9.3:
$ ruby --version
ruby 1.9.3p484 (2013-11-22 revision 43786) [x86_64-linux]
$ /opt/chef/embedded/bin/ruby test.rb
[hi, hi]
Ruby 2.1:
$ ruby --version
ruby 2.1.4p265 (2014-10-27 revision 48166) [x86_64-linux]
$ ruby test.rb
[#<Test:0x000000022ac400>, #<Test:0x000000022ac3d8>]
Is this documented somewhere? How can the old behavior be preserved?
Your code:
puts [Test.new(), Test.new()].to_s
is a questionable use of Array.to_s. Instead I'd use:
puts [Test.new(), Test.new()].map(&:to_s)
While I can see that the first use makes sense, the second use makes more sense and should work in any version of Ruby.
On ruby 2.1.5:
class Test
def to_s
"hi"
end
alias inspect to_s # add this line
end
puts [Test.new, Test.new].to_s
#=> [hi, hi]
This seems like a bug to me. If it is intended behavior, that is really annoying.
You don't need to_s. puts does the work for you
puts [Test.new(), Test.new()]
# hi
# hi
If you want the brackets, that's what inspect is for (in which case it makes sense that you would need to define Test#inspect).
I feel like I'm overlooking something here. When I try to use the Hash.key(keytolookfor) method, I get an error.
Is this method deprecated?
pete#Vader:~/tmp$ ruby -v
ruby 2.1.0p0 (2013-12-25 revision 44422) [x86_64-linux]
pete#Vader:~/tmp$ ./hashtest.rb
./hashtest.rb:8: undefined method `key' for {"firstkey"=>"firstvalue", "secondkey"=>"secondvalue"}:Hash (NoMethodError)
pete#Vader:~/tmp$
The script is as follows.
#!/usr/bin/ruby
testHash = Hash.new
testHash["firstkey"] = "firstvalue"
testHash["secondkey"] = "secondvalue"
if testHash.has_value?("secondvalue")
keyvalue = testHash.key("secondvalue")
puts "match found with key #{keyvalue}"
else
puts "no match found"
end
My wild guess is that your system ruby /usr/bin/ruby is 1.8.7 which doesn't have Hash#key method. ruby -v most probably shows rvm version which is located in ~/.rvm/..., but first line in your script calls /usr/bin/ruby.
Use the heap record for script as follows:
#/usr/bin/env ruby
This picks up the default ruby version specified by the system, rvm, or rbenv. Since Ruby 1.8.7 has no Hash#key, make sure that you're running at least Ruby 1.9.1:
$ /usr/bin/ruby -v
1.9.1p0
Alternatively, use Hash#[] instead:
keyvalue = testHash["secondvalue"]
I have a Ruby script that iterates over each line of a text file.
In Ruby 1.8.* using content.each do |line| works fine, but in Ruby 1.9.* that does not work, and I need to use content.each_line do |line|.
Since this script will be used by several different people, I need to be able to use the right method depending on their version of Ruby.
Is there a way to do this?
The global constant RUBY_VERSION contains the version of the currently running Ruby. So this script will do what you want:
if RUBY_VERSION < "1.9.2"
# code for 1.8.7
else
# code for 1.9.2+
end
If the inner code of the each_line is equal with 1.8.* and 1.9.*, the following approach is more DRY:
each_selector = RUBY_VERSION < "1.9.2" ? :each : :each_line
content.send(each_selector) do | line|
# ...
end