Getting output of system() calls in Ruby
I'd like to expand & clarify chaos's answer a bit.
If you surround your command with backticks, then you don't need to (explicitly) call system() at all. The backticks execute the command and return the output as a string. You can then assign the value to a variable like so:
output = `ls`
p output
or
printf output # escapes newline chars
How to execute a Ruby system call in the context of the current shell
These things can be tricky with RVM. Try this:
"/bin/bash -c -l 'rvm use 2.5.5 && <add your system commands here>'"
Note: I guess it would create a new shell environment. Do you really need to access your current shell?
Ruby system call with environment variables in windows
Ruby's system()
invokes whatever the host's default shell is, so you need to speak that shell's language.
The default shell on Windows is cmd.exe
, where environment variable FOO
must be referenced as %FOO%
in order to be expanded.
Thus, your code should be:
cmd = 'echo %FOO%'
system({'FOO' => '123'}, cmd)
Setting input for system() calls in ruby
Don't use system
at all for this sort of thing, system
is best for running an external command that you don't need to talk to.
Use Open3.open3
or Open3.open2
to open up some pipes to your external process then write to the stdin
pipe just like writing to any other IO channel; if there is any output to deal with, then you can read it straight from the stdout
pipe just like reading from any other input IO channel.
Get PID of system call in Ruby
If you use Process.spawn
, you will spawn a process, and get its PID, without having to wait for it to finish.
See the docs for more info, and for resource limits, which might be an alternative way to achieve your goal.
System call from Ruby
Use "`" quotes:
`rake db:migrate VERSION=....`
or system
system("rake db:migrate VERSION=....")
Also you can use this notation:
%x[rake db:migrate VERSION=...]
Also see http://blog.jayfields.com/2006/06/ruby-kernel-system-exec-and-x.html
Forming sanitary shell commands or system calls in Ruby
It doesn't look like you need a shell for what you're doing. See the documentation for system
here: http://ruby-doc.org/core/classes/Kernel.html#M001441
You should use the second form of system
. Your example above would become:
system 'usermod', '-p', @options['shadow'], @options['username']
A nicer (IMO) way to write this is:
system *%W(usermod -p #{@options['shadow']} #{@options['username']})
The arguments this way are passed directly into the execve
call, so you don't have to worry about sneaky shell tricks.
How can I pass a variable to a system() call in ruby?
Oh, happy injection. You're looking forIO.popen
.
IO.popen('grep ba', 'r+') {|f| # don't forget 'r+'
f.puts("foo\nbar\nbaz\n") # you can also use #write
f.close_write
f.read # get the data from the pipe
}
# => "bar\nbaz\n"
How to call shell commands from Ruby
This explanation is based on a commented Ruby script from a friend of mine. If you want to improve the script, feel free to update it at the link.
First, note that when Ruby calls out to a shell, it typically calls /bin/sh
, not Bash. Some Bash syntax is not supported by /bin/sh
on all systems.
Here are ways to execute a shell script:
cmd = "echo 'hi'" # Sample string that can be used
Kernel#`
, commonly called backticks –`cmd`
This is like many other languages, including Bash, PHP, and Perl.
Returns the result (i.e. standard output) of the shell command.
Docs: http://ruby-doc.org/core/Kernel.html#method-i-60
value = `echo 'hi'`
value = `#{cmd}`Built-in syntax,
%x( cmd )
Following the
x
character is a delimiter, which can be any character.
If the delimiter is one of the characters(
,[
,{
, or<
,
the literal consists of the characters up to the matching closing delimiter,
taking account of nested delimiter pairs. For all other delimiters, the
literal comprises the characters up to the next occurrence of the
delimiter character. String interpolation#{ ... }
is allowed.Returns the result (i.e. standard output) of the shell command, just like the backticks.
Docs: https://docs.ruby-lang.org/en/master/syntax/literals_rdoc.html#label-Percent+Strings
value = %x( echo 'hi' )
value = %x[ #{cmd} ]Kernel#system
Executes the given command in a subshell.
Returns
true
if the command was found and run successfully,false
otherwise.Docs: http://ruby-doc.org/core/Kernel.html#method-i-system
wasGood = system( "echo 'hi'" )
wasGood = system( cmd )Kernel#exec
Replaces the current process by running the given external command.
Returns none, the current process is replaced and never continues.
Docs: http://ruby-doc.org/core/Kernel.html#method-i-exec
exec( "echo 'hi'" )
exec( cmd ) # Note: this will never be reached because of the line above
Here's some extra advice:$?
, which is the same as $CHILD_STATUS
, accesses the status of the last system executed command if you use the backticks, system()
or %x{}
.
You can then access the exitstatus
and pid
properties:
$?.exitstatus
For more reading see:
- http://www.elctech.com/blog/i-m-in-ur-commandline-executin-ma-commands
- http://blog.jayfields.com/2006/06/ruby-kernel-system-exec-and-x.html
- http://tech.natemurray.com/2007/03/ruby-shell-commands.html
Return output from system command in Ruby?
You could use
output = `heroku create`
See: http://ruby-doc.org/core/classes/Kernel.html
Related Topics
Handling a JavaScript Popup Occurring on a Keyup Event
How to Use Savon Nested Attributes! Hash
How to Validate Xhtml with Nokogiri
What's the Point of Freezing Your Rails Version/Gems
How Does This Ruby Injection Magic Work
Converting a Hash into a Nested Hash
Ruby Ssl Error - Sslv3 Alert Unexpected Message
Functional Code Examples in Ruby
Render Three Different Partials Depending on Button Clicked
Rails Article Helper - "A" or "An"
What Does "<Top (Required)>" Mean in a Ruby Stack Trace
Why Can't I Use an Integer as a Key Using the New Ruby 1.9.2 Hash Syntax
Ruby - Send Get Request with Headers
Error: Failed to Build Gem Native Extension (Ruby Extconf.Rb): MAC Osx
Add Timestamps to an Existing Table
Format the Date Using Ruby on Rails
How to Traverse Symlinked Directories in Ruby with a "**" Glob