I have the following code to capture and process the Run command output.
How do I modify it such that the Run command window displays output and at the same time the output gets logged? Replacing #SW_HIDE with #SW_SHOW (or the equivalent) just shows a blank command window.
Something similar to the linux tee command which logs to file while it prints STDOUT.
$CurrentPID = Run(#ComSpec & ' /c ' & $CurrentLogCmd, "", #SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD)
If Not ProcessWaitClose($CurrentPID,60) Then
WriteLog("[Warning] Timed-out.Finding date in current hour raw log -" & $CurrentLogFileName)
$F_LogWarningExist = 1
Return $C_SUCCESS ; Take chances and proceed with parsing raw logs
EndIf
$CurrentOutput = StdoutRead($CurrentPID)
ConsoleWrite(_getDOSOutput('ipconfig /all') & #CRLF)
Func _getDOSOutput($command)
Local $text = '', $Pid = Run('"' & #ComSpec & '" /c ' & $command, '', #SW_HIDE, 2 + 4)
While 1
$text &= StdoutRead($Pid, False, False)
If #error Then ExitLoop
Sleep(10)
WEnd
Return StringStripWS($text, 7)
EndFunc ;==>_getDOSOutput
Maybe this helps you out.
Something similar to the linux tee command which logs to file while it prints STDOUT.
Redirecting STDOUT makes receiving party (the script) responsible for display and logging. As per documentation:
StdoutRead() does not block, it will return immediately. In order to get all data, it must be called in a loop.
Example:
#AutoIt3Wrapper_Change2CUI=Y
#include <Constants.au3>
#include <MsgBoxConstants.au3>
Global Enum $EXIT_OK, _
$EXIT_NOCOMPILE, _
$EXIT_ABORT
Global Const $g_sPromptError = 'Compile this script and run resulting executable instead.', _
$g_sPromptInput = 'Enter a command:', _
$g_sInputDefault = 'ping localhost -n 10'
Global $g_sCMD = '', _
$g_sSTD = ''
Main()
Func Main()
If Not #Compiled Then
MsgBox($MB_OK + $MB_ICONERROR, #ScriptName, $g_sPromptError)
Exit $EXIT_NOCOMPILE
EndIf
$g_sCMD = InputBox(#ScriptName, $g_sPromptInput, $g_sInputDefault)
If #error Then Exit $EXIT_ABORT
$g_sSTD = _getCmdStd($g_sCMD)
MsgBox($MB_OK + $MB_ICONINFORMATION, $g_sCMD, $g_sSTD)
Exit $EXIT_OK
EndFunc
Func _getCmdStd(Const $sCMD, Const $sDir = '', Const $iType = $STDERR_MERGED, Const $bShow = False, Const $iDelay = 100)
Local $sTMP = ''
Local $sSTD = ''
Local $sCOM = #ComSpec & ' /c ' & $sCMD
Local Const $iWin = $bShow ? #SW_SHOW : #SW_HIDE
Local Const $iPID = Run($sCOM, $sDir, $iWin, $iType)
While True
$sTMP = StdoutRead($iPID, False, False)
If #error Then
ExitLoop 1
ElseIf $sTMP Then
$sTMP = StringReplace($sTMP, #CR & #CR, '')
$sSTD &= $sTMP
ConsoleWrite($sTMP)
EndIf
Sleep($iDelay)
WEnd
Return SetError(#error, #extended, $sSTD)
EndFunc
Returns STDOUT (and STDERR) after execution completes, while writing to console during execution. Replace MsgBox() as required (logging function).
Related
I'm writing a code in groovy to read a file line by line and perform an action (for ex: build a code for a specific configuration) based on the information available in the line.
The following groovy code runs fine for me, except that i want to ignore or skip the first line or rather any line which starts with # or comment (//).
__SAMPLE_GROOVY_CODE__
input_file = '/home/user/inputFile.txt'
// read all the lines into a list, each line is an element in the list
File FH1 = new File(input_file)
def lines = FH1.readLines()
for (line in lines)
{
env.c_num = sh(returnStdout: true, script: "echo '${line}' | cut -d ':' -f 1").trim();
env.p_num = sh(returnStdout: true, script: "echo '${line}' | cut -d ':' -f 2").trim();
env.p_len = p_num.length();
println("INFO: Length is ${p_len} \n");
if(env.p_len != '0')
{
println ("INFO: Build is required !! \n");
println ("INFO: c_num is: ${c_num} \n");
println ("INFO: p_num is: ${p_num} \n");
// Code for build will come here..!!
}
else
{
println("INFO: Build is NOT required !! \n");
}
}
__INPUT_FILE__
$> cat /home/user/inputFile.txt
# Details of inputFile.txt
1234-A0: aa ab ac ad ae al
5678-B0:
2345-B0: ba
3456-B0:
4567-B0: ca
I have a PowerShell script that sets flags based on various conditions of the file. I'll abbreviate for brevity.
$path = "c:\path"
$srcfiles = Get-ChildItem $path -filter *.htm*
ForEach ($doc in $srcfiles) {
$s = $doc.Fullname
Write-Host "Processing :" $doc.FullName
if (stuff) {flag 1 = 1} else {flag 1 = 0}
if (stuff) {flag 1 = 1} else {flag 1 = 0}
if (stuff) {flag 1 = 1} else {flag 1 = 0}
$t = "$s;$flag1;$flag2;$flag2"
Write-Host "Output: " $t
This all works great. My file processes, the flags are set properly, and a neat semicolon delimited line is generated as $t. However, if I slap these two lines at the end of the function,
$stream = [System.IO.StreamWriter] "flags.txt"
$stream.WriteLine $t
I get this error.
Unexpected token 't' in expression or statement.
At C:\CGC003a.ps1:53 char:25
+ $stream.WriteLine $t <<<<
+ CategoryInfo : ParserError: (t:String) [], ParseException
+ FullyQualifiedErrorId : UnexpectedToken
If I'm reading this write, it appears that write-host flushed my variable $t before it got to the WriteLine. Before I try out-file, though, I want to understand what's happening to $t after Write-Host that prevents Write Line from seeing it as valid. Or is there something else I'm missing?
try:
$stream.WriteLine($t)
writeline is a method of streamwriter .net object. To pass in value you need to enclose it in ( )
-if you need to append to a streamwriter you need to create it like this:
$a = new-object 'System.IO.StreamWriter' -ArgumentList "c:\path\to\flags.txt",$true
Where the boolean arguments can be true to append data to the file orfalse to overwrite the file.
I suggest to pass full path for:
$stream = [System.IO.StreamWriter] "c:\path\to\flags.txt"
otherwise you create the file in .net current folder ( probably c:\windows\system32 if run as administrator your current powershell console, to know it type [System.IO.Directory]::GetCurrentDirectory())
you could try
$t > c:\path\to\flags.txt
As part of debugging a problem that might be related to my UIVIews, I want to write a python script to run from LLDB. I had thought to extract all settings for a view in a breakpoint and all view children, to allow me to compare states. I checked out the WWDC video on the topic and then spent time reading things at lldb.llvm.org/scripting.html, and didn't find them very helpful. A web search for examples led to nothing substantially different from those.
My problem is that I'm trying to figure out how to access iOS variables at my breakpoint. The examples I've seen do things like convert numbers and mimic shell commands. Interesting stuff but not useful for my purposes. I've been reading my way through the help info with "script help(lldb.SBValue)" and the like, but it is slow going as the results are huge and it is not clear what the use patterns are. I feel like one decent example of how to traverse a few iOS objects would help me understand the system. Does anyone know of one or can share a snippet of code?
UPDATE:
I wrote this to help me track down a bug in my UIView use. I want to do a bit more work to refine this to see if I could show the whole view tree, but this was sufficient to solve my problem, so I'll put it here to save others some time.
import lldb
max_depth = 6
filters = {'_view':'UIView *', '_layer':'CALayer *', '_viewFlags':'struct'}
def print_value(var, depth, prefix):
""" print values and recurse """
global max_depth
local_depth = max_depth - depth
pad = ' ' * local_depth
name = var.GetName()
typ = str(var.GetType()).split('\n')[0].split('{')[0].split(':')[0].strip()
found = name in filters.keys() # only visit filter items children
if found:
found = (filters.get(name) == typ)
value = var.GetValue()
if value is None or str(value) == '0x00000000':
value = ''
else:
value = ' Val: %s' % value
if var.GetNumChildren() == 0 and var.IsInScope():
path = lldb.SBStream()
var.GetExpressionPath(path)
path = ' pathData: %s' % path.GetData()
else:
path = ''
print '^' * local_depth, prefix, ' Adr:', var.GetAddress(), ' Name:', name, ' Type:', typ, value, path
if var.GetNumChildren() > 0:
if local_depth < 2 or found:
print pad, var.GetNumChildren(), 'children, to depth', local_depth + 1
counter = 0
for subvar in var:
subprefix = '%d/%d' % (counter, var.GetNumChildren())
print_value(subvar, depth - 1, subprefix)
counter += 1
def printvh (debugger, command_line, result, dict):
""" print view hierarchy """
global max_depth
args = command_line.split()
if len(args) > 0:
var = lldb.frame.FindVariable(args[0])
depth = max_depth
if len(args) > 1:
depth = int(args[1])
max_depth = depth
print_value(var, depth, 'ROOT')
else:
print 'pass a variable name and optional depth'
And I added the following to my .lldbinit :
script import os, sys
# So that files in my dir takes precedence.
script sys.path[:0] = [os.path.expanduser("~/lldbpy")]
script import views
command script add -f views.printvh printvh
so that I can just type "printvh self 3" at the LLDB prompt.
Maybe this will help. Here's an example of how to dump simple local variables when a breakpoint is hit. I'm not displaying char* arrays correctly, I'm not sure how I should get the data for these to display it like "frame variable" would display it but I'll figure that out later when I have a free minute.
struct datastore {
int val1;
int val2;
struct {
int val3;
} subdata;
char *name;
};
int main (int argc, char **argv)
{
struct datastore data = {1, 5, {3}, "a string"};
return data.val2;
}
Current executable set to 'a.out' (x86_64).
(lldb) br se -l 13
Breakpoint created: 1: file ='a.c', line = 13, locations = 1
(lldb) br comm add -s python
Enter your Python command(s). Type 'DONE' to end.
> def printvar_or_children(var):
> if var.GetNumChildren() == 0 and var.IsInScope():
> path = lldb.SBStream()
> var.GetExpressionPath(path)
> print '%s: %s' % (path.GetData(), var.GetValue())
> else:
> for subvar in var:
> printvar_or_children(subvar)
>
> print 'variables visible at breakpoint %s' % bp_loc
> for var in frame.arguments:
> printvar_or_children(var)
> for var in frame.locals:
> printvar_or_children(var)
>
> DONE
(lldb) r
variables visible at breakpoint 1.1: where = a.out`main + 51 at a.c:13, address = 0x0000000100000f33, resolved, hit count = 1
argc: 1
*(*(argv)): '/'
data.val1: 1
data.val2: 5
data.subdata.val3: 3
*(data.name): 'a'
Process 84865 stopped
* thread #1: tid = 0x1f03, 0x0000000100000f33 a.out`main + 51 at a.c:13, stop reason = breakpoint 1.1
frame #0: 0x0000000100000f33 a.out`main + 51 at a.c:13
10 int main (int argc, char **argv)
11 {
12 struct datastore data = {1, 5, {3}, "a string"};
-> 13 return data.val2;
(lldb)
Tip - for sanity's sake I worked on the python over in a side text editor and pasted it into lldb as I experimented.
If you use the frame variable command in lldb to explore your variables at a given stop location, that's the same basic way that you can access them via the SBFrame that is provided to your breakpoint python command in the 'frame' object.
Hope that helps to get you started.
Did you try looking at the python LLDB formatting templates stored in:
XCode.app/Contents/SharedFrameworks/LLDB.framework/Resources/Python/lldb/formatters/objc
I there a way to ask password in lua but hide with asterisks?
I'm asking about a console application
For Unix: use os.execute("stty -echo raw") to turn off echoing and enter raw mode (character-by-character input) and os.execute("stty echo cooked") to turn it on and exit raw mode when you are done. In raw mode, you can get each character of the input using io.stdin:read(1) and echo your asterisk as you go (use io.flush to ensure the character appears straight away). You will need to handle deletes and the end of line yourself.
For Windows, the situation is a bit trickier. Look at What would be the Windows batch equivalent for HTML's input type=“password”? for some approaches, the best of which seems to be a VB script.
Postscript
Thanks for lhf for pointing out that you need raw mode besides -echo on input and flush after each output asterisk to get the desired result: unless you have both, the asteriskes will not be echoed until the line is ended.
This code uses platform-specific features and works both on Linux and 32-bit Windows.
Compatible with Lua 5.1 and Lua 5.2
local console
local function enter_password(prompt_message, asterisk_char, max_length)
-- returns password string
-- "Enter" key finishes the password
-- "Backspace" key undoes last entered character
if not console then
if (os.getenv'os' or ''):lower():find'windows' then
------------------ Windows ------------------
local shift = 10
-- Create executable file which returns (getch()+shift) as exit code
local getch_filespec = 'getch.com'
-- mov AH,8
-- int 21h
-- add AL,shift
-- mov AH,4Ch
-- int 21h
local file = assert(io.open(getch_filespec, 'wb'))
file:write(string.char(0xB4,8,0xCD,0x21,4,shift,0xB4,0x4C,0xCD,0x21))
file:close()
console = {
wait_key = function()
local code_Lua51, _, code_Lua52 = os.execute(getch_filespec)
local code = (code_Lua52 or code_Lua51) - shift
assert(code >= 0, getch_filespec..' execution failed')
return string.char(code)
end,
on_start = function() end,
on_finish = function() end,
backspace_key = '\b'
}
-------------------------------------------
else
------------------ Linux ------------------
console = {
wait_key = function()
return io.read(1)
end,
on_start = function()
os.execute'stty -echo raw'
end,
on_finish = function()
os.execute'stty sane'
end,
backspace_key = '\127'
}
-------------------------------------------
end
end
io.write(prompt_message or '')
io.flush()
local pwd = ''
console.on_start()
repeat
local c = console.wait_key()
if c == console.backspace_key then
if #pwd > 0 then
io.write'\b \b'
pwd = pwd:sub(1, -2)
end
elseif c ~= '\r' and #pwd < (max_length or 32) then
io.write(asterisk_char or '*')
pwd = pwd..c
end
io.flush()
until c == '\r'
console.on_finish()
io.write'\n'
io.flush()
return pwd
end
-- Usage example
local pwd = enter_password'Enter password: '
print('You entered: '..pwd:gsub('%c','?'))
print(pwd:byte(1,-1))
Bug in code, for at least linux implementation. Need to add 'and c ~= nil`:
elseif c ~= '\r' and #pwd < (max_length or 32) and c ~= nil then
I'd like to do the equivalent of:
foo=$(echo "$foo"|someprogram)
within lua -- ie, I've got a variable containing a bunch of text, and I'd like to run it through a filter (implemented in python as it happens).
Any hints?
Added: would really like to do this without using a temporary file
As long as your Lua supports io.popen, this problem is easy. The solution is exactly as you have outlined, except instead of $(...) you need a function like this one:
function os.capture(cmd, raw)
local f = assert(io.popen(cmd, 'r'))
local s = assert(f:read('*a'))
f:close()
if raw then return s end
s = string.gsub(s, '^%s+', '')
s = string.gsub(s, '%s+$', '')
s = string.gsub(s, '[\n\r]+', ' ')
return s
end
You can then call
local foo = ...
local cmd = ("echo $foo | someprogram"):gsub('$foo', foo)
foo = os.capture(cmd)
I do stuff like this all the time. Here's a related useful function for forming commands:
local quote_me = '[^%w%+%-%=%#%_%/]' -- complement (needn't quote)
local strfind = string.find
function os.quote(s)
if strfind(s, quote_me) or s == '' then
return "'" .. string.gsub(s, "'", [['"'"']]) .. "'"
else
return s
end
end
I stumbled on this post while trying to do the same thing and never found a good solution, see the code below for how I solved my issues. This implementation allows users to access stdin, stdout, stderr and get the return status code. A simple wrapper is called for simple pipe calls.
require("posix")
--
-- Simple popen3() implementation
--
function popen3(path, ...)
local r1, w1 = posix.pipe()
local r2, w2 = posix.pipe()
local r3, w3 = posix.pipe()
assert((r1 ~= nil or r2 ~= nil or r3 ~= nil), "pipe() failed")
local pid, err = posix.fork()
assert(pid ~= nil, "fork() failed")
if pid == 0 then
posix.close(w1)
posix.close(r2)
posix.dup2(r1, posix.fileno(io.stdin))
posix.dup2(w2, posix.fileno(io.stdout))
posix.dup2(w3, posix.fileno(io.stderr))
posix.close(r1)
posix.close(w2)
posix.close(w3)
local ret, err = posix.execp(path, unpack({...}))
assert(ret ~= nil, "execp() failed")
posix._exit(1)
return
end
posix.close(r1)
posix.close(w2)
posix.close(w3)
return pid, w1, r2, r3
end
--
-- Pipe input into cmd + optional arguments and wait for completion
-- and then return status code, stdout and stderr from cmd.
--
function pipe_simple(input, cmd, ...)
--
-- Launch child process
--
local pid, w, r, e = popen3(cmd, unpack({...}))
assert(pid ~= nil, "filter() unable to popen3()")
--
-- Write to popen3's stdin, important to close it as some (most?) proccess
-- block until the stdin pipe is closed
--
posix.write(w, input)
posix.close(w)
local bufsize = 4096
--
-- Read popen3's stdout via Posix file handle
--
local stdout = {}
local i = 1
while true do
buf = posix.read(r, bufsize)
if buf == nil or #buf == 0 then break end
stdout[i] = buf
i = i + 1
end
--
-- Read popen3's stderr via Posix file handle
--
local stderr = {}
local i = 1
while true do
buf = posix.read(e, bufsize)
if buf == nil or #buf == 0 then break end
stderr[i] = buf
i = i + 1
end
--
-- Clean-up child (no zombies) and get return status
--
local wait_pid, wait_cause, wait_status = posix.wait(pid)
return wait_status, table.concat(stdout), table.concat(stderr)
end
--
-- Example usage
--
local my_in = io.stdin:read("*all")
--local my_cmd = "wc"
--local my_args = {"-l"}
local my_cmd = "spamc"
local my_args = {} -- no arguments
local my_status, my_out, my_err = pipe_simple(my_in, my_cmd, unpack(my_args))
-- Obviously not interleaved as they would have been if printed in realtime
io.stdout:write(my_out)
io.stderr:write(my_err)
os.exit(my_status)
There is nothing in the Lua standard library to allow this.
Here is an in-depth exploration of the difficulties of doing bidirectional communication properly, and a proposed solution:
if possible, redirect one end of the stream (input or output) to a file. I.e.:
fp = io.popen("foo >/tmp/unique", "w")
fp:write(anything)
fp:close()
fp = io.open("/tmp/unique")
x = read("*a")
fp:close()
You may be interested in this extension which adds functions to the os and io namespaces to make bidirectional communication with a subprocess possible.
Aha, a possibly better solution:
require('posix')
require('os')
require('io')
function splat_popen(data,cmd)
rd,wr = posix.pipe()
io.flush()
child = posix.fork()
if child == 0 then
rd:close()
wr:write(data)
io.flush()
os.exit(1)
end
wr:close()
rd2,wr2 = posix.pipe()
io.flush()
child2 = posix.fork()
if child2 == 0 then
rd2:close()
posix.dup(rd,io.stdin)
posix.dup(wr2,io.stdout)
posix.exec(cmd)
os.exit(2)
end
wr2:close()
rd:close()
y = rd2:read("*a")
rd2:close()
posix.wait(child2)
posix.wait(child)
return y
end
munged=splat_popen("hello, world","/usr/games/rot13")
print("munged: "..munged.." !")
A not very nice solution that avoids a temporary file...
require("io")
require("posix")
x="hello\nworld"
posix.setenv("LUA_X",x)
i=popen('echo "$LUA_X" | myfilter')
x=i.read("*a")
Here is how I solved the problem, it require lua posix.
p = require 'posix'
local r,w = p.pipe()
local r1,w1 = p.pipe()
local cpid = p.fork()
if cpid == 0 then -- child reads from pipe
w:close()
r1:close()
p.dup(r, io.stdin)
p.dup(w1 ,io.stdout)
p.exec('./myProgram')
r:close()
w1:close()
p._exit(0)
else -- parent writes to pipe
IN = r1
OUT = w
end
During myProgram execution, you'l read and write from normal io and after this part of code you just have to write/read on IN and OUT to comunicate with child program.
For a system I have running Lua 5.1 and luaposix 35.0-1, I started with the solution from Anthony Towns from this current page and made it work for this luaposix version for the purpose of calling openssl for encryption on a system without any other encryption capabilities. I have attempted to make the code more explicit in order to allow others to handle any potential API changes in luaposix in the future.
local posix = require('posix');
require('os');
require('io');
local function getOutputFromProcessProvidedInput( dataForProcess, command, commandArguments )
local MAXIMUM_BYTE_READ_COUNT = 100;
local readFileHandle1,writeFileHandle1 = posix.pipe()
io.flush();
local childProcessId1 = posix.fork();
if (childProcessId1 == 0)
then
posix.close( readFileHandle1 );
posix.write( writeFileHandle1, dataForProcess );
io.flush();
os.exit( 1 );
end
posix.close( writeFileHandle1 );
local readFileHandle2,writeFileHandle2 = posix.pipe();
io.flush();
local childProcessId2 = posix.fork();
if (childProcessId2 == 0)
then
posix.close( readFileHandle2 );
posix.dup2( readFileHandle1, posix.fileno( io.stdin ) );
posix.dup2( writeFileHandle2, posix.fileno( io.stdout ) );
posix.execp( command, commandArguments );
os.exit( 2 );
end
posix.close( writeFileHandle2 );
posix.close( readFileHandle1 );
local dataFromProcess = posix.read( readFileHandle2, MAXIMUM_BYTE_READ_COUNT );
posix.close( readFileHandle2 );
posix.wait( childProcessId2 );
posix.wait( childProcessId1 );
return dataFromProcess;
end
-- Command being executed
-- echo -n AAAAAAAAAAAAAAAA | openssl aes-128-cbc -e -nopad -a -K 30313233343536373839616263646566 -iv 1FF1ECB9000000000000000000000000
-- Expected result
-- 28iudIC31lHfDDxfa1/g9w==
result = openReadWritePipe("AAAAAAAAAAAAAAAA","openssl",{"aes-128-cbc", "-e", "-nopad", "-a", "-K", "30313233343536373839616263646566", "-iv", "1FF1ECB9000000000000000000000000"});
print("Result: "..result);
It's easy, no extensions necessary (tested with lua 5.3).
#!/usr/bin/lua
-- use always locals
local stdin = io.stdin:lines()
local stdout = io.write
for line in stdin do
stdout (line)
end
save as inout.lua and do chmod +x /tmp/inout.lua
20:30 $ foo=$(echo "bla"| /tmp/inout.lua)
20:30 $ echo $foo
bla