Sign in to follow this  
Followers 0
RaduG

No output from StdoutRead sometimes

17 posts in this topic

Hello,

I've been searching for a solution for this problem but I didn't find it so far.

What I'm trying to do is to run a command through SSH on multiple machines on a regular basis, then process the output of that command. And I've noticed that sometimes I got no output at all from running plink.

I think the problem is down to the way I do Run() or the way I do StdoutRead(). Or maybe there's a bug in AutoIt. Attached, there's a small script where for me the problem is always reproducible. At least, for me.

It doesn't matter if the binary you run is plink, or 7z, or whatever command that always gives some output. If you run it in the attached script for, let's say 100 times, all is fine. But if you run it for many times (eg: 2000), sometimes you will get no output. You can see that if you search for "Error" in the log file.

Any ideas on how to solve this issue? Until now I did a silly workaround: if I don't have any output, I repeat the command until I get something :graduated:

testplink.au3

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

[/autoit]I have try your plink like this succesfully ! [img]http://www.autoitscript.com/forum/public/style_emoticons/autoit/wink.gif[/img]

[autoit]

#include <Constants.au3>

$_ExePath = @ScriptDir & '\plink.exe'
$_Run = @ComSpec & ' /c ' & FileGetShortName ( $_ExePath ) & ' -V'
ConsoleWrite ( '-------- $_Run : ' & $_Run & @Crlf )    
$_Pid = Run ( $_Run, '', @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD )
Dim $_StderrRead='', $_StdoutRead=''

While ProcessExists ( $_Pid ) 
    $_StderrRead = StderrRead ( $_Pid )
    If Not @error And $_StderrRead <> '' Then ConsoleWrite ( "!------- STDERR read : " & $_StderrRead & @Crlf ) 
    $_StdoutRead = StdoutRead ( $_Pid )
    If Not @error And $_StdoutRead <> '' Then ConsoleWrite ( "+------- STDOUT read : " & $_StdoutRead & @Crlf ) 
Wend

STDOUT read : plink: Release 0.60

but nothing with your script...

Edit : I have found the solution : suppress the sleep (10 ) ! Posted Image

#Include <Date.au3>
#include <Constants.au3>
AutoItSetOption ("ExpandEnvStrings", 1)
$runningexe="plink"
$logfilename="%userprofile%\logging.log"
$logfile = FileOpen($logfilename,1)
If $logfile = -1 Then Exit MsgBox (16, "Error", "Can't open " & $logfilename & " for writing")

check_command()

Func _getDOSOutput($command)
    Local $text = ''
    $Pid = Run($command, '',  $STDOUT_CHILD)
    While 1
        $text &= StdoutRead($Pid)
        If @error Then ExitLoop
    WEnd
    Return $text
EndFunc

Func logging($line)
    If FileWrite($logfile, _NowTime() & "  " & $line & @CRLF) = 0 Then _
    Exit MsgBox (16, "Error", "Can't log to " & $logfilename)
EndFunc

Func check_command()
    Local $results = _getDOSOutput($runningexe & " -V")
    logging("Results: " & $results)
    If $results = "" Then logging("Error: no results")
EndFunc
Edited by wakillon

AutoIt 3.3.14.2 X86 - SciTE 3.6.0WIN 8.1 X64 - Other Example Scripts

Share this post


Link to post
Share on other sites

Thanks a lot for your reply!

I have tried without the sleep and I got more empty results than without the sleep :graduated:

But I will try like you did and see if it helps.

Share this post


Link to post
Share on other sites

The sleep interfere for get the output !

Glad to help you


AutoIt 3.3.14.2 X86 - SciTE 3.6.0WIN 8.1 X64 - Other Example Scripts

Share this post


Link to post
Share on other sites

OK, I've tried again without the sleep and I get much more blank outputs.

Then I tried something similar to what you did. Here's what's changed (the rest of the code is the same):

