Lazarus can run bash scripts and commands. How to get the output of an executed command as string and later use it, for example print it with ShowMessage? Thanks!
Summary:
use the tprocess class from unit process, that allows to trap console output using pipes.
for straightforward cases use the Runcommand helper functions (also in process, wrap tprocess for simple cases)
Be aware that while you see console output as one stream, in fact there might be two (stdout and stderr)
Related
The windows API provides GetCommandLine() which returns the cooked command line used to start a process.
For instance, if a console application is started with the command:
MyProg.exe > OutputHere
The command line seen by MyProg.exe will not include the portion
> OutputHere
I'd like to somehow get the command line exactly as it was. Is this possible ? and if yes, how ?
Suggestions in C and/or plain (no objects) Delphi greatly appreciated. Creative solutions welcome (hopefully, not requiring ring 0 code.)
Thank you very much for your help.
NOTE: I can tell if the input/output, etc has been redirected but, that is not what I'm looking for. I need the original/uncooked command line.
The redirection or piping of stdin, stdout and stderr is handled the command interpreter, typically cmd.exe. The interpreter parses the command and creates the necessary files and pipes, and then creates the one or more processes needed to implement your command.
The processes that are created have no knowledge of the original command, they only get that part of the command that is not related to piping and redirection.
So what you are trying to do is not possible, at least within your process. The only thing that knows the original command is the command interpreter.
Whether or not you can retrieve the full command line including the pipe commands depends on whether your start the program in a command window or for example using the "Run" command from the Start menu. If you use the "Run" command from the Start menu GetCommandLine actually retrieves the full command line including the redirection commands, but redirection does not work as it seems to be a feature of CMD.EXE.
As others have pointed out, what are you trying to achieve here / why do you need to capture the redirection commands?
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.
Bash commands are available from an interactive tclsh session. E.g. in a tclsh session you can have
% ls
instead of
$ exec ls
However, you cant have a tcl script which calls bash commands directly (i.e. without exec).
How can I make tclsh to recognize bash commands while interpreting tcl script files, just like it does in an interactive session?
I guess there is some tcl package (or something like that), which is being loaded automatically while launching an interactive session to support direct calls of bash commans. How can I load it manually in tcl script files?
If you want to have specific utilities available in your scripts, write bridging procedures:
proc ls args {
exec {*}[auto_execok ls] {*}$args
}
That will even work (with obvious adaptation) for most shell builtins or on Windows. (To be fair, you usually don't want to use an external ls; the internal glob command usually suffices, sometimes with extra help from some file subcommands.) Some commands need a little more work (e.g., redirecting input so it comes from the terminal, with an extra <#stdin or </dev/tty; that's needed for stty on some platforms) but that works reasonably well.
However, if what you're asking for is to have arbitrary execution of external programs without any extra code to mark that they are external, that's considered to be against the ethos of Tcl. The issue is that it makes the code quite a lot harder to maintain; it's not obvious that you're doing an expensive call-out instead of using something (relatively) cheap that's internal. Putting in the exec in that case isn't that onerous…
What's going on here is that the unknown proc is getting invoked when you type a command like ls, because that's not an existing tcl command, and by default, that command will check that if the command was invoked from an interactive session and from the top-level (not indirectly in a proc body) and it's checking to see if the proc name exists somewhere on the path. You can get something like this by writing your own proc unknown.
For a good start on this, examine the output of
info body unknown
One thing you should know is that ls is not a Bash command. It's a standalone utility. The clue for how tclsh runs such utilities is right there in its name - sh means "shell". So it's the rough equivalent to Bash in that Bash is also a shell. Tcl != tclsh so you have to use exec.
Is there a way to run a shell command, have the output show up in a new buffer and have that output show up incrementally? Eshell and other emacs terminal emulators do a find job of this but I see no way to script them.
What I'd like to do is write little elisp functions to do stuff like run unit tests, etc. and watch the output trickle into a buffer.
The elisp function shell-command is close to what I want but it shows all the output at once when the process finishes.
As doublep mentioned, there is M-x compile, and there's also just the simple M-x shell and in that shell you run whatever you want.
You can also use comint-run to execute a command without needing to start a sub-shell first. I believe M-x shell uses comint mode with some modifications, so this won't be a whole lot different from that. But if you want to call a program directly and have its input and output be tied to a buffer, comint-run is the function to call. It is a little tricky to use, so read the documentation: C-h f comint-run.