Unix style "tail -f" written in VBS.

Use this forum if you want to discuss a problem or ask a question related to a hMailServer beta release.
Post Reply
User avatar
SorenR
Senior user
Senior user
Posts: 3169
Joined: 2006-08-21 15:38
Location: Denmark

Unix style "tail -f" written in VBS.

Post by SorenR » 2019-06-25 13:32

In case someone need this functionality I found this ...

https://stujordan.wordpress.com/2012/09 ... -vbscript/

The download link triggered all the bells and whistles, so I took one for the community and here is the script. :mrgreen:

Remember to include drive and path of the file or it will simply just sit the and do nothing. CPU load wise it appears like it is not there :wink:

Code: Select all

'##############################################################################
'# Name: Tail.vbs
'# Description: Tail a file with follow
'# Version History:
'#
'# 1.0	Stuart Jordan	Script creation
'#
'##############################################################################

'Grab the path of the file to be tailed from the command line
Set args = WScript.Arguments
If WScript.Arguments.Count <> 1 Then
    WScript.echo vbCrLf
    WScript.echo "------------------------------------------------------------"
    WScript.echo "                   Tail.vbs syntax help                     "
    WScript.echo "------------------------------------------------------------"
    WScript.echo "You haven't correctly specified the filename to be tailed."
    WScript.echo vbCrLf
    WScript.echo "Syntax:"
    WScript.echo vbCrLf
    WScript.echo vbTab & "cscript /nologo tail.vbs c:\myfolder\myfilename.txt"
    WScript.echo vbCrLf
    WScript.echo "If there are spaces in your folder or filename please"
    WScript.echo "enclose the filename in double quotes"
    WScript.echo "------------------------------------------------------------"
    WScript.quit
End If
strLongFileName = args.Item(0)

