You can read bytes from system/ports/input, and if you convert them from BINARY! bytes to a STRING! of unicode codepoints you get something coherent:
>> to-string read system/ports/input
Hello
== "Hello^/"
But if you try writing to system/ports/output in Rebol3 you get:
>> write system/ports/output "World"
** Script error: write does not allow none! for its destination argument
The output port is a field in the object, but it's none. Running an ordinary PRINT command that generates output doesn't make the field get set. Where is it?
Also while on the topic, where is the stderr port?
Rebol3 Alpha has not completely implemented the standard output and standard error ports yet.
Related
I want my Nim program to write to the console if there is one, and redirect echo to write to a file if there isn't. Is there an equivalent to the Environment.UserInteractive property in .NET which I could use to detect if no console is available and redirect stdout in that case?
It's a combination of using isatty() as suggested by genotrance and the code that you found :)
# stdout_to_file.nim
import terminal, strformat, times
if isatty(stdout): # ./stdout_to_file
echo "This is output to the terminal."
else: # ./stdout_to_file | cat
const
logFileName = "log.txt"
let
# https://github.com/jasonrbriggs/nimwhistle/blob/183c19556d6f11013959d17dfafd43486e1109e5/tests/cgitests.nim#L15
logFile = open(logFileName, fmWrite)
stdout = logFile
echo fmt"This is output to the {logFileName} file."
echo fmt"- Run using nim {NimVersion} on {now()}."
Save above file as stdout_to_file.nim.
On running:
nim c stdout_to_file.nim && ./stdout_to_file | cat
I get this in the created log.txt:
This is output to the log.txt file.
- Run using nim 0.19.9 on 2019-01-23T22:42:27-05:00.
You should be able to use isatty().
Here's an example in Nimble.
Edit:
#tjohnson this is in response to your comment. I don't have enough points to respond to your comment directly or something? Thanks Stack Overflow...
It's hard to say without seeing more of the code.
What version of Nim are you using?
I suspect stdout has been shadowed by a read only symbol.
Are you calling this code inside of a proc and passing stdout as an argument?
like this:
proc foo(stdout: File)
If so, you will need to change it to a var parameter to make the argument writable:
proc test(stdout: var File)
Or use stdout as a global variable instead.
I am using Verilator to incorporate an algorithm written in SystemVerilog into an executable utility that manipulates I/O streams passed via stdin and stdout. Unfortunately, when I use the SystemVerilog $display() function, the output goes to stdout. I would like it to go to stderr so that stdout remains uncontaminated for my other purposes.
How can I make this happen?
Thanks to #toolic for pointing out the existence of $fdisplay(), which can be used thusly...
$fdisplay(STDERR,"hello world"); // also supports formatted arguments
IEEE Std 1800-2012 states that STDERR should be pre-opened, but it did not seem to be known to Verilator. A workaround for this is:
integer STDERR = 32'h8000_0002;
Alternatively, you can create a log file handle for use with $fdisplay() like so...
integer logfile;
initial begin
$system("echo 'initial at ['$(date)']'>>temp.log");
logfile = $fopen("temp.log","a"); // or open with "w" to start fresh
end
It might be nice if you could create a custom wrapper that works like $display but uses your selected file descriptor (without specifying it every time). Unfortunately, that doesn't seem to be possible within the language itself -- but maybe you can do it with the DPI, see DPI Display Functions (I haven't gotten this to work so far).
I would like to assign output of a bash command to a variable in .lua script. Is it possible?
For instance, something similar to:
var = `ps uax | grep myprocess`
Yes, you need to use io.popen for this.
io.popen (prog [, mode])
Starts program prog in a separated process and returns a file handle that you can use to read data from this program (if mode is "r", the default) or to write data to this program (if mode is "w").
This function is system dependent and is not available on all platforms.
Also see How to execute an external command?.
io.popen calls a command but returns a file object so you can read the output of the command, if the second argument is 'r', but you can also pass input to a command with a second argument of 'w'. Unfortunately, you don't get a io.popen2, and you don't get the return code.
I'm building an iOS application that communicates with a remote server. In this case, I'm executing commands using SSH, however, the response coming back from the server is coming in the form of what appears to be hexadecimal. My delegate function for handling responses from a remote server takes the response argument as an NSString, however, this is the content of the string returned (command executed was "ls /" )
ls /\r\n\x1b[0m\x1b[01;34mbin\x1b[0m \x1b[01;34mdev\x1b[0m \x1b[01;36minitrd.img\x1b[0m \x1b[01;34mlib64\x1b[0m \x1b[01;34mmnt\x1b[0m \x1b[01;34mroot\x1b[0m \x1b[01;34msrv\x1b[0m \x1b[01;34musr\x1b[0m\r\n\x1b[01;34mboot\x1b[0m \x1b[01;34metc\x1b[0m \x1b[01;36minitrd.img.old\x1b[0m \x1b[01;34mlost+found\x1b[0m \x1b[01;34mopt\x1b[0m \x1b[01;34mrun\x1b[0m \x1b[01;34msys\x1b[0m \x1b[01;34mvar\x1b[0m\r\n\x1b[01;34mcdrom\x1b[0m \x1b[01;34mhome\x1b[0m \x1b[01;34mlib\x1b[0m \x1b[01;34mmedia\x1b[0m \x1b[01;34mproc\x1b[0m \x1b[01;34msbin\x1b[0m \x1b[30;42mtmp\x1b[0m \x1b[01;36mvmlinuz\x1b[0m'
If this is in fact hexadecimal, how to I convert this back to a readable string for display purposes? If it's not hexadecimal, does anyone know what it is?
EDIT:
Since this is ANSI Color Control Codes, what's the best method to remove them?
prepend "\" to the beginning of the command
$ \ls
or provide handling for the escape sequences (strip, display)
I wrote the following two functions, and call the second ("callAndWait") from JavaScript running inside Windows Script Host. My overall intent is to call one command line program from another. That is, I'm running the initial scripting using cscript, and then trying to run something else (Ant) from that script.
function readAllFromAny(oExec)
{
if (!oExec.StdOut.AtEndOfStream)
return oExec.StdOut.ReadLine();
if (!oExec.StdErr.AtEndOfStream)
return "STDERR: " + oExec.StdErr.ReadLine();
return -1;
}
// Execute a command line function....
function callAndWait(execStr) {
var oExec = WshShell.Exec(execStr);
while (oExec.Status == 0)
{
WScript.Sleep(100);
var output;
while ( (output = readAllFromAny(oExec)) != -1) {
WScript.StdOut.WriteLine(output);
}
}
}
Unfortunately, when I run my program, I don't get immediate feedback about what the called program is doing. Instead, the output seems to come in fits and starts, sometimes waiting until the original program has finished, and sometimes it appears to have deadlocked. What I really want to do is have the spawned process actually share the same StdOut as the calling process, but I don't see a way to do that. Just setting oExec.StdOut = WScript.StdOut doesn't work.
Is there an alternate way to spawn processes that will share the StdOut & StdErr of the launching process? I tried using "WshShell.Run(), but that gives me a "permission denied" error. That's problematic, because I don't want to have to tell my clients to change how their Windows environment is configured just to run my program.
What can I do?
You cannot read from StdErr and StdOut in the script engine in this way, as there is no non-blocking IO as Code Master Bob says. If the called process fills up the buffer (about 4KB) on StdErr while you are attempting to read from StdOut, or vice-versa, then you will deadlock/hang. You will starve while waiting for StdOut and it will block waiting for you to read from StdErr.
The practical solution is to redirect StdErr to StdOut like this:
sCommandLine = """c:\Path\To\prog.exe"" Argument1 argument2"
Dim oExec
Set oExec = WshShell.Exec("CMD /S /C "" " & sCommandLine & " 2>&1 """)
In other words, what gets passed to CreateProcess is this:
CMD /S /C " "c:\Path\To\prog.exe" Argument1 argument2 2>&1 "
This invokes CMD.EXE, which interprets the command line. /S /C invokes a special parsing rule so that the first and last quote are stripped off, and the remainder used as-is and executed by CMD.EXE. So CMD.EXE executes this:
"c:\Path\To\prog.exe" Argument1 argument2 2>&1
The incantation 2>&1 redirects prog.exe's StdErr to StdOut. CMD.EXE will propagate the exit code.
You can now succeed by reading from StdOut and ignoring StdErr.
The downside is that the StdErr and StdOut output get mixed together. As long as they are recognisable you can probably work with this.
Another technique which might help in this situation is to redirect the standard error stream of the command to accompany the standard output.
Do this by adding "%comspec% /c" to the front and "2>&1" to the end of the execStr string.
That is, change the command you run from:
zzz
to:
%comspec% /c zzz 2>&1
The "2>&1" is a redirect instruction which causes the StdErr output (file descriptor 2) to be written to the StdOut stream (file descriptor 1).
You need to include the "%comspec% /c" part because it is the command interpreter which understands about the command line redirect. See http://technet.microsoft.com/en-us/library/ee156605.aspx
Using "%comspec%" instead of "cmd" gives portability to a wider range of Windows versions.
If your command contains quoted string arguments, it may be tricky to get them right:
the specification for how cmd handles quotes after "/c" seems to be incomplete.
With this, your script needs only to read the StdOut stream, and will receive both standard output and standard error.
I used this with "net stop wuauserv", which writes to StdOut on success (if the service is running)
and StdErr on failure (if the service is already stopped).
First, your loop is broken in that it always tries to read from oExec.StdOut first. If there is no actual output then it will hang until there is. You wont see any StdErr output until StdOut.atEndOfStream becomes true (probably when the child terminates). Unfortunately, there is no concept of non-blocking I/O in the script engine. That means calling read and having it return immediately if there is no data in the buffer. Thus there is probably no way to get this loop to work as you want. Second, WShell.Run does not provide any properties or methods to access the standard I/O of the child process. It creates the child in a separate window, totally isolated from the parent except for the return code. However, if all you want is to be able to SEE the output from the child then this might be acceptable. You will also be able to interact with the child (input) but only through the new window (see SendKeys).
As for using ReadAll(), this would be even worse since it collects all the input from the stream before returning so you wouldn't see anything at all until the stream was closed. I have no idea why the example places the ReadAll in a loop which builds a string, a single if (!WScript.StdIn.AtEndOfStream) should be sufficient to avoid exceptions.
Another alternative might be to use the process creation methods in WMI. How standard I/O is handled is not clear and there doesn't appear to be any way to allocate specific streams as StdIn/Out/Err. The only hope would be that the child would inherit these from the parent but that's what you want, isn't it? (This comment based upon an idea and a little bit of research but no actual testing.)
Basically, the scripting system is not designed for complicated interprocess communication/synchronisation.
Note: Tests confirming the above were performed on Windows XP Sp2 using Script version 5.6. Reference to current (5.8) manuals suggests no change.
Yes, the Exec function seems to be broken when it comes to terminal output.
I have been using a similar function function ConsumeStd(e) {WScript.StdOut.Write(e.StdOut.ReadAll());WScript.StdErr.Write(e.StdErr.ReadAll());} that I call in a loop similar to yours. Not sure if checking for EOF and reading line by line is better or worse.
You might have hit the deadlock issue described on this Microsoft Support site.
One suggestion is to always read both from stdout and stderr.
You could change readAllFromAny to:
function readAllFromAny(oExec)
{
var output = "";
if (!oExec.StdOut.AtEndOfStream)
output = output + oExec.StdOut.ReadLine();
if (!oExec.StdErr.AtEndOfStream)
output = output + "STDERR: " + oExec.StdErr.ReadLine();
return output ? output : -1;
}