In Ruby, the execution of shell commands is not surprising, and Ruby offers about 6 ways for developers to implement them. These methods are simple, and this article will describe how to invoke a terminal command in a Ruby script.
Exec
exec replaces the operation in the current process with the specified command, and the process ends when the command is finished.
Copy Code code as follows:
exec ' echo ' Hello World '
print ' abc '
By executing the above command, we can see that there is no ABC output, and the process is over when the echo "Hello World" command is executed. Will not continue to perform the following print ' ABC '.
Copy Code code as follows:
Ruby Testcommand.rb
Hello World
Using exec a headache is that there is no way to know whether the execution of the shell command succeeds or fails.
System
System and exec are similar, but the commands executed by system are not in the current process, but in a newly created process. System returns a Boolean value indicating whether the command execution results in success or failure.
Copy Code code as follows:
$ IRB
> System ' echo ' Hello $HOSTNAME '
Hello Androidyue
=> true
> puts $?
PID 11845 Exit 0
=> Nil
> System ' false '
=> false
> puts $?
PID 11858 exit 1
=> Nil
>>
System assigns the status code of the process's exit to $, and if the program exits normally, the value of $ is 0, otherwise it is not 0. By detecting the exit status code we can throw an exception in the Ruby script or retry the operation.
Note: The exit status code for the process in the Unix-like system is expressed as 0 and 0, 0 represents success, and non 0 represents failure.
System can tell us whether command execution succeeds or fails, but sometimes we need to get the output of executing the command and use it in a script. Obviously system cannot be directly satisfied, and we need to use inverted quotes to implement it.
Inverted quotation mark (')
Using inverted quotes is a commonly used method in the shell to get the output of a command, which is also possible in Ruby and needs to be changed at all. Executing a command with an inverted quotation mark also executes the command in another process.
Copy Code code as follows:
1.9.3p448:013 > Today = ' Date '
=> "Sat Nov 19:28:55 CST 2014\n"
1.9.3p448:014 > $?
=> #<process::status:pid 11925 Exit 0>
1.9.3p448:015 > $? To_i
=> 0
1.9.3p448:016 >
The above method is so simple that we can manipulate the returned string results directly.
Note that $? is no longer the simple exit status code as described above, it is actually a Process::status object. We can know not only the exit status code of the process, but also the ID of the process. Use $?. To_i will get out of the status code, using $? To_s will get a string containing information such as process ID, exit status code, and so on.
One result of using the inverted quotation marks is that we can only get the standard output (stdout) and not get the standard error message (STDERR), as in the following example, we execute a Perl script that outputs the error string.
Copy Code code as follows:
$ IRB
>> warning = ' perl-e ' warn ' dust in the Wind '
Dust in the wind at-e line 1.
=> ""
>> puts warning
=> Nil
As you can see, warning does not get the wrong information, which means that the inverted quotation marks do not get the standard error information.
Io#popen
Io#popen is also a way to execute a command, and its commands are executed in another process. Using Popen you can handle standard input and output like an Io object.
Copy Code code as follows:
$ IRB
>> Io.popen ("date") {|f| puts f.gets}
Mon Mar 18:58:56 PDT 2007
=> Nil
Open3#popen3
A OPEN3 is also provided in the Standard Ruby Library. Using this class we can easily handle the standard input, output, and error. Here we use a tool that can interact with DC. A DC is an inverse Polish expression (also called a suffix expression, where each operator is placed after its operator), which supports reading mathematical expressions from standard input. In this example, we handle the stack of two values and an operator. Then use p to output the results. For example, we enter 5 and 10, then enter the +, and then we get the output of the 15\n.
Copy Code code as follows:
$ IRB
>> stdin, stdout, stderr = Open3.popen3 (' DC ')
=> [#<io:0x6e5474>, #<io:0x6e5438>, #<io:0x6e53d4>]
>> stdin.puts (5)
=> Nil
>> Stdin.puts (10)
=> Nil
>> stdin.puts ("+")
=> Nil
>> stdin.puts ("P")
=> Nil
>> stdout.gets
=> "15\n"
Using this method, we can not only read the output of the command but also input the command. This method is convenient for interactive operation. By Popen3, we can also get the standard error message.
Copy Code code as follows:
# (IRB continued ...)
>> stdin.puts ("Asdfasdfasdfasdf")
=> Nil
>> stderr.gets
=> "Dc:stack empty\n"
However, Popen3 has a flaw in Ruby 1.8.5, and the exit state of the process is not written to $.
Copy Code code as follows:
$ IRB
>> require "Open3"
=> true
>> stdin, stdout, stderr = Open3.popen3 (' false ')
=> [#<io:0x6f39c0>, #<io:0x6f3984>, #<io:0x6f3920>]
>> $?
=> #<process::status:pid=26285,exited (0) >
>> $? To_i
=> 0
Why is the 0,false command execution after the exit state should be not 0 only right, because of this flaw, we need to understand the OPEN4
Open4#popen4
Open4#popen4 is similar to Open3#popen3, and we can get the exit status of the program. Popen4 can also return a child process ID. You can also get the process exit status by Process::waitpid2 plus the corresponding process ID. But the prerequisite is to install the Open4 gem.
Copy Code code as follows:
$ IRB
>> require "OPEN4"
=> true
>> PID, stdin, stdout, stderr = Open4::p open4 "false"
=> [26327, #<io:0x6dff24>, #<io:0x6dfee8>, #<io:0x6dfe84>]
>> $?
=> Nil
>> PID
=> 26327
>> ignored, status = Process::waitpid2 pid
=> [26327, #<process::status:pid=26327,exited (1)]
>> status.to_i
=> 256