在ruby脚本中运行命令时,使用'system'方法抑制运行命令的输出

kil*_*ari 29 ruby

我不确定这是否有意义,但我在想是否有办法在使用systemruby中的方法运行时抑制为命令显示的输出?我的意思是它应该只向STDOUT输出true或false,而不是输出命令.我认为它只能在命令可以静默运行而不是从system方法运行时才能完成.有人能提供更多的见解吗?

Ste*_*eve 44

如果你想利用可变形式的Kernel.system,它可以解决shell的许多引用问题,你可以使用Kernel.spawn接受的相同选项.

TL; DR - 用于:out => File::NULL使Kernel.system的输出静音

带有特殊字符(空格等)的参数可能会导致shell出现问题:

irb(main):001:0> filename_with_spaces = "foo bar.txt"
=> "foo bar.txt"

irb(main):002:0> system "ls -l #{filename_with_spaces}"
ls: bar.txt: No such file or directory
ls: foo: No such file or directory
=> false
Run Code Online (Sandbox Code Playgroud)

因此,如果要将变量插入到系统调用中,则单独提供参数会更安全:

irb(main):003:0> system "ls", "-l", filename_with_spaces
-rw-r--r--  1 nobody  nobody  9 Feb  1 16:53 foo bar.txt
=> true
Run Code Online (Sandbox Code Playgroud)

但是如果我们想隐藏输出,现在我们遇到了问题.

irb(main):004:0> system "ls", "-l", filename_with_spaces, "> /dev/null"
ls: > /dev/null: No such file or directory
-rw-r--r--  1 nobody  nobody  9 Feb  1 16:53 foo bar.txt
=> false
Run Code Online (Sandbox Code Playgroud)

我们可以使用以下:out => :close选项关闭STDOUT :

irb(main):005:0> system "ls", "-l", filename_with_spaces, :out => :close
=> true
Run Code Online (Sandbox Code Playgroud)

但是,这可能会导致某些命令出现问题,这些命令可能会尝试连接到STDOUT.

irb(main):006:0> system "echo", "hi there", :out => :close
echo: write: Bad file descriptor
=> false
Run Code Online (Sandbox Code Playgroud)

要解决这个问题,我们可以返回重定向输出,使用File::NULL以保持可移植性:

irb(main):007:0> system "echo", "hi there", :out => File::NULL
=> true
Run Code Online (Sandbox Code Playgroud)

  • 这绝对是正确的答案. (7认同)
  • 从这个答案我能够推断出`:err =>`.是否有东西意味着`out:`和`:err`,所以我不必写`:out => File :: NULL,:err => File :: NULL`? (3认同)
  • 如果你看一下[Kernel#spawn](http://ruby-doc.org/core-2.3.0/Kernel.html#method-i-spawn)的文档,你会发现你可以做到这一点. :out,:err] => File :: NULL`,还有很多其他的东西. (2认同)

mik*_*kej 23

system在对特殊变量的退出代码调用之后$?,如果useradd返回不同的值以指示用户是否已成功添加(例如0表示成功),则可以执行以下操作:

system('useradd xx > /dev/null')
if $? == 0
  puts 'added'
else
  puts 'failed'
end
Run Code Online (Sandbox Code Playgroud)

重定向到哪里/dev/null会抑制输出.

或者,如果被调用的程序不使用其退出代码来指示成功或失败,则可以使用反引号并在输出中搜索特定子字符串,例如

if `useradd xx`.include? 'success'
  puts 'it worked'
else
  puts 'failed to add user'
end
Run Code Online (Sandbox Code Playgroud)

  • 仅此一点不会压制`stderr`.应该使用这个`system('useradd xx>/dev/null 2>&1')` (8认同)
  • 这些都不适用于Windows,因为`/ dev/null`不存在,即使在Git-Bash下也是如此.更好的答案是使用`out:File :: NULL,err:File :: NULL`.这是适当的便携式并清楚地表明意图,而不必担心你是否处理了`&2> 1`与`&>`vs. (4认同)

Chr*_*ane 8

作为附录,当我使用反引号并且从命令行运行脚本时看到输出"滑过"我的变量时,我几次感到惊讶.

问题总是存在,我所看到的文本实际上来自stderr而不是stdout.因此,要将该文本纠缠到stdout中,请记住附加2>&1到您尝试运行的命令.

我希望这对某人有帮助.我只是浪费了二十分钟重新学习这一课:)