Func _getDOSOutput($command)
    Local $text = ''
    Local $_StderrRead='', $_StdoutRead=''
    $Pid = Run($command, '', @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD)
    While ProcessExists($Pid)
        $_StderrRead = StderrRead ( $Pid )
        If Not @error And $_StderrRead <> '' Then $text &= $_StderrRead
        $_StdoutRead = StdoutRead ( $Pid )
        If Not @error And $_StdoutRead <> '' Then $text &= $_StdoutRead
    WEnd
    Return $text
EndFunc

And in this case I also get tons of blank outputs. Do you have other suggestions?

Unfortunately, I don't really understand how this Std*Read thing works. I've searched the web but I didn't get much information. Can you tell me about this function? Something that's not written in the help file?

Share this post


Link to post
Share on other sites

Try

Return StringStripWS ( $text, 7 ) Posted Image


AutoIt 3.3.14.2 X86 - SciTE 3.6.0WIN 8.1 X64 - Other Example Scripts

Share this post


Link to post
Share on other sites

Thanks for the suggestion.

I've tried, but unfortunately I get the same results.

Share this post


Link to post
Share on other sites

Thanks for the suggestion.

I've tried, but unfortunately I get the same results.

Can you give me your $command ?

I will try by my side...Posted Image


AutoIt 3.3.14.2 X86 - SciTE 3.6.0WIN 8.1 X64 - Other Example Scripts

Share this post


Link to post
Share on other sites

Can you give me your $command ?

I will try by my side...Posted Image

Sure. It's "plink -V". But you can try with any other executable, as I said in my first post. You can use the script from the first post to reproduce the issue.

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

Sure. It's "plink -V". But you can try with any other executable, as I said in my first post. You can use the script from the first post to reproduce the issue.

I thinked you use a different command line switch ...

So, i try like this and it works fine ! Posted Image

without spaces...

#Include <Date.au3>
#include <Constants.au3>

Global $runningexe=@ScriptDir &'\plink.exe'
Global $logfilename='c:\logging.log'
Global $logfile = FileOpen($logfilename,1)
If $logfile = -1 Then Exit MsgBox (16, "Error", "Can't open " & $logfilename & " for writing")

check_command()

Func _getDOSOutput ( $command )
    Local $text = ''
    ConsoleWrite ( "---->--- $command : " & $command & @Crlf )  
    $Pid = Run ( $command, '', @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD) 
    While ProcessExists ( $Pid )
        If Not @error Then $text &= StdoutRead($Pid)
    WEnd
    ConsoleWrite ( "+--->--- STDOUT read : " & $text & @Crlf )  
    Return $text
EndFunc

Func logging($line)
    If FileWrite($logfile, _NowTime() & "  " & $line & @CRLF) = 0 Then Exit MsgBox (16, "Error", "Can't log to " & $logfilename)
EndFunc

Func check_command()
    Local $results = _getDOSOutput ( @ComSpec & ' /c ' & FileGetShortName ( $runningexe ) & " -V" ) ; $_Run = @ComSpec & ' /c ' & FileGetShortName ( $_ExePath ) & ' -V'
    logging("Results: " & $results)
    If $results = "" Then logging("Error: no results")
EndFunc
Edited by wakillon

AutoIt 3.3.14.2 X86 - SciTE 3.6.0WIN 8.1 X64 - Other Example Scripts

Share this post


Link to post
Share on other sites

This works for me as well, if I only run the command once. But try to do the same thing in a loop for 2000 times. In this case for me it often returns an empty output. Not every time, but quite a lot.

Share this post


Link to post
Share on other sites

This works for me as well, if I only run the command once. But try to do the same thing in a loop for 2000 times. In this case for me it often returns an empty output. Not every time, but quite a lot.

Perhaps your loop is too fast, try like this :

#Include <Date.au3>
#include <Constants.au3>

Global $runningexe=@ScriptDir &'\plink.exe'
Global $logfilename='c:\logging.log'
Global $logfile = FileOpen($logfilename,1)
HotKeySet ( "{ESC}", "Terminate" )

