I am not sure if this makes sense but I am thinking if there is a way to suppress the output shown for a command when run using the system
method in ruby? I mean it should just output true or false to STDOUT and not the output of the command. What I think is it can just only be done if the command can run silently and not from the system
method. Can someone provide a bit more insight?
8 Answers
If you want to take advantage of the variadic form of Kernel.system, which side-steps the many quoting issues with shells, you can use the same options which Kernel.spawn accepts.
TL;DR - Use :out => File::NULL
to silence output from Kernel.system
Arguments with special characters (spaces, etc.) can cause problems with the 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
So if you are interpolating variables into a system call, it is safer to provide the arguments separately:
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
But now we have a problem if we want to hide the output.
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
We could close STDOUT using the :out => :close
option:
irb(main):005:0> system "ls", "-l", filename_with_spaces, :out => :close
=> true
However, this might cause issues with certain commands which may try to attach to STDOUT.
irb(main):006:0> system "echo", "hi there", :out => :close
echo: write: Bad file descriptor
=> false
To fix this, we can go back to redirecting our output, using File::NULL
to remain portable:
irb(main):007:0> system "echo", "hi there", :out => File::NULL
=> true

- 6,618
- 3
- 44
- 42
-
6From this answer I was able to deduce `:err =>` as well. Is there something that means both `out:` and `:err`, so I don’t have to write `:out => File::NULL, :err => File::NULL`? – user137369 Dec 07 '16 at 19:30
-
3If you look at documentation for [Kernel#spawn](http://ruby-doc.org/core-2.3.0/Kernel.html#method-i-spawn), you'll find that you can do this `[:out, :err] => File::NULL`, as well as many other things. – Steve Dec 08 '16 at 00:32
-
@Steve Goddamn that's elegant AF. – Joshua Pinter Dec 29 '20 at 23:24
After a call to system
the exit code is in the special variable $?
so if useradd
returns different values to indicate if the user was successfully added (e.g. 0 for success) then you can do the following:
system('useradd xx > /dev/null')
if $? == 0
puts 'added'
else
puts 'failed'
end
where the redirect to /dev/null
will suppress the output.
Alternatively if the program being called does not use its exit code to indicate success or failure you can use backticks and search for a particular substring in the output e.g.
if `useradd xx`.include? 'success'
puts 'it worked'
else
puts 'failed to add user'
end

- 65,295
- 17
- 152
- 131
-
10This alone won't suppress `stderr`. Should use this `system('useradd xx > /dev/null 2>&1')` – Dex Jan 09 '14 at 05:00
-
1`system` also returns `true` or `false` and I especially like to depend on those simple values. The return values are not affected by the `> /dev/null 2>&1` redirection. – Ikon Jun 23 '15 at 09:26
-
6None of these will work on Windows because `/dev/null` doesn't exist, even under Git-Bash. The better answer is to use `out: File::NULL, err: File::NULL`. That's properly portable and clearly indicates intent without having to worry about if you handled `&2>1` vs. `&>` vs whatever. – Rob Kinyon Sep 21 '16 at 15:02
As an addendum, I've been surprised a few times when I've used backticks and saw output "slipping past" my variables when running scripts from the command line.
Invariably, the issue is that the text I'm seeing is actually coming from stderr
rather than stdout
. So, to wrangle that text into stdout as well, remember to append 2>&1
to the command you're trying to run.
I hope that's helpful to someone. I just wasted twenty minutes re-learning this lesson :)

- 6,334
- 5
- 25
- 31
I was faced with this question as well...
Keep in mind that with ruby system
calls, the UNIX command you are trying to use might offer a "silent" option--nullifying the need to suppress terminal output altogether!
For instance:
system 'curl -s "your_params_here"'
Will suppress the output that typically accompanies a curl call.

- 119
- 4
IO.popen
This is another good option:
IO.popen(['echo', 'a']) do |f|
f.read == "a\n" or raise
end
$?.exitstatus == 0 or raise
Nothing will get output to your stdout.

- 347,512
- 102
- 1,199
- 985
-
TODO does `IO.popen('cmd').close` work as well? http://stackoverflow.com/questions/1217351/io-popen-how-to-wait-for-process-to-finish#comment42139826_1236075 – Ciro Santilli OurBigBook.com Nov 06 '14 at 13:57
- define
null_device
, it's operating systems dependent: windows 7 and newer usenul
, while *nix systems uses/dev/null
- run the command
- redirect it's standard and error output to
null_device
- then use the exit code, or the backtick method as mentioned by @mikej to determine the output
as follows:
null_device = Gem.win_platform? ? "/nul" : "/dev/null"
do method
system "run command 1>#{null_device} 2>#{null_device} "
p ($? == 0)
end

- 1
- 1

- 1,691
- 19
- 23
You can also use backticks or %x

- 5,855
- 1
- 26
- 22
-
yes but I will not be able to use it as a condition to execute a few statements which I can do when using 'system' – kilari Dec 25 '09 at 09:45
-
2That makes very little sense so maybe you should post an actual example. – Azeem.Butt Dec 25 '09 at 10:01
-
So write a different conditional that actually parses the output and might be a better idea than what you have now. – Azeem.Butt Dec 25 '09 at 15:55
This should work
system ls, STDOUT:'/dev/null'

- 25,519
- 37
- 106
- 129

- 37,208
- 23
- 149
- 195