echo "yes\yes\oops" | program doesn't work well for a long-running program.
I can think of redirect the output of program to a file, then use a loop to grep that file until certain output appears. But is there any better idea?
If you prefer/are stuck with bash, perhaps you are looking for expect?
More on that here: http://wiki.tcl.tk/11583
Write a Python, Perl, Ruby or script in another language to interact with the program. In Python you'd use subprocess. In Perl you'd use popen(). Read the program's stdout line-by-line and match against known prompts, replying with the desired response by writing to the program's stdin.
You can do the same in bash, but I personally prefer not to.
Related
Usually I capture the output via a subshell:
result="$(command 2>&1)"
If the command is source, the subshell swallows some (all?) changes to the scripts shell's environment.
How can I capture the output of source into a variable?
Surprisingly tricky question!
My first thought was to use a named pipe (mkfifo(1)), but those have a finite buffer size, so if the sourced script fills up the buffer the script would hang. And you can't use a background process to drain the buffer because you want the output in a variable in the original process eventually.
I'm sure there's a way to make it work entirely in memory, but in the end I think a simple and stupid redirect to a temporary file is the most straightforward and robust solution:
OUTPUT_FILE=$(mktemp)
source other_script.sh >$OUTPUT_FILE 2>&1
OUTPUT="$(< "$OUTPUT_FILE")"
rm -f "$OUTPUT_FILE"
(See this question and in particular BashFAQ 062 for security implications of mktemp though.)
What I would like to do is:
run a ruby script...
that executes a shell command
and redirects it to a named pipe accessible outside the script
from the system shell, read from that pipe
That is, have the Ruby script capture some command output and redirect it in such a way that it's connectable to from outside the script?
I want to mention that the script cannot simply start and exit, since it's a REPL. The idea is that using the REPL you would be able to run a command and redirect its output elsewhere to consume it.
Using abort and an exit message, will pass the message to STDERR (and the script will fail with exit code 1). You can pass this shell command output in this way.
This is possibly not the only (or best) way, but it has worked for me in the past.
[edit]
You can also redirect the output to a file (using standard methods), and read that file outside the ruby script.
require 'open3'
stdin, stderr, status = Open3.capture3(commandline)
stdin.chomp #Here, you should ge
Incase, if someone wanted to use you can get the output via stdin.chomp
I'm using a Windows x64 machine and am trying to capture the STDOUT and STDERR streams from a command. I also have to write to the command's STDIN. I'm trying to use perl's IPC::Open3 for this, with no luck. I'm using the script posted here and the command as this script here. I of course replaced the $cmd variable with "perl test.pl" for Windows.
It's supposed to print 'StdOut!' and 'StdErr!', along with the pid, but I only get the PID. I don't know if it is because of my operating system, or because the thread is 10 years old (no biggie, Perl 5 is almost 18, right?). Another monk posted this script to fix any problems in the other one, but on my computer it never exits.
Can anyone give me a working example of using open3 to start a command in perl, write to its STDIN, and capture both its STDERR and its STDOUT?
select only works for sockets in Windows; it doesn't work on pipes. You could create sockets instead and pass those to open3 instead of letting it create pipes for you (as seen here), but I suggest that you use a higher-level module such as IPC::Run instead. open3 is a rather low-level function.
I'm using a bash script to automatically run a simulation program. This program periodically prints the current status of the simulation in the console, like "Iteration step 42 ended normally".
Is it possible to abort the script, if the console output is something like "warning: parameter xyz outside range of validity"?
And what can I do, if the console output is piped to a text file?
Sorry if this sounds stupid, I'm new to this :-)
Thanks in advance
This isn't an ideal job for Bash. However, you can certainly capture and test STDOUT inside a Bash iteration loop using an admixture of conditionals, grep-like tools, and command substitution.
On the other hand, if Bash isn't doing the looping (e.g. it's just waiting for an external command to finish) then you need to use something like expect. Expect is purpose-built to monitor output streams for regular expressions, and perform branching based on expression matches.
Can command_b knows that command_c is following?
command_a | command_b | command_c
As the other answerers said, no, command_b cannot (need not, should not) know that command_c follows. I'm adding another answer because here is a little additional information:
The shell interpreter (Bash, in this case) does, and must know (because it implements the pipe).
A program can tell if its standard output is to a terminal. This can be used to change behavior on the fly (for instance, command_b might omit ASCII color codes, while command_c might colorize its output).
See also:
the isatty(3) manpage
How to detect if my shell script is running through a pipe?
Test whether the actual output is a terminal or not in node.js
No. Each program is just reading standard input and writing to standard output.
No, it cannot, need not and should not.