2
value = %x( #{"svn lock #{@path}/#{@file}"} )

=>

svn: warning: W160035: Path '/README.txt' is already locked by user 'tester' in filesystem 'some_path'
""

Returns empty string rather then the svn:warning message. I want to record the svn warning message. What am I doing wrong.

Thanks for your help in advance.

Ross
  • 109
  • 2
  • 10
  • 1
    See http://stackoverflow.com/questions/690151/getting-output-of-system-calls-in-ruby/20001569#20001569 - You need to use http://www.ruby-doc.org/stdlib-2.0.0/libdoc/open3/rdoc/Open3.html#method-c-capture2e – Denis de Bernardy Feb 17 '14 at 14:41

2 Answers2

5

This is likely because the output is being sent to STDERR, not STDOUT (which is all %x captures). Because you’re not capturing it, it does what it would normally and prints to the console.

You can either redirect STDERR to STDOUT in your command:

%x(svn lock #{@path}/#{@file} 2>&1)

Or use Open3 to capture both STDOUT & STDERR:

require 'open3'

Open3.popen3("svn lock #{@path}/#{@file}") do |stdin, stdout, stderr, wait_thr|
  puts "stdout is:" + stdout.read
  puts "stderr is:" + stderr.read
end

The first option offloads the work to the shell executing the command and depending on the environment it may not support it. As such using Open3 is a much more portable solution.

Some additional notes: note I’ve removed the unnecessary interpolation in your %x statement. Also, consider using ShellWords to properly escape interpolated string in shell commands. This is particularly important if these are user-inputted strings.

Andrew Marshall
  • 95,083
  • 20
  • 220
  • 214
  • That's interesting - `%x(svn lock #{@path}/#{@file} 2>&1)`. What does `2>&1` mean ? – Arup Rakshit Feb 17 '14 at 14:48
  • 1
    @ArupRakshit It redirects STDERR (which is file descriptor #2) to STDOUT (which is file descriptor #1). – Andrew Marshall Feb 17 '14 at 14:51
  • @AndrewMarshall What is that `&` there ? – Arup Rakshit Feb 17 '14 at 14:52
  • 1
    @ArupRakshit The `&` specifies that you’re giving a file descriptor (`1`) as the location to redirect output to. If you didn’t give it then it would send the output to a file named `1`. – Andrew Marshall Feb 17 '14 at 14:54
  • @ArupRakshit No problem. Also note, of course, that that style of output redirection is not done by Ruby but rather by the shell running the command; whereas with Open3 Ruby coordinates the redirection (and is thus more portable). – Andrew Marshall Feb 17 '14 at 14:58
  • @AndrewMarshall Just a minor note: the `2>&1` trick won't work on csh compatible shells. – toro2k Feb 17 '14 at 15:02
  • 1
    @toro2k Right. I suppose I should move the note about portability from my comment to the answer… I have been bitten by that before when running a different platform. – Andrew Marshall Feb 17 '14 at 15:05
  • @AndrewMarshall Yes... That was my 3rd question, but before me you answered.. Again thanks for this.. :-) – Arup Rakshit Feb 17 '14 at 15:12
2

Your problem is that backticks (or %x) returns the output of STDOUT, whereas in this case you want STDERR. Use e.g. Open3::capture2e instead:

http://www.ruby-doc.org/stdlib-2.0.0/libdoc/open3/rdoc/Open3.html#method-c-capture2e

Denis de Bernardy
  • 75,850
  • 13
  • 131
  • 154