Ruby run external program stops script - ruby

I have a ruby script that midway through I need it to run another program.
After running the program the rest of the script doesnt get run. For example:
# some ruby that gets run
exe = "Something.exe"
system(exe)
# some ruby that doesnt run
I have also tried using Open3.popen2e(cmd) and Open3.popen3(cmd) but its the same.
Can anyone help me understand what is happening here and how to fix it?
note: I'm using windows

Try to run Something.exe in a new Thread:
Thread.new { system("Something.exe") }

In case you want to run your System.exe asynchronously and continue without waiting it to be finished, you could use spawn or multithreading.
pid = spawn('System.exe')
Process.detach(pid)
According to this previous answer, this should work on Windows as well (while fork or other methods don't).
In this article you can find several examples using system, exec, fork, spawn and Thread on Unix.
I cannot reproduce it, but it could be worth to see if using system("start System.exe") works on windows like system("cmd &") works on UNIX. You can refer to start documentation here.

Related

Launch subprocess in Ruby and continue execution of script

I want to launch a subprocess in Ruby, concretely an external .exe file (I'm working in Windows environment). I don't want to block the Ruby script, so I want to return to the next line of the script while the subprocess is running. The Ruby script can even finish before the subprocess is done.
Is there any way to do it? I've tried exec(), fork(), spawn(), system()... but cannot make it work properly.
You could use Thread:
Thread.new { <your logic here> }
There are a bunch of helper methods defined on Thread which will allow you to monitor and manipulate the thread.

Process.spawn (Ruby 1.9.x): How to check if spawning was successful and detect errors?

Using a cross-platform solution (GNU/Linux, Windows), I want to spawn an external program in the background, capture it's pid and later on stop the program via the stored pid.
Consider this code in Ruby 1.9.x:
pid = Process.spawn("xxx")
puts pid
stdout/stderr:
8117
sh: 1: xxx: not found
No exception is thrown, and I don't see any way to detect the fact that the spawn was not successful (xxx is not a valid command).
What is the best way to detect that this spawn was not successful?
Process#spawn returns a process ID. If you get a process ID back, then technically the function itself did not fail. In Ruby >= 2.0.0, Process#spawn will throw Errno::ENOENT if it fails to find the command. As ruby 1.9 is unsupported, the best solution is to upgrade ruby.
A hack which may help would be to test if the process is actually running after the call returns. Sadly, this will be platform specific.
pid = Process.spawn("xxx")
case RUBY_PLATFORM
when /linux/i
success = File.exist?("/proc/#{pid}")
when /windows/i
# use win32api gem, Windows API call EnumProcesses
else
# ?
end
Unfortunately, if the process finishes by the time you test for its existence, you can't tell. You probably want to check for its results (whatever it does) to see if it did it also.
Another approach, if you control the program being launched, is to open a named pipe before launching it and have it send your ruby program a message over the pipe that it is running. You can then read from the pipe after the spawn call in a non-blocking way and use Timeout to prevent it from blocking forever. A simpler, less clean approach would be to have that program write something deterministic to a file that you can use a simple File.exist? test on to see if its there.

run a subprocess from ruby without waiting for it to return [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Spawn a background process in Ruby
Spent a couple days poking at this. I was using ruby 1.8.7 from the OS until recently. I would call a subshell with backticks. The subshell was a bash wrapper that would call run any program in the background with stdout and stderr both closed. It then ran disown to let init take over the process and it would return immediately. This worked great for years, where I would have this looping process kick off jobs in the background and immediately report back "yes, it ran, that's all I am telling you".
I upgraded everything to rvm 1.9.3 and everything's fine except for this trick. I'm starting to suspect it's more of a hack than I want to admit. In 1.9.3, I always get an EPIPE error when I spawn that subshell. It says that it has a broken pipe. I can accept that it isn't going to work in 1.9.3 since it seems kinda gross what I was doing in 1.8.7.
I've tried using the system command and I have tried open3:popen2. They also both throw an EPIPE with me calling the disown wrapper.
#!/bin/bash
# this will crash ruby if you keep trying to read from it.
$* >&- &
disown %1
This is the disown wrapper. In ruby I have something like
r=`/usr/local/bin/disown /usr/local/bin/job.sh`
And when this runs, it throws
/usr/local/bin/runner.rb:88:in ``': Broken pipe (Errno::EPIPE)
If I don't assign the (zero) output to the r variable, the effect is identical. And with the system function and Open3:popen2.
So my goal is to simply run a command from ruby and not wait for it to come back. It takes several hours and I do not need to track it, just spawn it. I might try a worker thread pool if it begins to sound like ruby can no longer do this, or if my disown wrapper is too heinous to get any approval. Ok. Thanks.
*edit: Thanks for the great answers everyone. I think Casper showed me that if I had a better handle on the ruby lingo, I probably would have zeroed in on this. Sorry if this a little pedestrian. I appreciate the quick answers, everyone!
Well, you answered yourself: Process.spawn:
Process.spawn("something");
in Ruby 1.9.3, u can use
Process.fork do
# do your long time job
end
Check out the daemons gem. Then you can do:
require 'daemons'
Daemons.run('some_script.rb')

Piping stdin to ruby script via `myapp | myscript.rb`

I have an app that runs continuously, dumping output from a server and sending strings to stdout. I want to process this output with a Ruby script. The strings are \n-terminated.
For example, I'm trying to run this on the command line:
myapp.exe | my_script.rb
...with my_script.rb defined as:
while $stdin.gets
puts $_
end
I ultimately am going to process the strings using regexes and display some summary data, but for now I'm just trying to get the basic functionality hooked up. When I run the above, I get the following error:
my_script.rb:1:in `gets': Bad file descriptor (Errno::EBADF)
from my_script.rb:1
I am running this on Windows Server 2003 R2 SP2 and Ruby 1.8.6.
How do I continuously process stdin in a Ruby script? (Continuously as in not processing a file, but running until I kill it.)
EDIT:
I was able to make this work, sort of. There were several problems standing in my way. For one thing, it may be that using Ruby to process the piped-in stdin from another process doesn't work on Windows 2003R2. Another direction, suggested by Adrian below, was to run my script as the parent process and use popen to connect to myapp.exe as a forked child process. Unfortunately, fork isn't implemented in Windows, so this didn't work either.
Finally I was able to download POpen4, a RubyGem that does implement popen on Windows. Using this in combination with Adrian's suggestion, I was able to write this script which does what I really want -- processes the output from myapp.exe:
file: my_script.rb
require 'rubygems'
require 'popen4'
status =
POpen4::popen4("myapp.exe") do |stdout, stderr, stdin, pid|
puts pid
while s = stdout.gets
puts s
end
end
This script echoes the output from myapp.exe, which is exactly what I want.
Try just plain gets, without the $stdin. If that doesn't work, you might have to examine the output of myapp.exe for non-printable characters with another ruby script, using IO.popen.
gets doesn't always use stdin but instead tries to open a file.
See SO.
Try executing your Ruby script by explicitly calling ruby:
myapp.exe | ruby my_script.rb
I've experienced some odd behavior using stdin in Ruby when relying on Windows to invoke the correct program based on the file associations.

Process.daemon vs. running a Ruby script with nohup + &

I have a Ruby 1.9 script that I want to run as a long-running background process.
It looks like I have a choice between calling Process.daemon inside the script to daemonize it, or I can just run the script in the background using a shell's ampersand and keep it running after I log out of the server by prefixing the command with nohup.
Which way is better?
Process.daemon seems like a more clean and straightforward way, especially if this is something you would ever way to turn into a full-fledged daemon that is started during boot.

Resources