Ste*_*ard 1280
这个解释是基于我朋友的评论Ruby脚本.如果您想改进脚本,请随时在链接上更新它.
首先,请注意当Ruby调用shell时,它通常调用/bin/sh
,而不是 Bash./bin/sh
所有系统都不支持某些Bash语法.
以下是执行shell脚本的方法:
cmd = "echo 'hi'" # Sample string that can be used
Run Code Online (Sandbox Code Playgroud)
Kernel#`
,通常称为反引号 - `cmd`
这和许多其他语言一样,包括Bash,PHP和Perl.
返回shell命令的结果.
文档:http://ruby-doc.org/core/Kernel.html#method-i-60
value = `echo 'hi'`
value = `#{cmd}`
Run Code Online (Sandbox Code Playgroud)内置语法, %x( cmd )
继x
字符是一个分隔符,它可以是任何字符.如果分隔符是字符中的一个(
,[
,{
,或<
,文字由字符直到匹配的结束分隔符,以嵌套定界符对帐户.对于所有其他分隔符,文字包括直到下一个分隔符字符出现的字符.#{ ... }
允许字符串插值.
返回shell命令的结果,就像反引号一样.
文档:http://www.ruby-doc.org/docs/ProgrammingRuby/html/language.html
value = %x( echo 'hi' )
value = %x[ #{cmd} ]
Run Code Online (Sandbox Code Playgroud)Kernel#system
在子shell中执行给定的命令.
返回true
是否找到命令并成功运行,false
否则返回.
文档:http://ruby-doc.org/core/Kernel.html#method-i-system
wasGood = system( "echo 'hi'" )
wasGood = system( cmd )
Run Code Online (Sandbox Code Playgroud)Kernel#exec
通过运行给定的外部命令替换当前进程.
返回none,当前进程被替换并且永远不会继续.
文档: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
Run Code Online (Sandbox Code Playgroud)这里有一些额外的建议:
$?
,$CHILD_STATUS
如果使用反引号,则访问上次系统执行命令的状态,system()
或者%x{}
.然后,您可以访问exitstatus
和pid
属性:
$?.exitstatus
Run Code Online (Sandbox Code Playgroud)
如需更多阅读,请参阅
cyn*_*man 157
我喜欢这样做的方法是使用%x
文字,这使得在命令中使用引号变得容易(并且可读!),如下所示:
directorylist = %x[find . -name '*test.rb' | sort]
Run Code Online (Sandbox Code Playgroud)
在这种情况下,将使用当前目录下的所有测试文件填充文件列表,您可以按预期处理该文件:
directorylist.each do |filename|
filename.chomp!
# work with file
end
Run Code Online (Sandbox Code Playgroud)
Mih*_*i A 62
这是我在Ruby中运行shell脚本的最佳文章:"在Ruby 中运行Shell命令的6种方法 ".
如果你只需要输出使用反引号.
我需要更高级的东西,如STDOUT和STDERR,所以我使用了Open4 gem.你有解释的所有方法.
ans*_*hul 36
我最喜欢的是Open3
require "open3"
Open3.popen3('nroff -man') { |stdin, stdout, stderr| ... }
Run Code Online (Sandbox Code Playgroud)
小智 26
在这些机制之间进行选择时需要考虑的一些事项是:
你可能需要从简单的反引号(``),system()IO.popen
到full-blown Kernel.fork
/ Kernel.exec
with IO.pipe
和IO.select
.
如果子进程执行时间过长,您可能还希望将超时投入到混合中.
不幸的是,这非常取决于.
j-g*_*tus 23
还有一个选择:
当你:
您可以使用shell重定向:
puts %x[cat bogus.txt].inspect
=> ""
puts %x[cat bogus.txt 2>&1].inspect
=> "cat: bogus.txt: No such file or directory\n"
Run Code Online (Sandbox Code Playgroud)
从早期的MS-DOS开始,该2>&1
语法适用于Linux,Mac和Windows.
Ste*_*ard 22
我绝对不是Ruby专家,但我会试一试:
$ irb
system "echo Hi"
Hi
=> true
Run Code Online (Sandbox Code Playgroud)
您还应该能够执行以下操作:
cmd = 'ls'
system(cmd)
Run Code Online (Sandbox Code Playgroud)
小智 18
上面的答案已经非常好了,但我真的想分享以下摘要文章:" 在Ruby中运行Shell命令的6种方法 "
基本上,它告诉我们:
Kernel#exec
:
exec 'echo "hello $HOSTNAME"'
Run Code Online (Sandbox Code Playgroud)
system
并且$?
:
system 'false'
puts $?
Run Code Online (Sandbox Code Playgroud)
反引号(`):
today = `date`
Run Code Online (Sandbox Code Playgroud)
IO#popen
:
IO.popen("date") { |f| puts f.gets }
Run Code Online (Sandbox Code Playgroud)
Open3#popen3
- stdlib:
require "open3"
stdin, stdout, stderr = Open3.popen3('dc')
Run Code Online (Sandbox Code Playgroud)
Open4#popen4
- 宝石:
require "open4"
pid, stdin, stdout, stderr = Open4::popen4 "false" # => [26327, #<IO:0x6dff24>, #<IO:0x6dfee8>, #<IO:0x6dfe84>]
Run Code Online (Sandbox Code Playgroud)
dra*_*788 13
如果你真的需要Bash,请按照"最佳"答案中的说明.
首先,请注意当Ruby调用shell时,它通常调用
/bin/sh
,而不是 Bash./bin/sh
所有系统都不支持某些Bash语法.
如果您需要使用Bash,请插入bash -c "your Bash-only command"
所需的调用方法.
quick_output = system("ls -la")
quick_bash = system("bash -c 'ls -la'")
去测试:
system("echo $SHELL")
system('bash -c "echo $SHELL"')
或者,如果您正在运行现有的脚本文件(例如script_output = system("./my_script.sh")
)Ruby 应该尊重shebang,但您可以始终使用system("bash ./my_script.sh")
以确保(尽管/bin/sh
运行时可能会有轻微的开销/bin/bash
,您可能不会注意到.
您也可以使用反引号运算符(`),类似于Perl:
directoryListing = `ls /`
puts directoryListing # prints the contents of the root directory
Run Code Online (Sandbox Code Playgroud)
如果你需要简单的东西,很方便.
您想要使用哪种方法取决于您要完成的工作; 查看文档以获取有关不同方法的更多详细信息.
我们可以通过多种方式实现它.
使用Kernel#exec
此命令后执行任何操作:
exec('ls ~')
Run Code Online (Sandbox Code Playgroud)
运用 backticks or %x
`ls ~`
=> "Applications\nDesktop\nDocuments"
%x(ls ~)
=> "Applications\nDesktop\nDocuments"
Run Code Online (Sandbox Code Playgroud)
使用Kernel#system
命令,true
如果成功false
则返回,如果不成功则返回,nil
如果命令执行失败则返回:
system('ls ~')
=> true
Run Code Online (Sandbox Code Playgroud)
使用这里的答案并在Mihai的答案中链接,我整理了一个满足这些要求的功能:
作为奖励,如果shell命令成功退出(0)并将任何内容放在STDOUT上,这个也将返回STDOUT.以这种方式,它不同于在这种情况下system
简单地返回true
.
代码如下.具体功能是system_quietly
:
require 'open3'
class ShellError < StandardError; end
#actual function:
def system_quietly(*cmd)
exit_status=nil
err=nil
out=nil
Open3.popen3(*cmd) do |stdin, stdout, stderr, wait_thread|
err = stderr.gets(nil)
out = stdout.gets(nil)
[stdin, stdout, stderr].each{|stream| stream.send('close')}
exit_status = wait_thread.value
end
if exit_status.to_i > 0
err = err.chomp if err
raise ShellError, err
elsif out
return out.chomp
else
return true
end
end
#calling it:
begin
puts system_quietly('which', 'ruby')
rescue ShellError
abort "Looks like you don't have the `ruby` command. Odd."
end
#output: => "/Users/me/.rvm/rubies/ruby-1.9.2-p136/bin/ruby"
Run Code Online (Sandbox Code Playgroud)
不要忘记spawn
创建后台进程以执行指定命令的命令.你甚至可以使用Process
类和返回的等待它的完成pid
:
pid = spawn("tar xf ruby-2.0.0-p195.tar.bz2")
Process.wait pid
pid = spawn(RbConfig.ruby, "-eputs'Hello, world!'")
Process.wait pid
Run Code Online (Sandbox Code Playgroud)
该文档说:这种方法类似#system
但不等待命令完成.
给出如下命令attrib
:
require 'open3'
a="attrib"
Open3.popen3(a) do |stdin, stdout, stderr|
puts stdout.read
end
Run Code Online (Sandbox Code Playgroud)
我发现虽然这种方法不像
system("thecommand")
Run Code Online (Sandbox Code Playgroud)
或者
`thecommand`
Run Code Online (Sandbox Code Playgroud)
在反引号中,与其他方法相比,这种方法的好处是反引号似乎不允许puts
我运行/存储我想在变量中运行的命令,并且system("thecommand")
似乎不允许我获得输出,而这个方法让我可以做这两件事,它让我独立访问 stdin、stdout 和 stderr。
请参阅“在 ruby 中执行命令”和Ruby 的 Open3 文档。
如果您的案例比普通案例(无法处理``
)更复杂,请在Kernel.spawn()
此处查看。这似乎是普通Ruby提供的用于执行外部命令的最通用/最全面的功能。
例如,您可以使用它来:
官方的红宝石文档有足够好的例子。
env: hash
name => val : set the environment variable
name => nil : unset the environment variable
command...:
commandline : command line string which is passed to the standard shell
cmdname, arg1, ... : command name and one or more arguments (no shell)
[cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell)
options: hash
clearing environment variables:
:unsetenv_others => true : clear environment variables except specified by env
:unsetenv_others => false : dont clear (default)
process group:
:pgroup => true or 0 : make a new process group
:pgroup => pgid : join to specified process group
:pgroup => nil : dont change the process group (default)
create new process group: Windows only
:new_pgroup => true : the new process is the root process of a new process group
:new_pgroup => false : dont create a new process group (default)
resource limit: resourcename is core, cpu, data, etc. See Process.setrlimit.
:rlimit_resourcename => limit
:rlimit_resourcename => [cur_limit, max_limit]
current directory:
:chdir => str
umask:
:umask => int
redirection:
key:
FD : single file descriptor in child process
[FD, FD, ...] : multiple file descriptor in child process
value:
FD : redirect to the file descriptor in parent process
string : redirect to file with open(string, "r" or "w")
[string] : redirect to file with open(string, File::RDONLY)
[string, open_mode] : redirect to file with open(string, open_mode, 0644)
[string, open_mode, perm] : redirect to file with open(string, open_mode, perm)
[:child, FD] : redirect to the redirected file descriptor
:close : close the file descriptor in child process
FD is one of follows
:in : the file descriptor 0 which is the standard input
:out : the file descriptor 1 which is the standard output
:err : the file descriptor 2 which is the standard error
integer : the file descriptor of specified the integer
io : the file descriptor specified as io.fileno
file descriptor inheritance: close non-redirected non-standard fds (3, 4, 5, ...) or not
:close_others => false : inherit fds (default for system and exec)
:close_others => true : dont inherit (default for spawn and IO.popen)
Run Code Online (Sandbox Code Playgroud)
backticks`方法是从ruby调用shell命令的最简单方法。它返回shell命令的结果。
url_request = 'http://google.com'
result_of_shell_command = `curl #{url_request}`
Run Code Online (Sandbox Code Playgroud)