Right now, I have the following code to capture a character in ruby using the IO.read,
tty_param = `stty -g`
system 'stty raw -echo'
capt = IO.read '/dev/stdin', 1
system "stty #{tty_param}"
The code is called through a key-binding, so I'll be in the middle of an application like vim or just the bash prompt, when this is called.
What I'm wondering is, how do I send the characters back to my process once I've finished running my program?
Open3 can be what you are looking for.
Open3 grants you access to stdin, stdout, stderr and a thread to wait
for the child process when running another program. You can specify
various attributes, redirections, current directory, etc., of the
program in the same way as for Process.spawn.
Related
I am designing a ruby program that needs to run a command and store it a variable.
var = exec('some command');
This doesn't work the way I want it to, it just prints the output from the command prompt and then ends the program.
So is there a function that doesn't end the program, doesn't print the cmd output and stores the information in a variable?
Thanks in advance.
You need to use either Ruby's built in backtick syntax, or use %x
output = `some command`
or
output = %x(some "command")
Open3 grants you access to stdin, stdout, stderr and a thread to wait
the child process when running another program. You can specify
various attributes, redirections, current directory, etc., of the
program as Process.spawn.
See the various ways of executing a command
I need to start a subprocess from ruby, that takes over then returns control.
This subprocess needs interactive input from the user, so it's io should be tied to stdin stdout and stderr. Further it requests for input changes depending on the circumstances.
An example of a program like that is TeX, which I would start on a file but during the process TeX may encounter a user error which it has to query the user how to fix.
Essentially I am looking for a reentrant version of exec.
PS
For those who cannot read carefully let me reiterate.
This subprocess needs interactive input from the user
That means that if the ruby program runs in a tty, that its output goes to the tty not the Ruby program and its input comes from the tty, not the Ruby program.
In other words:
Essentially I am looking for a reentrant version of exec.
I use TeX as an example so let me show you an example. I found a sample piece of TeX on the at Sample Tex . I intend to put an error in but it seems I don't have to it chokes on my system. Save it in sample1.tex, sample2.tex, sample3.tex.
Now I would like to run this bit of ruby code:
files=["sample1.tex","sample2.tex","sample3.tex"]
files.each{|file|
# It is really a latex command.
commmand_that_I_am_looking_for("latex #{file}")
}
When I run this code I should see in the terminal, three times a bunch of stuff:
Generic information about the latex program, progress in processing etc.
! LaTeX Error: File `html.sty' not found.
Type X to quit or <RETURN> to proceed,
or enter new name. (Default extension: sty)
Enter file name:
Where upon each of the three times the program waits for the user to type something.
You can pair fork with exec:
Process.fork { exec('./somescript') }
Process.wait
The Process.wait ensures that you wait for the subprocess to complete.
Ruby standard library has a special command for your needs. It is called open3. Here is an example from its docs:
Open3.popen3("pwd", :chdir=>"/") {|stdin, stdout, stderr, thread|
p stdout.read.chomp #=> "/"
}
I am currently displaying the output of a subprocess onthe python shell (in my case iDLE on windows) by using a pipe and displaying each line.
I want to do this with a subprocess that has user input, so that the prompt will appear on the python console, and the user can enter the result, and the result can be send to the subprocess.
Is there a way to do this?
Use process.stdin.write.
Remember to set stdin = subprocess.PIPE when you call subprocess.Popen.
I want to understand that how does shell executes piped commands ? e.g. cat | more. I am aware that for executing a normal command shell does a fork, execute it and then child returns. But how does shell internally handle the execution of piped commands ?
Considering for example cat | grep, the shell first forks itself to start cat, and then forks itself once more to start grep.
Before calling one of the exec* family of functions in the two newly created processes to start the two programs, the tricky part is setting up the pipe and redirecting the descriptors. The pipe(2) system call is used in the shell process before forking to return a pair of descriptors which both children inherit - a reading end and a writing end.
The reading end will be closed in the first process (cat), and stdout will be redirected to the writing end using the dup2(2) system call. Similarly, the writing end in the second process (grep) will be closed and stdin will be redirected to the reading end again using dup2(2).
This way both programs are unaware of a pipe because they just work with the standard input/output.
It sets up a pipe using the pipe system call, forks two processes instead of one and attaches one end of the pipe to the first process' stdout and the other end to the second process' stdin.
The same, just the stdout of one application is the same as the next stdin. http://unixwiz.net/techtips/remap-pipe-fds.html
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.