What does ruby -run do? How does it work? - ruby

I've seen this used to start a process:
ruby -run
What does it do?
Where is the documentation located?

It's a little misleading in appearance... The flag isn't -run as in the verb run, but rather -r to require the un.rb file from the standard library, which according to documentation, contains:
Utilities to replace common UNIX commands in Makefiles etc
The -r<libraryname> flag allows you to require a library from the command line before your program's execution begins.
See ruby --help for the command line flags (I suspect you already did).

Related

Running perl script with Scalar::Util fails with "Attempt to reload Scalar/Util.pm aborted."

I have recently switched to a Mac Book Pro M1 (from Ubuntu) and installed Perl from homebrew.
I've installed a number of perl packages I commonly use without any issues. Unfortunately at runtime any perl programs that depend on (or use a package that depends on) Scalar::Util or List::Util fail with errors like:
Attempt to reload Scalar/Util.pm aborted.
Compilation failed in require at /opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0/YAML.pm line 21.
BEGIN failed--compilation aborted at /opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0/YAML.pm line 21.
...
or
Can't load '/opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0/darwin-thread-multi-2level/auto/List/Util/Util.bundle' for module List::Util: dlopen(/opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0/darwin-thread-multi-2level/auto/List/Util/Util.bundle, 0x0001): symbol not found in flat namespace (_Perl_croak_memory_wrap) at /System/Library/Perl/5.30/XSLoader.pm line 96.
at /opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0/darwin-thread-multi-2level/List/Util.pm line 24.
Compilation failed in require at /opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0/darwin-thread-multi-2level/Scalar/Util.pm line 23.
I've also tried to install perlbrew as an alternative but haven't succeeded there. I've also checked that everything appears in the PERL5LIB path correctly.
With List::Util I've managed to install a newer version from CPAN but still get the same error. (The builtin Scalar::Util is the latest version)
Any suggestions on what to try to get them working I fear that it's an M1 issue but I'm not sure it could be an xcode issue I guess.
You can replicate this with:
$ cpanm VCSL::Which
$ vcsvimdiff -v
Can't load '/opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0/darwin-thread-multi-2level/auto/List/Util/Util.bundle' for module List::Util: dlopen(/opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0/darwin-thread-multi-2level/auto/List/Util/Util.bundle, 0x0001): symbol not found in flat namespace (_Perl_croak_memory_wrap) at /System/Library/Perl/5.30/XSLoader.pm line 96.
at /opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0/darwin-thread-multi-2level/List/Util.pm line 24.
Compilation failed in require at /opt/homebrew/Cellar/perl/5.34.0/bin/vcsvimdiff line 12.
BEGIN failed--compilation aborted at /opt/homebrew/Cellar/perl/5.34.0/bin/vcsvimdiff line 12.
Unfortunately running
perl -MScalar::Util -e 1
or
perl -MList::Util -e 1
both run successfully. I looked at my PERL5LIB path and only see the homebrew perl paths there.
$ perl -E 'say join "\n", split /:/, $ENV{PERL5LIB}'
/opt/homebrew/Cellar/perl/5.34.0/lib/perl5
/opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0
/opt/homebrew/Cellar/perl/5.34.0/lib/perl5
/opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0
/opt/homebrew/Cellar/perl/5.34.0/lib/perl5
/opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0
All that looks fine with no system perl references
The summary:
check that you aren't missing something
check perl -V to see which perl it is and it's default module search path
check environment variables such as PERL5LIB for conflicting values
look in the shebang line for the programs you are running
Do you have everything?
As Håkon noted, it looks like there are two perl installations interfering with each other. But, also as ikegami said "never seen that" error message. I haven't either, but StackOverflow has seen it.
The entry in [perldiag] is says that the program tried to load the module, failed the first time, and then something tried again:
Attempt to reload %s aborted.
(F) You tried to load a file with "use" or "require" that failed to
compile once already. Perl will not try to compile this file again
unless you delete its entry from %INC. See "require" in perlfunc and
"%INC" in perlvar.
I don't know what keeps it from failing the first time, but you should check with something simple to see if you can load the module:
$ perl -MScalar::Util -e 1
But, it's actually more tricky than this. Maybe that perl can load it, but some other perl can't. And, maybe you have multiple installations of Scalar::Util, but the particular perl and environment and program settings conspire to choose the wrong one.
The environment can tell perl where to look
But, perhaps none of that works.
First, figure out which perl you want to use, and check its settings:
$ perl -V
At the end of the output you should see the interesting environment settings and the default module search path. With a clean session, I don't have any environment variables that contain PERL:
%ENV:
#INC:
/usr/local/perls/perl-5.36.0/lib/site_perl/5.36.0/darwin-2level
/usr/local/perls/perl-5.36.0/lib/site_perl/5.36.0
/usr/local/perls/perl-5.36.0/lib/5.36.0/darwin-2level
/usr/local/perls/perl-5.36.0/lib/5.36.0
However, I can dirty up my environment. I'll set a PERL5LIB value, which prepends directories to the default module search path:
$ export PERL5LIB=/usr/local/perls/perl-5.10.1/lib/5.10.1/darwin-2level:/usr/local/perls/perl-5.10.1/lib/5.10.1:/usr/local/perls/perl-5.10.1/lib/site_perl/5.10.1/darwin-2level:/usr/local/perls/perl-5.10.1/lib/site_perl/5.10.1
Check perl -V again and this interesting thing happens:
Perl lib version (5.10.1) doesn't match executable version (v5.36.0) at /usr/local/perls/perl-5.10.1/lib/5.10.1/darwin-2level/Config.pm line 50.
Compilation failed in require.
BEGIN failed--compilation aborted.
If I try to load Scalar::Util from the command line with -M, which is what I'd expect if you've mixed up the perls:
$ perl -MScalar::Util -e 1
Can't load '/usr/local/perls/perl-5.10.1/lib/5.10.1/darwin-2level/auto/List/Util/Util.bundle' for module List::Util: dlopen(/usr/local/perls/perl-5.10.1/lib/5.10.1/darwin-2level/auto/List/Util/Util.bundle, 0x0001): symbol not found in flat namespace '_PL_sv_no' at /usr/local/perls/perl-5.10.1/lib/5.10.1/darwin-2level/XSLoader.pm line 73.
at /usr/local/perls/perl-5.10.1/lib/5.10.1/darwin-2level/List/Util.pm line 23
Compilation failed in require at /usr/local/perls/perl-5.10.1/lib/5.10.1/darwin-2level/Scalar/Util.pm line 23.
Compilation failed in require.
BEGIN failed--compilation aborted.
Programs may be incorrectly adjusting #INC
I don't think this is a problem with cpanm because the world would have complained by now. However, if some program is doing funky things with #INC, it may be adding the wrong things.
I think the likely case for this is a set of vendor module directories they use and that some of those modules are targeted at a particular perl. When you use a different perl, you get the binary mismatch thing.
Programs choose their interpreter
MacOS: two Perl installs: "Dumper.c: loadable library and perl binaries are mismatched" notes that their home-brew cpanm was hardcoded to use the system perl.
But, there's another part involved. You are running some programs, and those programs choose the perl. If you look at their first lines, they either have an absolute path to a perl, like this:
#!/usr/bin/perl
Or they play a trick to find the first perl in your PATH:
#!/usr/bin/env perl
I don't like that second one because I'm never sure which perl it will find first. In Mastering Perl, I have a long example of someone calling a program "perl", dropping it in a user-controlled directory in PATH (or adding that to PATH for you), then acting like its the real perl but turning off taint-checking along the way. Probably not your problem, but when you let the program guess who is going to handle it weird things can happen.
For example, I guess I haven't installed cpanm for v5.36.0 yet:
$ head -1 `which cpanm`
#!/usr/local/perls/perl-5.34.1/bin/perl
When I run just cpanm, it's going to use v5.34.1 and whatever settings I have for that.
I could tell it directly which perl to use, but I then need to tell that perl where to find the program:
$ perl5.36.0 `which cpanm` ...
Likewise, I have older versions of some programs that I address with the version I intend to use (I do a lot of stuff that runs something against many, many perls):
$ head -1 `which cpan5.10.1`
#!/usr/local/perls/perl-5.10.1/bin/perl
$ head -1 `which cpan5.12.5`
#!/usr/local/perls/perl-5.12.5/bin/perl
When you install programs, such as cpanm, the installation adjusts the shebang line for the perl that installed it. Simply running cpanm does not mean that you are installing into the perl you think you are.

