Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.java.programmer > #31814 > unrolled thread
| Started by | FredK <fred.l.kleinschmidt@gmail.com> |
|---|---|
| First post | 2015-06-17 13:56 -0700 |
| Last post | 2015-07-03 23:41 -0400 |
| Articles | 18 — 4 participants |
Back to article view | Back to comp.lang.java.programmer
Getting results of command execution FredK <fred.l.kleinschmidt@gmail.com> - 2015-06-17 13:56 -0700
Re: Getting results of command execution Eric Sosman <esosman@comcast-dot-net.invalid> - 2015-06-17 17:14 -0400
Re: Getting results of command execution FredK <fred.l.kleinschmidt@gmail.com> - 2015-06-17 14:57 -0700
Re: Getting results of command execution Martin Gregorie <martin@address-in-sig.invalid> - 2015-06-17 23:07 +0000
Re: Getting results of command execution Jeff Higgins <jeff@invalid.invalid> - 2015-06-17 21:26 -0400
Re: Getting results of command execution FredK <fred.l.kleinschmidt@gmail.com> - 2015-06-18 07:18 -0700
Re: Getting results of command execution FredK <fred.l.kleinschmidt@gmail.com> - 2015-06-18 07:30 -0700
Re: Getting results of command execution Jeff Higgins <jeff@invalid.invalid> - 2015-06-18 17:37 -0400
Re: Getting results of command execution FredK <fred.l.kleinschmidt@gmail.com> - 2015-06-19 07:50 -0700
Re: Getting results of command execution Jeff Higgins <jeff@invalid.invalid> - 2015-06-19 21:33 -0400
Re: Getting results of command execution Jeff Higgins <jeff@invalid.invalid> - 2015-06-19 21:56 -0400
Re: Getting results of command execution Jeff Higgins <jeff@invalid.invalid> - 2015-06-19 23:02 -0400
Re: Getting results of command execution Jeff Higgins <jeff@invalid.invalid> - 2015-06-20 11:11 -0400
Re: Getting results of command execution Jeff Higgins <jeff@invalid.invalid> - 2015-06-20 12:14 -0400
Re: Getting results of command execution Jeff Higgins <jeff@invalid.invalid> - 2015-06-20 20:58 -0400
Re: Getting results of command execution Eric Sosman <esosman@comcast-dot-net.invalid> - 2015-06-19 11:01 -0400
Re: Getting results of command execution Eric Sosman <esosman@comcast-dot-net.invalid> - 2015-06-18 08:38 -0400
Re: Getting results of command execution Jeff Higgins <jeff@invalid.invalid> - 2015-07-03 23:41 -0400
| From | FredK <fred.l.kleinschmidt@gmail.com> |
|---|---|
| Date | 2015-06-17 13:56 -0700 |
| Subject | Getting results of command execution |
| Message-ID | <c3df45f4-0172-4986-95e4-cbfb6222610f@googlegroups.com> |
I want to execute a set of commands and get the results. So I start with,
on Unix;
process P = Runtime.getRuntime().exec("commandA; commandB");
or on Windows
process P = Runtime.getRuntime().exec("commandA & commandB");
How do I get the results of the output AND error output in the order they are created?
If I use this type of coding:
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new
InputStreamReader(p.getErrorStream()));
// read the output from the command
System.out.println("Here is the standard output of the command:\n");
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
// read any errors from the attempted command
System.out.println(
"Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
I get all of the stdout, followed by all of the stderr. But suppose commandA writes some output, then some errors, then more outputs, etc. I want to retrieve them in that order. I guess I could use:
"commandA >myfileA 2>&1 ; commandB >myfileB 2>&1 ; cat myfileA myfileB"
but that seems excessive (and I also need to delete the files, plus I might not even have permission to create files in the current directory)
--
Fred K
[toc] | [next] | [standalone]
| From | Eric Sosman <esosman@comcast-dot-net.invalid> |
|---|---|
| Date | 2015-06-17 17:14 -0400 |
| Message-ID | <mlsnte$efd$1@dont-email.me> |
| In reply to | #31814 |
On 6/17/2015 4:56 PM, FredK wrote:
> I want to execute a set of commands and get the results. So I start with,
> on Unix;
> process P = Runtime.getRuntime().exec("commandA; commandB");
>
> or on Windows
> process P = Runtime.getRuntime().exec("commandA & commandB");
>
> How do I get the results of the output AND error output in the order they are created?
>
> If I use this type of coding:
> [...]
> I get all of the stdout, followed by all of the stderr. But suppose commandA writes some output, then some errors, then more outputs, etc. I want to retrieve them in that order.
You could try using a ProcessBuilder to set up your Process, and
use its redirectErrorStream() method to merge stdout and stderr before
calling start(). But even then, you'll be at the mercy of whatever
buffering takes place in the external process itself: If that process
holds on to stdout data until it's got a bufferload, but emits stderr
data right away (this is the default behavior for many C programs),
the mingled data will be temporally scrambled no matter what you do
on the receiving side.
--
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM
[toc] | [prev] | [next] | [standalone]
| From | FredK <fred.l.kleinschmidt@gmail.com> |
|---|---|
| Date | 2015-06-17 14:57 -0700 |
| Message-ID | <7a28b01f-2a86-4703-98e7-79a7be418abf@googlegroups.com> |
| In reply to | #31815 |
On Wednesday, June 17, 2015 at 2:14:45 PM UTC-7, Eric Sosman wrote:
> On 6/17/2015 4:56 PM, FredK wrote:
> > I want to execute a set of commands and get the results. So I start with,
> > on Unix;
> > process P = Runtime.getRuntime().exec("commandA; commandB");
> >
> > or on Windows
> > process P = Runtime.getRuntime().exec("commandA & commandB");
> >
> > How do I get the results of the output AND error output in the order they are created?
> >
> > If I use this type of coding:
> > [...]
> > I get all of the stdout, followed by all of the stderr. But suppose commandA writes some output, then some errors, then more outputs, etc. I want to retrieve them in that order.
>
> You could try using a ProcessBuilder to set up your Process, and
> use its redirectErrorStream() method to merge stdout and stderr before
> calling start(). But even then, you'll be at the mercy of whatever
> buffering takes place in the external process itself: If that process
> holds on to stdout data until it's got a bufferload, but emits stderr
> data right away (this is the default behavior for many C programs),
> the mingled data will be temporally scrambled no matter what you do
> on the receiving side.
>
>
I'm not sure I can accomplish what I want; I haven't been able to find anything that will let me execute multiple commands in the same invocation.
I want to pass along user commands to be executed, and there might be a "cd" imbedded in the string, or setting some environment variables, or any of a multitude of things that cause one command to depend on the results of some previous command(s), so it I can't just execute each command in a separate process.
--
Fred K
[toc] | [prev] | [next] | [standalone]
| From | Martin Gregorie <martin@address-in-sig.invalid> |
|---|---|
| Date | 2015-06-17 23:07 +0000 |
| Message-ID | <mlsuja$9rv$1@dont-email.me> |
| In reply to | #31816 |
On Wed, 17 Jun 2015 14:57:04 -0700, FredK wrote: > I'm not sure I can accomplish what I want; I haven't been able to find > anything that will let me execute multiple commands in the same > invocation. > > I want to pass along user commands to be executed, and there might be a > "cd" imbedded in the string, or setting some environment variables, or > any of a multitude of things that cause one command to depend on the > results of some previous command(s), so it I can't just execute each > command in a separate process. > You can run a shell script containing the commands (Unix/Linux terminology) and I'm certain Windows and and OSX have a similar capability. -- martin@ | Martin Gregorie gregorie. | Essex, UK org |
[toc] | [prev] | [next] | [standalone]
| From | Jeff Higgins <jeff@invalid.invalid> |
|---|---|
| Date | 2015-06-17 21:26 -0400 |
| Message-ID | <mlt6pr$3cc$1@dont-email.me> |
| In reply to | #31816 |
On 06/17/2015 05:57 PM, FredK wrote:
> On Wednesday, June 17, 2015 at 2:14:45 PM UTC-7, Eric Sosman wrote:
>> On 6/17/2015 4:56 PM, FredK wrote:
>>> I want to execute a set of commands and get the results. So I start with,
>>> on Unix;
>>> process P = Runtime.getRuntime().exec("commandA; commandB");
>>>
>>> or on Windows
>>> process P = Runtime.getRuntime().exec("commandA & commandB");
>>>
>>> How do I get the results of the output AND error output in the order they are created?
>>>
>>> If I use this type of coding:
>>> [...]
>>> I get all of the stdout, followed by all of the stderr. But suppose commandA writes some output, then some errors, then more outputs, etc. I want to retrieve them in that order.
>>
>> You could try using a ProcessBuilder to set up your Process, and
>> use its redirectErrorStream() method to merge stdout and stderr before
>> calling start(). But even then, you'll be at the mercy of whatever
>> buffering takes place in the external process itself: If that process
>> holds on to stdout data until it's got a bufferload, but emits stderr
>> data right away (this is the default behavior for many C programs),
>> the mingled data will be temporally scrambled no matter what you do
>> on the receiving side.
>>
>>
> I'm not sure I can accomplish what I want;
I'm sure that you're clear on what you want to accomplish
but so far you haven't made it clear to me. It sounds as if
you want to plant a Java process between a user and his CLI
(sh, cmd.exe, ...) or perhaps replace it?
<http://labs.neohapsis.com/2008/04/17/connect-back-shell-literally/>
> I haven't been able to find anything that will let me execute multiple commands in the same invocation.
>
> I want to pass along user commands to be executed, and there might be a "cd" imbedded in the string, or setting some environment variables, or any of a multitude of things that cause one command to depend on the results of some previous command(s), so it I can't just execute each command in a separate process.
>
[toc] | [prev] | [next] | [standalone]
| From | FredK <fred.l.kleinschmidt@gmail.com> |
|---|---|
| Date | 2015-06-18 07:18 -0700 |
| Message-ID | <a6622ed1-2772-4f91-8a3a-03969f64a2c7@googlegroups.com> |
| In reply to | #31818 |
On Wednesday, June 17, 2015 at 6:28:51 PM UTC-7, Jeff Higgins wrote:
> On 06/17/2015 05:57 PM, FredK wrote:
> > On Wednesday, June 17, 2015 at 2:14:45 PM UTC-7, Eric Sosman wrote:
> >> On 6/17/2015 4:56 PM, FredK wrote:
> >>> I want to execute a set of commands and get the results. So I start with,
> >>> on Unix;
> >>> process P = Runtime.getRuntime().exec("commandA; commandB");
> >>>
> >>> or on Windows
> >>> process P = Runtime.getRuntime().exec("commandA & commandB");
> >>>
> >>> How do I get the results of the output AND error output in the order they are created?
> >>>
> >>> If I use this type of coding:
> >>> [...]
> >>> I get all of the stdout, followed by all of the stderr. But suppose commandA writes some output, then some errors, then more outputs, etc. I want to retrieve them in that order.
> >>
> >> You could try using a ProcessBuilder to set up your Process, and
> >> use its redirectErrorStream() method to merge stdout and stderr before
> >> calling start(). But even then, you'll be at the mercy of whatever
> >> buffering takes place in the external process itself: If that process
> >> holds on to stdout data until it's got a bufferload, but emits stderr
> >> data right away (this is the default behavior for many C programs),
> >> the mingled data will be temporally scrambled no matter what you do
> >> on the receiving side.
> >>
> >>
> > I'm not sure I can accomplish what I want;
>
> I'm sure that you're clear on what you want to accomplish
> but so far you haven't made it clear to me. It sounds as if
> you want to plant a Java process between a user and his CLI
> (sh, cmd.exe, ...) or perhaps replace it?
>
> <http://labs.neohapsis.com/2008/04/17/connect-back-shell-literally/>
>
> > I haven't been able to find anything that will let me execute multiple commands in the same invocation.
> >
> > I want to pass along user commands to be executed, and there might be a "cd" imbedded in the string, or setting some environment variables, or any of a multitude of things that cause one command to depend on the results of some previous command(s), so it I can't just execute each command in a separate process.
> >
[toc] | [prev] | [next] | [standalone]
| From | FredK <fred.l.kleinschmidt@gmail.com> |
|---|---|
| Date | 2015-06-18 07:30 -0700 |
| Message-ID | <7e0fd613-2e77-44bb-9c7e-7f31dfb33273@googlegroups.com> |
| In reply to | #31818 |
On Wednesday, June 17, 2015 at 6:28:51 PM UTC-7, Jeff Higgins wrote:
> On 06/17/2015 05:57 PM, FredK wrote:
> > On Wednesday, June 17, 2015 at 2:14:45 PM UTC-7, Eric Sosman wrote:
> >> On 6/17/2015 4:56 PM, FredK wrote:
> >>> I want to execute a set of commands and get the results. So I start with,
> >>> on Unix;
> >>> process P = Runtime.getRuntime().exec("commandA; commandB");
> >>>
> >>> or on Windows
> >>> process P = Runtime.getRuntime().exec("commandA & commandB");
> >>>
> >>> How do I get the results of the output AND error output in the order they are created?
> >>>
> >>> If I use this type of coding:
> >>> [...]
> >>> I get all of the stdout, followed by all of the stderr. But suppose commandA writes some output, then some errors, then more outputs, etc. I want to retrieve them in that order.
> >>
> >> You could try using a ProcessBuilder to set up your Process, and
> >> use its redirectErrorStream() method to merge stdout and stderr before
> >> calling start(). But even then, you'll be at the mercy of whatever
> >> buffering takes place in the external process itself: If that process
> >> holds on to stdout data until it's got a bufferload, but emits stderr
> >> data right away (this is the default behavior for many C programs),
> >> the mingled data will be temporally scrambled no matter what you do
> >> on the receiving side.
> >>
> >>
> > I'm not sure I can accomplish what I want;
>
> I'm sure that you're clear on what you want to accomplish
> but so far you haven't made it clear to me. It sounds as if
> you want to plant a Java process between a user and his CLI
> (sh, cmd.exe, ...) or perhaps replace it?
>
> <http://labs.neohapsis.com/2008/04/17/connect-back-shell-literally/>
>
> > I haven't been able to find anything that will let me execute multiple commands in the same invocation.
> >
> > I want to pass along user commands to be executed, and there might be a "cd" imbedded in the string, or setting some environment variables, or any of a multitude of things that cause one command to depend on the results of some previous command(s), so it I can't just execute each command in a separate process.
> >
The requirement is essentially that I want to include a panel in my program that acts like a shell. So throughout the lifetime of the program, in addition to interacting with the program the user can also use it as if it were a shell - kind of like a Unix xterm, with additional capabilities. For example, the user could type "ls", then point to a file name, right-click on it and it would open up an editor for that file (based on what kind of file it is), or if it is the name of a directory, cd to that directory and possibly execute ls in that directory. Typing "<Ctrl>+U" would execute "cd ..;pwd;ls", plus other features.
I have written something like this in C using Motif, and it works fine - I just fork at the beginning and the child becomes a shell, and I redirect the pipes such that I have access to the shell's input, output, and error streams.
But I don't know how to do this in Java.
--
Fred K
[toc] | [prev] | [next] | [standalone]
| From | Jeff Higgins <jeff@invalid.invalid> |
|---|---|
| Date | 2015-06-18 17:37 -0400 |
| Message-ID | <mlvdp7$2ht$1@dont-email.me> |
| In reply to | #31825 |
On 06/18/2015 10:30 AM, FredK wrote:
> On Wednesday, June 17, 2015 at 6:28:51 PM UTC-7, Jeff Higgins wrote:
>> On 06/17/2015 05:57 PM, FredK wrote:
>>> On Wednesday, June 17, 2015 at 2:14:45 PM UTC-7, Eric Sosman wrote:
>>>> On 6/17/2015 4:56 PM, FredK wrote:
>>>>> I want to execute a set of commands and get the results. So I start with,
>>>>> on Unix;
>>>>> process P = Runtime.getRuntime().exec("commandA; commandB");
>>>>>
>>>>> or on Windows
>>>>> process P = Runtime.getRuntime().exec("commandA & commandB");
>>>>>
>>>>> How do I get the results of the output AND error output in the order they are created?
>>>>>
>>>>> If I use this type of coding:
>>>>> [...]
>>>>> I get all of the stdout, followed by all of the stderr. But suppose commandA writes some output, then some errors, then more outputs, etc. I want to retrieve them in that order.
>>>>
>>>> You could try using a ProcessBuilder to set up your Process, and
>>>> use its redirectErrorStream() method to merge stdout and stderr before
>>>> calling start(). But even then, you'll be at the mercy of whatever
>>>> buffering takes place in the external process itself: If that process
>>>> holds on to stdout data until it's got a bufferload, but emits stderr
>>>> data right away (this is the default behavior for many C programs),
>>>> the mingled data will be temporally scrambled no matter what you do
>>>> on the receiving side.
>>>>
>>>>
>>> I'm not sure I can accomplish what I want;
>>
>> I'm sure that you're clear on what you want to accomplish
>> but so far you haven't made it clear to me. It sounds as if
>> you want to plant a Java process between a user and his CLI
>> (sh, cmd.exe, ...) or perhaps replace it?
>>
>> <http://labs.neohapsis.com/2008/04/17/connect-back-shell-literally/>
>>
>>> I haven't been able to find anything that will let me execute multiple commands in the same invocation.
>>>
>>> I want to pass along user commands to be executed, and there might be a "cd" imbedded in the string, or setting some environment variables, or any of a multitude of things that cause one command to depend on the results of some previous command(s), so it I can't just execute each command in a separate process.
>>>
>
> The requirement is essentially that I want to include a panel in my program that acts like a shell. So throughout the lifetime of the program, in addition to interacting with the program the user can also use it as if it were a shell - kind of like a Unix xterm, with additional capabilities. For example, the user could type "ls", then point to a file name, right-click on it and it would open up an editor for that file (based on what kind of file it is), or if it is the name of a directory, cd to that directory and possibly execute ls in that directory. Typing "<Ctrl>+U" would execute "cd ..;pwd;ls", plus other features.
>
> I have written something like this in C using Motif, and it works fine - I just fork at the beginning and the child becomes a shell, and I redirect the pipes such that I have access to the shell's input, output, and error streams.
>
> But I don't know how to do this in Java.
>
Thanks for the explanation.
That is pretty much what I had imagined you are looking for.
I'm afraid such a thing is well beyond my skill set and
I'm impressed that you've got something working albeit in
another programming environment.
I wish you good luck and would love to here back about
your successes.
[toc] | [prev] | [next] | [standalone]
| From | FredK <fred.l.kleinschmidt@gmail.com> |
|---|---|
| Date | 2015-06-19 07:50 -0700 |
| Message-ID | <6122c63f-1e03-4a2e-87eb-2c246352c4fe@googlegroups.com> |
| In reply to | #31826 |
On Thursday, June 18, 2015 at 2:40:15 PM UTC-7, Jeff Higgins wrote:
> On 06/18/2015 10:30 AM, FredK wrote:
> > On Wednesday, June 17, 2015 at 6:28:51 PM UTC-7, Jeff Higgins wrote:
> >> On 06/17/2015 05:57 PM, FredK wrote:
> >>> On Wednesday, June 17, 2015 at 2:14:45 PM UTC-7, Eric Sosman wrote:
> >>>> On 6/17/2015 4:56 PM, FredK wrote:
> >>>>> I want to execute a set of commands and get the results. So I start with,
> >>>>> on Unix;
> >>>>> process P = Runtime.getRuntime().exec("commandA; commandB");
> >>>>>
> >>>>> or on Windows
> >>>>> process P = Runtime.getRuntime().exec("commandA & commandB");
> >>>>>
> >>>>> How do I get the results of the output AND error output in the order they are created?
> >>>>>
> >>>>> If I use this type of coding:
> >>>>> [...]
> >>>>> I get all of the stdout, followed by all of the stderr. But suppose commandA writes some output, then some errors, then more outputs, etc. I want to retrieve them in that order.
> >>>>
> >>>> You could try using a ProcessBuilder to set up your Process, and
> >>>> use its redirectErrorStream() method to merge stdout and stderr before
> >>>> calling start(). But even then, you'll be at the mercy of whatever
> >>>> buffering takes place in the external process itself: If that process
> >>>> holds on to stdout data until it's got a bufferload, but emits stderr
> >>>> data right away (this is the default behavior for many C programs),
> >>>> the mingled data will be temporally scrambled no matter what you do
> >>>> on the receiving side.
> >>>>
> >>>>
> >>> I'm not sure I can accomplish what I want;
> >>
> >> I'm sure that you're clear on what you want to accomplish
> >> but so far you haven't made it clear to me. It sounds as if
> >> you want to plant a Java process between a user and his CLI
> >> (sh, cmd.exe, ...) or perhaps replace it?
> >>
> >> <http://labs.neohapsis.com/2008/04/17/connect-back-shell-literally/>
> >>
> >>> I haven't been able to find anything that will let me execute multiple commands in the same invocation.
> >>>
> >>> I want to pass along user commands to be executed, and there might be a "cd" imbedded in the string, or setting some environment variables, or any of a multitude of things that cause one command to depend on the results of some previous command(s), so it I can't just execute each command in a separate process.
> >>>
> >
> > The requirement is essentially that I want to include a panel in my program that acts like a shell. So throughout the lifetime of the program, in addition to interacting with the program the user can also use it as if it were a shell - kind of like a Unix xterm, with additional capabilities. For example, the user could type "ls", then point to a file name, right-click on it and it would open up an editor for that file (based on what kind of file it is), or if it is the name of a directory, cd to that directory and possibly execute ls in that directory. Typing "<Ctrl>+U" would execute "cd ..;pwd;ls", plus other features.
> >
> > I have written something like this in C using Motif, and it works fine - I just fork at the beginning and the child becomes a shell, and I redirect the pipes such that I have access to the shell's input, output, and error streams.
> >
> > But I don't know how to do this in Java.
> >
>
> Thanks for the explanation.
> That is pretty much what I had imagined you are looking for.
> I'm afraid such a thing is well beyond my skill set and
> I'm impressed that you've got something working albeit in
> another programming environment.
> I wish you good luck and would love to here back about
> your successes.
Here's what I am now doing:
First, I store the current working directory as currentDir.
Then I create a meta-command from the actual command:
private final String[] cbufWindows = { "cmd", "/c", "" };
private final String[] cbufLinux = { "bash", "-c", "" };
String[] buf;
String command;
if ( platform == Platform.UNIX ) {
command = "cd " + dir + "; " + cmd + "; echo " + END_STR
+ "; echo $?; pwd";
cbufLinux[2] = command;
buf = cbufLinux;
} else if ( platform == Platform.WINDOWS ) {
command = "pushd " + dir + " & " + cmd + " & echo " + END_STR
+ " & cd &popd";
cbufWindows[2] = command;
buf = cbufWindows;
} else {
return; // unimplemented for other platforms
}
Runtime rt = Runtime.getRuntime();
Process p = rt.exec(buf);
Here, Platform is an enum defined by me, and END_STR is a sentinel that is just a constant long string of gibberish unlikely to be input by the user or output by a command; this is to determine when the command actually ends.
Note that in my meta-command I first cd to the current directory, execute the command, echo the ENDSTR, then echo the (possibly new) current directory.
When reading the output of the command, I look for the sentinel, then read the echoed directory and store it back in "currentDir".
This works fine as long as the command does not require interactive user input, but is sufficient for my needs.
--
Fred K
[toc] | [prev] | [next] | [standalone]
| From | Jeff Higgins <jeff@invalid.invalid> |
|---|---|
| Date | 2015-06-19 21:33 -0400 |
| Message-ID | <mm2fug$71o$1@dont-email.me> |
| In reply to | #31828 |
On 06/19/2015 10:50 AM, FredK wrote:
> On Thursday, June 18, 2015 at 2:40:15 PM UTC-7, Jeff Higgins wrote:
>> On 06/18/2015 10:30 AM, FredK wrote:
>>> On Wednesday, June 17, 2015 at 6:28:51 PM UTC-7, Jeff Higgins wrote:
>>>> On 06/17/2015 05:57 PM, FredK wrote:
>>>>> On Wednesday, June 17, 2015 at 2:14:45 PM UTC-7, Eric Sosman wrote:
>>>>>> On 6/17/2015 4:56 PM, FredK wrote:
>>>>>>> I want to execute a set of commands and get the results. So I start with,
>>>>>>> on Unix;
>>>>>>> process P = Runtime.getRuntime().exec("commandA; commandB");
>>>>>>>
>>>>>>> or on Windows
>>>>>>> process P = Runtime.getRuntime().exec("commandA & commandB");
>>>>>>>
>>>>>>> How do I get the results of the output AND error output in the order they are created?
>>>>>>>
>>>>>>> If I use this type of coding:
>>>>>>> [...]
>>>>>>> I get all of the stdout, followed by all of the stderr. But suppose commandA writes some output, then some errors, then more outputs, etc. I want to retrieve them in that order.
>>>>>>
>>>>>> You could try using a ProcessBuilder to set up your Process, and
>>>>>> use its redirectErrorStream() method to merge stdout and stderr before
>>>>>> calling start(). But even then, you'll be at the mercy of whatever
>>>>>> buffering takes place in the external process itself: If that process
>>>>>> holds on to stdout data until it's got a bufferload, but emits stderr
>>>>>> data right away (this is the default behavior for many C programs),
>>>>>> the mingled data will be temporally scrambled no matter what you do
>>>>>> on the receiving side.
>>>>>>
>>>>>>
>>>>> I'm not sure I can accomplish what I want;
>>>>
>>>> I'm sure that you're clear on what you want to accomplish
>>>> but so far you haven't made it clear to me. It sounds as if
>>>> you want to plant a Java process between a user and his CLI
>>>> (sh, cmd.exe, ...) or perhaps replace it?
>>>>
>>>> <http://labs.neohapsis.com/2008/04/17/connect-back-shell-literally/>
>>>>
>>>>> I haven't been able to find anything that will let me execute multiple commands in the same invocation.
>>>>>
>>>>> I want to pass along user commands to be executed, and there might be a "cd" imbedded in the string, or setting some environment variables, or any of a multitude of things that cause one command to depend on the results of some previous command(s), so it I can't just execute each command in a separate process.
>>>>>
>>>
>>> The requirement is essentially that I want to include a panel in my program that acts like a shell. So throughout the lifetime of the program, in addition to interacting with the program the user can also use it as if it were a shell - kind of like a Unix xterm, with additional capabilities. For example, the user could type "ls", then point to a file name, right-click on it and it would open up an editor for that file (based on what kind of file it is), or if it is the name of a directory, cd to that directory and possibly execute ls in that directory. Typing "<Ctrl>+U" would execute "cd ..;pwd;ls", plus other features.
>>>
>>> I have written something like this in C using Motif, and it works fine - I just fork at the beginning and the child becomes a shell, and I redirect the pipes such that I have access to the shell's input, output, and error streams.
>>>
>>> But I don't know how to do this in Java.
>>>
>>
>> Thanks for the explanation.
>> That is pretty much what I had imagined you are looking for.
>> I'm afraid such a thing is well beyond my skill set and
>> I'm impressed that you've got something working albeit in
>> another programming environment.
>> I wish you good luck and would love to here back about
>> your successes.
>
> Here's what I am now doing:
> First, I store the current working directory as currentDir.
> Then I create a meta-command from the actual command:
>
> private final String[] cbufWindows = { "cmd", "/c", "" };
> private final String[] cbufLinux = { "bash", "-c", "" };
> String[] buf;
> String command;
> if ( platform == Platform.UNIX ) {
> command = "cd " + dir + "; " + cmd + "; echo " + END_STR
> + "; echo $?; pwd";
> cbufLinux[2] = command;
> buf = cbufLinux;
> } else if ( platform == Platform.WINDOWS ) {
> command = "pushd " + dir + " & " + cmd + " & echo " + END_STR
> + " & cd &popd";
> cbufWindows[2] = command;
> buf = cbufWindows;
> } else {
> return; // unimplemented for other platforms
> }
>
> Runtime rt = Runtime.getRuntime();
> Process p = rt.exec(buf);
>
> Here, Platform is an enum defined by me, and END_STR is a sentinel that is just a constant long string of gibberish unlikely to be input by the user or output by a command; this is to determine when the command actually ends.
>
> Note that in my meta-command I first cd to the current directory, execute the command, echo the ENDSTR, then echo the (possibly new) current directory.
>
> When reading the output of the command, I look for the sentinel, then read the echoed directory and store it back in "currentDir".
>
> This works fine as long as the command does not require interactive user input, but is sufficient for my needs.
>
I'm kinda tempted to ask why but probably shouldn't.
<http://www.linusakesson.net/programming/tty/>
Well, what the heck. Why?
[toc] | [prev] | [next] | [standalone]
| From | Jeff Higgins <jeff@invalid.invalid> |
|---|---|
| Date | 2015-06-19 21:56 -0400 |
| Message-ID | <mm2han$1ap$1@dont-email.me> |
| In reply to | #31831 |
On 06/19/2015 09:33 PM, Jeff Higgins wrote: > Well, what the heck. Why? <http://www.linusakesson.net/programming/pipelogic/index.php>
[toc] | [prev] | [next] | [standalone]
| From | Jeff Higgins <jeff@invalid.invalid> |
|---|---|
| Date | 2015-06-19 23:02 -0400 |
| Message-ID | <mm2l5e$im5$1@dont-email.me> |
| In reply to | #31832 |
Not to mention this one. <http://www.linusakesson.net/programming/vimsuspend/index.php>
[toc] | [prev] | [next] | [standalone]
| From | Jeff Higgins <jeff@invalid.invalid> |
|---|---|
| Date | 2015-06-20 11:11 -0400 |
| Message-ID | <mm3vtq$kiv$1@dont-email.me> |
| In reply to | #31832 |
On 06/19/2015 09:56 PM, Jeff Higgins wrote: > On 06/19/2015 09:33 PM, Jeff Higgins wrote: > >> Well, what the heck. Why? > <http://www.linusakesson.net/programming/pipelogic/index.php> > > Well, it's not Java, but as a personal memento: GASH - The Good Auld Shell <http://rust-class.org/pages/ps2.html> <http://rust-class.org/0/pages/using-rust-for-an-undergraduate-os-course.html> <http://tldp.org/HOWTO/Text-Terminal-HOWTO.html>
[toc] | [prev] | [next] | [standalone]
| From | Jeff Higgins <jeff@invalid.invalid> |
|---|---|
| Date | 2015-06-20 12:14 -0400 |
| Message-ID | <mm43k4$3de$1@dont-email.me> |
| In reply to | #31835 |
On 06/20/2015 11:11 AM, Jeff Higgins wrote: > On 06/19/2015 09:56 PM, Jeff Higgins wrote: >> On 06/19/2015 09:33 PM, Jeff Higgins wrote: >> >>> Well, what the heck. Why? >> <http://www.linusakesson.net/programming/pipelogic/index.php> >> >> > Well, it's not Java, but as a personal memento: > GASH - The Good Auld Shell > <http://rust-class.org/pages/ps2.html> > > <http://rust-class.org/0/pages/using-rust-for-an-undergraduate-os-course.html> > > <http://tldp.org/HOWTO/Text-Terminal-HOWTO.html> > <https://github.com/drrb/java-rust-example>
[toc] | [prev] | [next] | [standalone]
| From | Jeff Higgins <jeff@invalid.invalid> |
|---|---|
| Date | 2015-06-20 20:58 -0400 |
| Message-ID | <mm52a1$gg4$1@dont-email.me> |
| In reply to | #31835 |
On 06/20/2015 11:11 AM, Jeff Higgins wrote: > Well, it's not Java, but as a personal memento: Xinu Is Not Unix <http://www.xinu.cs.purdue.edu/> RCU - read-copy-update <http://www2.rdrop.com/users/paulmck/RCU/>
[toc] | [prev] | [next] | [standalone]
| From | Eric Sosman <esosman@comcast-dot-net.invalid> |
|---|---|
| Date | 2015-06-19 11:01 -0400 |
| Message-ID | <mm1ap2$vt7$1@dont-email.me> |
| In reply to | #31825 |
On 6/18/2015 10:30 AM, FredK wrote:
>
> The requirement is essentially that I want to include a panel in my program that acts like a shell. So throughout the lifetime of the program, in addition to interacting with the program the user can also use it as if it were a shell - kind of like a Unix xterm, with additional capabilities. For example, the user could type "ls", then point to a file name, right-click on it and it would open up an editor for that file (based on what kind of file it is), or if it is the name of a directory, cd to that directory and possibly execute ls in that directory. Typing "<Ctrl>+U" would execute "cd ..;pwd;ls", plus other features.
>
> I have written something like this in C using Motif, and it works fine - I just fork at the beginning and the child becomes a shell, and I redirect the pipes such that I have access to the shell's input, output, and error streams.
>
> But I don't know how to do this in Java.
Quick and (very) dirty, Windows version:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class Foo extends JPanel {
private final JTextArea screen;
private final Process shellProcess;
private final Writer shellInput;
private final Reader shellOutput;
private Foo() throws IOException {
assert SwingUtilities.isEventDispatchThread();
screen = new JTextArea(24, 80);
add(new JScrollPane(screen));
ProcessBuilder builder = new ProcessBuilder();
builder.command("cmd");
builder.redirectErrorStream(true);
shellProcess = builder.start();
shellInput = new OutputStreamWriter(shellProcess.getOutputStream());
shellOutput = new InputStreamReader(shellProcess.getInputStream());
Runnable listener = () -> {
char[] buffer = new char[512];
int len;
do {
String text;
try {
len = shellOutput.read(buffer);
text = (len >= 0) ? new String(buffer, 0, len) : "***
EOF ***";
} catch (IOException ex) {
len = -1;
text = "*** " + ex.getLocalizedMessage() + " ***";
}
final String finalText = text;
SwingUtilities.invokeLater(() -> {
screen.append(finalText);
});
} while (len >= 0);
};
new Thread(listener).start();
}
public void stopProcess() {
shellProcess.destroyForcibly();
}
private static final String NEWLINE =
System.getProperty("line.separator");
public void sendCommand(String command) {
if (!command.endsWith(NEWLINE)) {
command += NEWLINE;
}
try {
shellInput.write(command);
shellInput.flush();
} catch (IOException ex) {
Logger.getLogger(Foo.class.getName()).log(Level.SEVERE, null, ex);
System.exit(1);
}
}
public static void main(String[] unused) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("Foo");
final Foo foo;
try {
foo = new Foo();
} catch (IOException ex) {
Logger.getLogger(Foo.class.getName()).log(Level.SEVERE,
null, ex);
System.exit(1);
return; // to placate the compiler
}
frame.add(foo, BorderLayout.CENTER);
final JTextField command = new JTextField(60);
command.addActionListener((ActionEvent e) -> {
foo.sendCommand(command.getText());
});
JLabel label = new JLabel("Command me:");
label.setLabelFor(command);
JPanel controls = new JPanel();
controls.add(label);
controls.add(command);
frame.add(controls, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
foo.stopProcess();
System.exit(0);
}
});
frame.pack();
frame.setVisible(true);
});
}
}
--
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM
[toc] | [prev] | [next] | [standalone]
| From | Eric Sosman <esosman@comcast-dot-net.invalid> |
|---|---|
| Date | 2015-06-18 08:38 -0400 |
| Message-ID | <mlue17$v8u$1@dont-email.me> |
| In reply to | #31816 |
On 6/17/2015 5:57 PM, FredK wrote:
> On Wednesday, June 17, 2015 at 2:14:45 PM UTC-7, Eric Sosman wrote:
>> On 6/17/2015 4:56 PM, FredK wrote:
>>> I want to execute a set of commands and get the results. So I start with,
>>> on Unix;
>>> process P = Runtime.getRuntime().exec("commandA; commandB");
>>>
>>> or on Windows
>>> process P = Runtime.getRuntime().exec("commandA & commandB");
>>>
>>> How do I get the results of the output AND error output in the order they are created?
>>>
>>> If I use this type of coding:
>>> [...]
>>> I get all of the stdout, followed by all of the stderr. But suppose commandA writes some output, then some errors, then more outputs, etc. I want to retrieve them in that order.
>>
>> You could try using a ProcessBuilder to set up your Process, and
>> use its redirectErrorStream() method to merge stdout and stderr before
>> calling start(). But even then, you'll be at the mercy of whatever
>> buffering takes place in the external process itself: If that process
>> holds on to stdout data until it's got a bufferload, but emits stderr
>> data right away (this is the default behavior for many C programs),
>> the mingled data will be temporally scrambled no matter what you do
>> on the receiving side.
>>
>>
> I'm not sure I can accomplish what I want; I haven't been able to find anything that will let me execute multiple commands in the same invocation.
>
> I want to pass along user commands to be executed, and there might be a "cd" imbedded in the string, or setting some environment variables, or any of a multitude of things that cause one command to depend on the results of some previous command(s), so it I can't just execute each command in a separate process.
On Unixoid systems, you do this by executing a shell as the child
process and feeding it the stream of commands you want executed. I'm
not sure what the Windows idiom is -- maybe execute cmd.exe? -- but it's
likely to be something similar.
But that's a separate matter from getting "correct" interleaving
of the stdout and stderr streams, which may be buffered independently
(and differently!) in the various sub-commands. If the commands are
A,B,C I think you can ensure that all of A's output will precede B's,
and all of B's will precede C's, but unless you've got special knowledge
of A,B,C I don't think you can impose any particular ordering of the
stdout and stderr data they generate individually.
--
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM
[toc] | [prev] | [next] | [standalone]
| From | Jeff Higgins <jeff@invalid.invalid> |
|---|---|
| Date | 2015-07-03 23:41 -0400 |
| Message-ID | <mn7knt$nka$1@dont-email.me> |
| In reply to | #31814 |
On 06/17/2015 04:56 PM, FredK wrote: > I want to execute a set of commands and get the results. JEP 102: Process API Updates <http://openjdk.java.net/jeps/102> jshell - A shell implementation in Java <https://code.google.com/p/jshell/> JShell http://geophile.com/jshell/ JEP 222: jshell: The Java Shell (Read-Eval-Print Loop) <http://openjdk.java.net/jeps/222>
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.java.programmer
csiph-web