arrArgsLine=Split(strLongFileName,"\")
strDrive=arrArgsLine(0)
If UBound(arrArgsLine)>1 Then
    For i=1 To UBound(arrArgsLine)-1
        strFolder=strFolder & "\\" & arrArgsLine(i)
    Next
    strFolder=strFolder & "\\"
End If
strFileName=arrArgsLine(UBound(arrArgsLine))

If strDrive = "" Or strFilename = "" Then
    WScript.echo "WARNING: Either the drive or filename was not specified. Please try again."
    WScript.quit
End If

WScript.echo vbCrLf
WScript.echo "----------------------------------------------------------------"
WScript.echo "This is the information that was detected:"
WScript.echo "Full path = " & strLongFileName
WScript.echo "Drive letter = " & strDrive
WScript.echo "File name = " & strFileName
WScript.echo "Folder path = " & strFolder
WScript.echo vbCrLf
WScript.echo "----------------------------------------------------------------"
WScript.echo vbCrLf

'This is the interval with which the WMI events are checked
intInterval = "2"
strComputer = "." 

intLastRunLineinFile=get_NumLinesInFile(strLongFileName)

Set objWMIService = GetObject( "winmgmts:" & _ 
"{impersonationLevel=impersonate}!\\" & _ 
strComputer & "\root\cimv2" )
If Len(strFolder) Then
    strQuery =  _
    "Select * From __InstanceOperationEvent" _
    & " Within " & intInterval _
    & " Where Targetinstance Isa 'CIM_DataFile'" _
    & " And TargetInstance.Drive='" & strDrive & "'" _
    & " And TargetInstance.Path='" & strFolder & "'"
Else
    strQuery =  _
    "Select * From __InstanceOperationEvent" _
    & " Within " & intInterval _
    & " Where Targetinstance Isa 'CIM_DataFile'" _
    & " And TargetInstance.Drive='" & strDrive & "\\'"
End If

Set colEvents = objWMIService. ExecNotificationQuery (strQuery) 
WScript.Echo "Monitoring events...[Ctl-C] to end"
Do 
    Set objEvent = colEvents.NextEvent()
    Set objTargetInst = objEvent.TargetInstance
    Select Case objEvent.Path_.Class 
        Case "__InstanceDeletionEvent" 
        If 0=StrComp(objTargetInst.Name,strLongFileName,1) Then
            WScript.echo objTargetInst.Name & " has been deleted. Exiting."
            WScript.quit
        End If
        Case "__InstanceModificationEvent" 
        If 0=StrComp(objTargetInst.Name,strLongFileName,1) Then
            tailFile(objTargetInst.Name)
        End If
    End Select 
Loop

Function tailFile(strFileName)
    Const FOR_READING = 1
    Dim intCurrLine,intNewNumLines
    Set objFSO   = WScript.CreateObject("Scripting.FileSystemObject")
    Set objFile = objFSO.OpenTextFile(strFileName, FOR_READING)
    
    intNewNumLines=0
    intCurrLine=0
    Do Until objFile.AtEndOfStream
        intCurrLine=intCurrLine+1
        If intCurrLine <= intLastRunLineinFile Then
            objFile.skipline
        Else
            WScript.echo objFile.ReadLine
            intNewNumLines=intNewNumLines+1
        End If
    Loop
    
    If intCurrLine < intLastRunLineinFile Then 
        'The number of lines on this scan was less than the last run so resetting the num lines in file
        intLastRunLineinFile = intCurrLine
    Else
        intLastRunLineinFile=intLastRunLineinFile+intNewNumLines
    End If
    'wscript.echo "(" & intLastRunLineinFile & ")"
    objFile.close
End Function

Function get_NumLinesInFile(strFileName)
    Const FOR_READING = 1
    Set objFSO   = WScript.CreateObject("Scripting.FileSystemObject")
    Set objFile = objFSO.OpenTextFile(strFileName, FOR_READING)
    intTotalNumLines=0
    Do Until objFile.AtEndOfStream
        objFile.skipline
        intTotalNumLines=intTotalNumLines+1
    Loop
    objFile.close
    get_NumLinesInFile=intTotalNumLines
End Function
SørenR.

The quantum rule of insecurity which states that the act of observing how vulnerable a host or service is changes the insecurity level of the service.

User avatar
SorenR
Senior user
Senior user
Posts: 3169
Joined: 2006-08-21 15:38
Location: Denmark

Re: Unix style "tail -f" written in VBS.

Post by SorenR » 2019-06-25 17:19

How to always use the current logfile on startup.

Delete this ...

Code: Select all

'Grab the path of the file to be tailed from the command line
Set args = WScript.Arguments
If WScript.Arguments.Count <> 1 Then
    WScript.echo vbCrLf
    WScript.echo "------------------------------------------------------------"
    WScript.echo "                   Tail.vbs syntax help                     "
    WScript.echo "------------------------------------------------------------"
    WScript.echo "You haven't correctly specified the filename to be tailed."
    WScript.echo vbCrLf
    WScript.echo "Syntax:"
    WScript.echo vbCrLf
    WScript.echo vbTab & "cscript /nologo tail.vbs c:\myfolder\myfilename.txt"
    WScript.echo vbCrLf
    WScript.echo "If there are spaces in your folder or filename please"
    WScript.echo "enclose the filename in double quotes"
    WScript.echo "------------------------------------------------------------"
    WScript.quit
End If
strLongFileName = args.Item(0)
And replace with this ...

Code: Select all

Dim oLog : Set oLog = CreateObject("hMailServer.Logging")
strLongFileName = oLog.CurrentDefaultLog
Set oLog = Nothing
SørenR.

The quantum rule of insecurity which states that the act of observing how vulnerable a host or service is changes the insecurity level of the service.

User avatar
jimimaseye
Moderator
Moderator
Posts: 8095
Joined: 2011-09-08 17:48

Re: Unix style "tail -f" written in VBS.

Post by jimimaseye » 2019-06-25 21:24

In addition: for those looking for a non vbs tailing program, i and some others also use this: https://www.baremetalsoft.com/baretail/ (free version is adequate).

Now you have choices.

[Entered by mobile. Excuse my spelling.]
HMS 5.6.6 B2383 on Win Server 2008 R2 Foundation, + 5.6.7-B2415 on test.
SpamassassinForWindows 3.4.0 spamd service
AV: Clamwin + Clamd service + sanesecurity defs : https://www.hmailserver.com/forum/viewtopic.php?f=21&t=26829

User avatar
SorenR
Senior user
Senior user
Posts: 3169
Joined: 2006-08-21 15:38
Location: Denmark

Re: Unix style "tail -f" written in VBS.

Post by SorenR » 2019-06-25 22:26

jimimaseye wrote:
2019-06-25 21:24
In addition: for those looking for a non vbs tailing program, i and some others also use this: https://www.baremetalsoft.com/baretail/ (free version is adequate).

Now you have choices.

[Entered by mobile. Excuse my spelling.]
I think you missed the obvious. It's not for eyeballing the log as it happens - I can use hMailAdmin for that ...
It's VBScript, it can monitor hMailServer log files in real-time and you can interact with hMailServer based on what is logged. Banning on failed logons or send a mail to admin if some debug event occurs.

The bonus is that you are not slowing the server down.
SørenR.

The quantum rule of insecurity which states that the act of observing how vulnerable a host or service is changes the insecurity level of the service.

User avatar
jimimaseye
Moderator
Moderator
Posts: 8095
Joined: 2011-09-08 17:48

Re: Unix style "tail -f" written in VBS.

Post by jimimaseye » 2019-06-25 23:27

SorenR wrote:
2019-06-25 22:26
I think you missed the obvious. It's not for eyeballing the log as it happens - I can use hMailAdmin for that ...
It's VBScript, it can monitor hMailServer log files in real-time and you can interact with hMailServer based on what is logged. Banning on failed logons or send a mail to admin if some debug event occurs.

The bonus is that you are not slowing the server down.
Indeed. Plenty of options and good stuff. (I simply posted the other for users who were looking for read only (tail type) thingy.)

[Entered by mobile. Excuse my spelling.]
HMS 5.6.6 B2383 on Win Server 2008 R2 Foundation, + 5.6.7-B2415 on test.
SpamassassinForWindows 3.4.0 spamd service
AV: Clamwin + Clamd service + sanesecurity defs : https://www.hmailserver.com/forum/viewtopic.php?f=21&t=26829

palinka
Senior user
Senior user
Posts: 986
Joined: 2017-09-12 17:57

Re: Unix style "tail -f" written in VBS.

Post by palinka » 2019-06-26 00:09

Could this be used to check if multiple rejections from the same IP within n seconds?

For example, if the same IP gets rejected by spamhaus 5 times within 30 seconds: I want to autoban.

User avatar
mattg
Moderator
Moderator
Posts: 20028
Joined: 2007-06-14 05:12
Location: 'The Outback' Australia

Re: Unix style "tail -f" written in VBS.

Post by mattg » 2019-06-26 00:59

I think that is where it is headed...

I can't wait to get some time to play, could possibly read the log in real time from eventhandlers.vbs, and then create some AutoBans. Currently I parse the log every five minutes with a scheduled task...
Just 'cause I link to a page and say little else doesn't mean I am not being nice.
https://www.hmailserver.com/documentation

User avatar
SorenR
Senior user
Senior user
Posts: 3169
Joined: 2006-08-21 15:38
Location: Denmark

Re: Unix style "tail -f" written in VBS.

Post by SorenR » 2019-06-26 07:59

palinka wrote:
2019-06-26 00:09
Could this be used to check if multiple rejections from the same IP within n seconds?

For example, if the same IP gets rejected by spamhaus 5 times within 30 seconds: I want to autoban.
That is what my IDS code does, sort of...

But yes, that was the idea.
SørenR.

The quantum rule of insecurity which states that the act of observing how vulnerable a host or service is changes the insecurity level of the service.

User avatar
SorenR
Senior user
Senior user
Posts: 3169
Joined: 2006-08-21 15:38
Location: Denmark

Re: Unix style "tail -f" written in VBS.

Post by SorenR » 2019-06-26 08:22

mattg wrote:
2019-06-26 00:59
I think that is where it is headed...

I can't wait to get some time to play, could possibly read the log in real time from eventhandlers.vbs, and then create some AutoBans. Currently I parse the log every five minutes with a scheduled task...
Not "could"... "is" reading the log in real-time. It sets a 2 second event timer in WMI so in any case log data is max 2 seconds "old".

I'm working on the basic set-up with switching logfile after midnight and making it more "modulized" for ease of programming.

I want it to be able to monitor the server 24/7 or easily used as a one-off to monitor for any event/logon and send a mail to admin.
SørenR.

The quantum rule of insecurity which states that the act of observing how vulnerable a host or service is changes the insecurity level of the service.

palinka
Senior user
Senior user
Posts: 986
Joined: 2017-09-12 17:57

Re: Unix style "tail -f" written in VBS.

Post by palinka » 2019-06-26 11:42

SorenR wrote:
2019-06-26 07:59
palinka wrote:
2019-06-26 00:09
Could this be used to check if multiple rejections from the same IP within n seconds?

For example, if the same IP gets rejected by spamhaus 5 times within 30 seconds: I want to autoban.
That is what my IDS code does, sort of...

But yes, that was the idea.
Right, but not in real time, correct? The scheduled task does the banning, i thought. I'll have to look at it again.

User avatar
SorenR
Senior user
Senior user
Posts: 3169
Joined: 2006-08-21 15:38
Location: Denmark

Re: Unix style "tail -f" written in VBS.

Post by SorenR » 2019-06-26 13:11

Proof-of-Concept code.

1: Hardcoded to look for hmailserver_<date>.log via COM API.
2: Added "__InstanceCreationEvent" Case from WMI ExecNotificationQuery to capture new logfile at midnight.
3: Will send email to postmaster@acme.inc (feel free to change) if mail arrive to unknown user.

Run with cscript /nologo log_tail.vbs

Code: Select all

Option Explicit

'******************************************************************************************************************************
'********** Configuration                                                                                            **********
'******************************************************************************************************************************
'
'   COM authentication
'
Private Const ADMIN = "Administrator"
Private Const PASSWORD = "VerySecretPassword"
'
'   Misc. settings
'
Private Const intInterval = "2" '   Event trigger interval in seconds.
Private Const strComputer = "." '   Nodename/Computer name
Private Const FOR_READING = 1

'******************************************************************************************************************************
'********** Functions                                                                                                **********
'******************************************************************************************************************************

Function tailFile(strFileName)
    Dim intCurrLine, intNewNumLines, strReadLine, arrReadLine
    Dim oFSO, oFile
    Set oFSO = WScript.CreateObject("Scripting.FileSystemObject")
    Set oFile = oFSO.OpenTextFile(strFileName, FOR_READING)
    intNewNumLines = 0
    intCurrLine = 0
    Do Until oFile.AtEndOfStream
        intCurrLine = intCurrLine + 1
        If intCurrLine <= intLastRunLineinFile Then
            oFile.skipline
        Else
            '
            '    THIS IS WHERE THE FUN BEGINS ==>
            '
            strReadLine = oFile.ReadLine
            WScript.echo strReadLine
            If (InStr(1, strReadLine, "SENT: 550 Unknown user", 1) > 0) Then
                With CreateObject("hMailServer.Message")
                    .AddRecipient "Postmaster", "postmaster@acme.inc"
                    .FromAddress = "postmaster@acme.inc"
                    .HeaderValue("To") = Chr(34) & "Postmaster" & Chr(34) & " <postmaster@acme.inc>"
                    .HeaderValue("From") = Chr(34) & "Postmaster" & Chr(34) & " <postmaster@acme.inc>"
                    .Subject = "Mail to unknown user"
                    .Body = strReadLine
                    .Save
                End With
            End If
            '
            '    ==> THIS IS WHERE THE FUN ENDS
            '
            intNewNumLines = intNewNumLines + 1
        End If
    Loop
    If intCurrLine < intLastRunLineinFile Then
        '   The number of lines on this scan was less than the last run so resetting the num lines in file
        intLastRunLineinFile = intCurrLine
    Else
        intLastRunLineinFile = intLastRunLineinFile + intNewNumLines
    End If
    oFile.close
    Set oFile = Nothing
    Set oFSO = Nothing
End Function

Function get_NumLinesInFile(strFileName)
    Dim intTotalNumLines
    Dim oFSO, oFile
    Set oFSO = WScript.CreateObject("Scripting.FileSystemObject")
    Set oFile = oFSO.OpenTextFile(strFileName, FOR_READING)
    intTotalNumLines = 0
    Do Until oFile.AtEndOfStream
        oFile.skipline
        intTotalNumLines = intTotalNumLines + 1
    Loop
    oFile.close
    Set oFile = Nothing
    Set oFSO = Nothing
    get_NumLinesInFile = intTotalNumLines
End Function

Function get_DefaultLogFileName(stdDrive, strFolder, strFileName)
    Dim oLog, i, arrArgsLine
    Set oLog = CreateObject("hMailServer.Logging")
    get_DefaultLogFileName = oLog.CurrentDefaultLog
    Set oLog = Nothing
    arrArgsLine = Split(get_DefaultLogFileName, "\")
    strDrive = arrArgsLine(0)
    If UBound(arrArgsLine) > 1 Then
        For i = 1 To UBound(arrArgsLine)-1
            strFolder = strFolder & "\\" & arrArgsLine(i)
        Next
        strFolder = strFolder & "\\"
    End If
    strFileName = arrArgsLine(UBound(arrArgsLine))
End Function

'******************************************************************************************************************************
'********** Main Code                                                                                                **********
'******************************************************************************************************************************

Dim oApp : Set oApp = CreateObject("hMailServer.Application")
Call oApp.Authenticate(ADMIN, PASSWORD)
Dim EventLog : Set EventLog = CreateObject("hMailServer.EventLog")

Dim strLongFileName, strDrive, strFolder, strFileName, strQuery, intLastRunLineinFile, colEvents
Dim oWMIService, oEvent, oTargetInst
Do
    '
    '   Read logfile
    '
    strLongFileName = get_DefaultLogFileName(strDrive, strFolder, strFileName)
    intLastRunLineinFile = get_NumLinesInFile(strLongFileName)
    '
    '   Build interface to WMI
    '
    strQuery = "Select * From __InstanceOperationEvent Within " & intInterval & _
               " Where Targetinstance Isa 'CIM_DataFile' And TargetInstance.Drive='" & strDrive & _
               "' And TargetInstance.Path='" & strFolder & "'"
    Set oWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
    Set colEvents = oWMIService.ExecNotificationQuery(strQuery)
    '
    '   Event management
    '
    Do
        Set oEvent = colEvents.NextEvent()
        Set oTargetInst = oEvent.TargetInstance
        Select Case oEvent.Path_.Class
            Case "__InstanceDeletionEvent"
            If 0 = StrComp(oTargetInst.Name, strLongFileName, 1) Then
                WScript.echo oTargetInst.Name & " has been deleted. Exiting."
                WScript.quit
            End If
            Case "__InstanceModificationEvent"
            If 0 = StrComp(oTargetInst.Name, strLongFileName, 1) Then
                tailFile(oTargetInst.Name)
            End If
            Case "__InstanceCreationEvent"
            If 0 = StrComp(Left(oTargetInst.Name, 12), Left(strLongFileName, 12), 1 ) Then
                WScript.echo oTargetInst.Name & " has been created. Loading new logfile."
            	 Exit Do
            End If
        End Select
    Loop
Loop
WScript.quit
Any further postings should be done in the Scripting forum. Yes?

https://www.hmailserver.com/forum/viewt ... 68#p212968
SørenR.

The quantum rule of insecurity which states that the act of observing how vulnerable a host or service is changes the insecurity level of the service.

Post Reply