Where to find the ruby executable documentation?

I was trying to find the list of command-line arguments available for the ruby executable in http://ruby-doc.com/ but I could not find anything. After a Google search for "ruby interpreter command line options" I could only find this page, which applies to Ruby 1.4 only. Where can I find the documentation for the ruby executable in an 'official' source, like ruby-doc.com? Thanks!
Easiest option is to run man ruby. It will show your locally installed interpreter options.
Definitive option is the ruby repository on GitHub. Navigate to the version you need in the releases and locate man/ruby.1 file in the tree. The file contains definitions for CLI arguments.
Example: Ruby 2.3.0 interpreter CLI arguments definitions are here.
There is no such thing as "the Ruby executable". Every Ruby implementation has their own commandline executable. (Actually, come to think of it, SmallRuby and BlueRuby didn't have a commandline executable at all.)
And every Ruby implementation has their own commandline flags. That's why there cannot be a document explaining all the options: which implementation's options would that document?
For example, JRuby's --jdb flag to run under the Java Debugger simply doesn't make sense for IronRuby, Rubinius, MacRuby, Topaz, Cardinal, MRuby, or YARV. Rubinius's flag to turn on the sampling profiler doesn't make sense for implementations that don't have a sampling profiler. Rubinius's flag to turn on the native code JIT compiler doesn't make sense for implementations that don't have a native code JIT compiler. And so on.
However, there are a couple of options that most implementations agree on:
-0
-a
-c
-C
-d
-e
-E
-F
-i
-I
-l
-n
-p
-r
-s
-S
-T
-v
-w
-W
-x
BUT!!!
If you look at MRuby, which is the Ruby implementation written by Yukihiro "matz" Matsumoto, Ruby's creator, which is intended to be a lightweight implementation of the minimum core that can still be called "Ruby", it only supports these options:
-b load and execute RiteBinary (mrb) file
-c check syntax only
-e 'command' one line of script
-v print version number, then run in verbose mode
--verbose run in verbose mode
--version print the version
--copyright print the copyright
Of these, -b is clearly implementation specific, and -c, -v, --version, and --copyright have no runtime impact, so we can interpret this as meaning that -e is the only option that must be supported by a conforming Ruby implementation … after all, it is the only option supported by the Ruby implementation written by the only person who can legitimately have a say in what it means to be "a Ruby implementation".

Ruby Script to Command Line Tool

I am trying to make a command line tool. I already have a ruby script (one file). But I want to project it as a normal command line command.
Right now I have to go into the directory where the script is and type ruby script.rb for it to function but i want to make a command such as script [option] from directory and it should process the required option in the script.
Do I need to make an independent ruby gem for this? I have read about some gems like thor and commander but I am not able to use them properly.
How can I make this command line tool?
PS: An example can be the twitter gem and a command line tool 't' which is also a gem.
Ruby, because it's a general-programming language, makes it easy to create command-line scripts. Here's a basic script you can build upon:
#!/usr/bin/env ruby
require 'optparse'
args = {}
OptionParser.new do |opt|
opt.on('-i', '--input FILE', 'File to read') { |o| args[:file_in] = o }
opt.on('-o', '--output FILE', 'File to write') { |o| args[:file_out] = o }
end.parse!
abort "Missing input or output file" unless (args[:file_in] && args[:file_out])
File.write(args[:file_out], File.read(args[:file_in]))
Here's what's happening:
#!/usr/bin/env ruby is commonly called a "bang line". The shell will look for this line at the top of a file to determine what application can read the file and execute/interpret it. env is an application that will look through the user's PATH environment variable and return the first Ruby found as the Ruby to execute the script. Using this makes the script work with Rubies in the normal /usr/bin, /usr/local/bin or when managed by rbenv or RVM.
require 'opt parse' pulls in Ruby's command-line parser class OptionParser, which makes it easy to set up traditional flags, such as -i path/to/file/to/read, -o path/to/file/to/write, or long parameters, like --input or --output. It also automatically supplies the -h and --help flags to return formatted help text for the script. OptionParser is a bit of a learning-curve, so play with the complete example and you'll figure it out.
The rest should be pretty self-explanatory.
Traditionally, executables that are installed by the system go in /usr/bin. Executables we write, or add, go in /usr/local/bin, and I highly recommend sticking with that.
Some OSes don't automatically supply an entry for /usr/local/bin in the PATH, so you might need to modify your PATH setting in your ~/.bashrc, ~/.bash_profile or ~/.profile to allow the shell to locate the script.
Executable scripts need to have their executable flag set: chmod +x /path/to/executable is the basic command. See man chmod for more information.
I tend to leave the script's extension in place; Ruby scripts are "foo.rb", Python are "bar.py", etc. I do that because I prefer to have that extension as a hint of the language it's written in, but YMMV. The extension isn't necessary so go with what works for you.
Beyond all that, you might want to provide logging output, or output to the system's syslog. In the first case use Ruby's built-in Logger class, or the Syslog class in the second case.
Actually there's two great gems for command line apps in Ruby.
First is methadone which is for simpler command line apps.
Another is gli which is for apps with multiple commands, for example something like bundler.
If you want to know more, you can check out book about creating command line apps build awesome command-line apps in ruby by author of these gems.
You do not need to make it a gem, the following suffices:
Change its name from script.rb to script
Add #!/usr/bin/env ruby as the first line of script
Put it somewhere in PATH (e.g. $HOME/bin, making sure it is in PATH), or execute by giving path explicitly, e.g. $HOME/myscriptdir/script

I want to make a shell command program in ruby for windows but everything is in linux

I have a ruby program named options that I want to run from the command line with a few options like
options -add 400
options -sub 600
options -h
I am already using optparse to interpret the commands but I want to run the program as its own script, but have to run it as
ruby options -add 400
I've looked it up and found some answers like How to create a shell command supporting Ruby? which seems to be linux and I'm not sure of part of the explanation like which bin to put in, or answers like Shell execute from Ruby whose answer still requires ruby in the command. Can anyone explain how to do this in more depth, or direct me to a source that explains it without relying on a linux platform?
Assuming that you have ruby in your PATH on Windows couln't you just create wrapper script and place it in folder present at your PATH?
ruby options %*
Do you have thought about to make it as gem ? There is a simple guide http://guides.rubygems.org/, then you can make the gem which will be working on linux and windows too. I don't know if you know but when I did software avaible under shell or bash I used slop (https://github.com/injekt/slop) it is very convenient the gem. Please see the source of slop, because it is an example of gem, all structure and necessary files to build the gem.

OCaml Installation, not finding binaries

I am attempting to install and run objective-caml on a remote unix server.
I have successfully built and installed all files included in the ocaml package. However, when attempting to use it, eg:
[~]# ocamllex
gives:
-bash: /home1/PATHTOMYHOME/local/bin/ocamllex: /usr/local/bin/ocamlrun: bad interpreter: No such file or directory
Is there any way to tell it to look somewhere else for ocamlrun? The correct directory is in the $PATH variable (ocamlrun works).
You can pass the name of the bytecode file to ocamlrun:
/correct/path/to/ocamlrun /home1/PATHTOMYHOME/local/bin/ocamllex
Alternately, it may just work to edit the first line of the bytecode file: there is a #! and a hardcoded path there. The rest of the file is bytecode though, but if your editor does not mess with it, there is a chance...
As a third solution, use the native-compiled version ocamllex.opt: it does not rely on ocamlrun.
On unix systems, Ocaml bytecode executables begin with a shebang line that gives the path to the bytecode interpreter (ocamlrun). It seems that your executables start with #!/usr/local/bin/ocamlrun. Change this to /home1/PATHTOMYHOME/local/bin/ocamlrun.
If you want ocamlrun to be looked up in the $PATH, change the shebang line to #!/usr/bin/env ocamlrun.
Here's a way to change the path to the bytecode executables in the current directories, leaving other files intact. Remove the *.orig files once you've checked the replacement works.
perl -i.orig -pe 's~^#!.*/ocamlrun.*~#!/usr/bin/env ocamlrun~ if $.==1; close ARGV if eof' *
I suggest that you compile OCaml with ./configure -prefix /home1/PATHTOMYHOME/local. That way all programs will look in the right directories automatically.

Resources