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?
Ruby command is a free and open source programming language; it is flexible and is feature rich. As the name suggests, ruby indeed is a jewel language which comes at a very low entry cost. Its plug and play capability and also easily readable syntax makes it very user-friendly.
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
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
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 :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With