Jump to content

No output from StdoutRead sometimes


RaduG
 Share

Recommended Posts

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

Link to comment
Share on other sites

[/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

Link to comment
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?

Link to comment
Share on other sites

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

Link to comment
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

Link to comment
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!

Link to comment
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?

Link to comment
Share on other sites

  • 5 years later...

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

 

 

image.jpeg.9f1a974c98e9f77d824b358729b089b0.jpeg Chimp

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

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...