If $logfile = -1 Then Exit MsgBox (16, "Error", "Can't open " & $logfilename & " for writing")
$_TimerInit = TimerInit ( )

While 1
   If _EachXseconds ( 2 ) Then check_command ( )
   Sleep ( 10 )
WEnd

Func _getDOSOutput ( $command )
    Local $text = ''
    ConsoleWrite ( "---->--- $command : " & $command & @Crlf )  
    $Pid = Run ( $command, '', @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD) 
    While ProcessExists ( $Pid )
        If Not @error Then $text &= StdoutRead($Pid)
    WEnd
    ConsoleWrite ( "+--->--- STDOUT read : " & $text & @Crlf )  
    Return $text
EndFunc

Func logging($line)
    If FileWrite($logfile, _NowTime() & "  " & $line & @CRLF) = 0 Then Exit MsgBox (16, "Error", "Can't log to " & $logfilename)
EndFunc

Func check_command()
    Local $results = _getDOSOutput ( @ComSpec & ' /c ' & FileGetShortName ( $runningexe ) & " -V" ) ; $_Run = @ComSpec & ' /c ' & FileGetShortName ( $_ExePath ) & ' -V'
    logging("Results: " & $results)
    If $results = "" Then logging("Error: no results")
EndFunc

Func _EachXseconds ( $_Interval )
    $_TimerDiff = Round ( TimerDiff ( $_TimerInit )/ 1000 )
    If $_TimerDiff >= $_Interval Then
        $_TimerInit = TimerInit ( )
        Return 1
    Else
        Return 0
    EndIf
EndFunc ;==> _EachXseconds ( )

Func Terminate ( )
    FileClose ( $logfile )
    Exit 
EndFunc

AutoIt 3.3.14.2 X86 - SciTE 3.6.0WIN 8.1 X64 - Other Example Scripts

Share this post


Link to post
Share on other sites

Perhaps your loop is too fast, try like this :

Thanks for the suggestion! Until now I didn't realize that even though I'm running plink quite rarely in the original script (more than 1 minute intervals), I am actually running it on multiple computers in a for loop. So yes, that one is probably too fast.

I'll slow it down and let you know of the results.

Thanks a lot for all your suggestions!

Share this post


Link to post
Share on other sites

I've just tried with one and two second timeouts between each command, and I still get the same problem. After about 130-150 runs, it starts giving no results sometimes.

I remember trying this before posting here, but I've just tried again now to make sure I didn't miss something.

So you think there's a possibility that a bug exists in StdoutRead?

Share this post


Link to post
Share on other sites

#15 ·  Posted (edited)

I have a similar problem now.

Did you find a solution?

Thanks in advance.

Edited by MBrand

Share this post


Link to post
Share on other sites

Userprofile says: Last visited: 30 Nov 2010.

Share this post


Link to post
Share on other sites

MBrand

Perhaps the problem is due on how stdoutread is used on that listing, (two consecutive  wrong way of use in one shot)
On the above listing, stdoutread is executed when Process is still running and when there is no @error.
Now, first wrong way of use:  If the process terminates just a moment before the Wend  instruction is executed, it happens that the loop is ended before the stdoutread instruction is performed, causing the lost  of the data on the output.
Also,second wrong way of use: if you are lucky and you remain inside the while - wend loop, you can get into a second issue, that is: The @error used like that, should never rised, so the stdoutread is performed anyway on each loop, so the "if not @error" statement is suprfluous.

in short the right way to use the stdoutread should be like this:

Func _getDOSOutput ( $command )
    Local $text = ''
    ConsoleWrite ( "---->--- $command : " & $command & @Crlf )  
    $Pid = Run ( $command, '', @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD)
    ;   
    ; -- read output using stdoutread
    Do
    $text &= StdoutRead($Pid)
    Until @error
    ; -------------------------------
    ;
    ConsoleWrite ( "+--->--- STDOUT read : " & $text & @Crlf )  
    Return $text
EndFunc

 


small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0