Skript, mis pakib failid ja laeb ftp abil üles

From EIK wiki
Revision as of 22:26, 1 February 2013 by Htahis (talk | contribs) (PowerShell)

Skript

Mihkel Soomere (C)

Allpool on ka VBScript variant, millest PowerShell variant porditi. See skript on VBS variandis ühe spetsiiflise süsteemi logide edastamiseks mõeldud ja live's kasutuses, sellest tulenevalt ei ole see päris universaalne lahendus. Nt logide transpordiks ette valmistamisel on tähtis säilitada emakausta nimi.

PowerShell

<#
.Synopsis
YourView andmete pushija
Edastab YourView logifailid koos struktuuriga FTP'sse kokku Zipituna
Porditud VBS versioonist
Alustatud detsember 2012
Autor Mihkel Soomere
.DESCRIPTION
Skript vajab Zippimiseks: http://pscx.codeplex.com ja  FTP laadimiseks http://gallery.technet.microsoft.com/scriptcenter/PowerShell-FTP-Client-db6fe0cb
Testitud PS3 ja W8 peal
ToDo
Kui FTP ebaõnnestus, siis pane fail Queuesse. Järgmisel käivitusel laadi queue failid üles.
.EXAMPLE
YourViewPush.ps1 TallinnHarku
Kasutab jaama nimena TallinnHarku.
.INPUTS
Ainus atribuut on jaama nimi, mis peab koosnema A-Z, a-z, 0-9 märkidest
#>

 Param (
    [parameter(Mandatory=$true,HelpMessage="Jaama nimes tohib olla sümboleid a-z ja numbreid 0-9")]
    [ValidatePattern("^[0-9a-zA-Z]+$")]
    [String] $JaamaNimi
) 
#Lülida debugimine sisse
#$DebugPreference = "Continue"

#Debug
Write-Debug ("args.Count " + $args.Count)
Write-Debug ("args " + $args)

#Logimise käivitamine
$LogFile = $env:TEMP + "\YWPushLog.txt"
Function LogWrite {
   Param ([string]$logstring)
   Write-Host $logstring
   Add-content $Logfile -value ((Get-Date -format "dd.MM.yyyy HH:mm").ToString() + " " + $logstring)
}

#Debug
Write-Debug ("LogFile " + $LogFile)

#Parameetrite arvu kontroll
#If ($args.Count -ne 1) {
#    LogWrite ("Viga 6! Puudu käsurea argument määramaks jaama nimi või liiga palju parameetreid")
#    Exit 6
#}

#Parameetri valideerimine
#foreach ($char in $args[0].ToString().GetEnumerator()) {
#    if (![System.Char]::IsLetterOrDigit($char)) {
#        LogWrite ("Viga 7! Jaama nimi ei ole a-z,A-Z,0-9")
#        Exit 7
#    }
#}

#Muutujate väärtustamine
#Muutumatu, kuna igal pool sama
$YourViewJuurkaust = "C:\YourView"
#Argumendist
$Jaamanimi = $args[0].ToString()
#Kujul YYYYMMDD
$KuuPaev = (Get-Date -Format "yyyyMMdd").ToString()
#Alati jäetakse natuke logisid maha
$MaxFailivanus = 3
$YlekandeKaust = ($Jaamanimi + "-" + $KuuPaev)
$AjutineJuurkaust = ($YourViewJuurkaust + "\" + $YlekandeKaust)
$YlekantavFailiNimi = ($YlekandeKaust + ".zip")
#Implementeerimata
$TeadaolevadKaustad = "CT","FD","PTU","SR","TG","WA","WIND","CT25K","FD12P","PTU_INST","SR_INST","TG_INST"
$FTPServer = ""
$FTPServerTee = ""
$FTPServerKasutaja =""
#Enamvähem turvaline paroolisalvestusviis, et skript ei küsiks FTPga üles laadides parooli
#Parooli salvestamiseks read-host -assecurestring | convertfrom-securestring | out-file C:\yourview\securestring.txt
$FTPServerParool = cat C:\yourview\securestring.txt | convertto-securestring

#Debug
Write-Debug ("YourViewJuurKaust " + $YourViewJuurKaust)
Write-Debug ("JaamaNimi " + $Jaamanimi)
Write-Debug ("KuuPaev " + $KuuPaev)
Write-Debug ("MaxFailiVanus " + $MaxFailivanus)
Write-Debug ("YlekandeKaust " + $YlekandeKaust)
Write-Debug ("AjutineJuurkaust " + $AjutineJuurkaust)
Write-Debug ("YlekantavFailiNimi " + $YlekantavFailiNimi)
Write-Debug ("TeadaolevadKaustad " + $TeadaolevadKaustad)

#Liigutab failid koos emakaustaga
Get-ChildItem $YourViewJuurkaust -Directory | ForEach-Object {
    Write-Debug ("YourViewChild " + $_.FullName)
    Get-ChildItem $_.FullName -Recurse | Where-Object {-not $_.PsIsContainer -and $_.LastWriteTime -lt (Get-Date).AddDays(-$MaxFailivanus) -and $_.Extension -eq ".csv"} | ForEach-Object {
        $Destination = ($AjutineJuurkaust + "\" + $_.Directory.Name + "\" + $_.Name)
        #Debug
        Write-Debug ("Source " + $_.FullName)
        Write-Debug ("Destination " + $Destination)
        #Workaround, kuna Move-Item ei loo faili liigutamisel pathi ette
        New-Item -ItemType Directory -Path ($AjutineJuurkaust + "\" + $_.Directory.Name) -Force
        Move-Item $_.FullName -Destination $Destination -Force
    }
}

#Pakib failid kokku
Try{
    Write-Zip -Level 9 -IncludeEmptyDirectories -Path ($YourViewJuurkaust + "\" + $YlekandeKaust) -OutputPath ($YourViewJuurkaust + "\" + $YlekantavFailiNimi)
}
Catch [system.exception] {
    LogWrite ("Viga 4! Pakkimine ebaõnnestus")
    Exit 4
}

#Edastab ZIPi FTP'ga
Try {
    #Creadential objekti on vaja, ses muidu ei saa kuidagi parooli ette anda
    $Credential = new-object -typename System.Management.Automation.PSCredential -argumentlist $FTPServerKasutaja,$FTPServerParool
    Set-FTPConnection -Credentials $Credential -Server $FTPServer -UseBinary -UsePassive
    Add-FTPItem -Path $FTPServerTee -LocalPath ($YourViewJuurkaust + "\" + $YlekantavFailiNimi) -Overwrite
}
Catch [system.exception] {
    LogWrite ("Viga 5! FTP Edastamine ebaõnnestus")
    Exit 5
}

#Kustuta ZIP
Remove-Item ($YourViewJuurkaust + "\" + $YlekantavFailiNimi)
#Kustuta ajutine kaust
Remove-Item ($YourViewJuurkaust + "\" + $YlekandeKaust) -Recurse

#Exit
LogWrite ("Kõik OK!")
Write-Debug "0"
Exit 0

VBScript

'YourView andmete pushija.
'Alustas Mihkel Soomere augustis 2011.
'Skripti mõte on transportida minutiandmed automaatselt peamajja objektidel, kus pole püsiühendust ega VPNi.
'Sõltuvused on 7-zip ja ncftpput.
'Skript eeldab, et ta leiab asjad määratud kaustadest.
'st 7-zip peab olema arhitektuuripõhine, ncftpput võib olla ka 32b, sest see läheb system32'te
'Testitud Windows 7 peal, kuid peaks töötama kõige peal alates Windows 2000.

'Kasutamine
'Kopeeri skript ja ncftpput windows\system32 kausta
'Kontorlli, et 7-zip oleks sama, mis operatsioonissüsteemi arhitektuur (alati %programfiles% variable)
'Lisa Task Scheduleri
'Kasutajaks SYSTEM
'Käivita parameetriga jaama nimi.
'Käivita igal pühapäeval kell 00 (üldjuhul UTC)
'Jaama nimi peaks olema ASCII märkidega ja kõik kokku, nt narvajoesuu


'Workflow:
'Loo ajutine kaust mis koosneb arvuti nimest ja kuupäevast
'Liiguta määratud ajast vanem sisu YW põhikaustadest ajutisse kausta
'Paki ajutine kaust kokku
'Saada pakitud info ära
'Kustuta ajutised asjad
'Kui midagi vahepeal feilib, skript väljub
'Järgmise käivituse ajal korjab see kokku ka eelmisest käivitusest üle jäänud sodi, pakib selle uuesti kokku ning üritab uuesti ära saata

'Muudatused
'1.1
'CURL vahetatud ncfptput vastu, muutujad jäävad samaks.
'Failid luuakse argumendist võetava failinimega, lisatud kiire väljumine koodiga 6 argumendi puudumisel
'Logifunktsioon varasemaks toodud, et kontrollida argumendi puudumist
'1.2
'Muudetud saadetavate failide nimekuju kujule YYYYMMDD
'Lisatud koristaja
'1.2a
'Välja lülitatud vigane kustutaja

'Karm režiim, nõua muutujate defineerimist, aitab debugimisel
Option Explicit


'Muutujate loomine
Dim LogFile, Shell, FileSystemObject, RootFolder, SourceFolder, SourceFolderSubfolder, TransferRootFolder, TransferFile, CreateFolderPath, TransferPath, FileAge, FTPServer, FTPServerUser, FTPServerPassword, SevenZipPath, CURLPath, ComputerName, WshNetwork, FileItem, FTPServerPath, SevenZipExec, i, Run7Zip, LogFileAccess, CURLExec, RunCURL, CleanupFolder, FolderArray, FolderEntry, IsKnownFolder

'Objektide loomine
Set Shell = CreateObject("WScript.Shell")
Set FileSystemObject = CreateObject("Scripting.FileSystemObject")
Set WshNetwork = WScript.CreateObject("WScript.Network")

'Initsialiseeri logi
'Logifail
LogFile = Shell.ExpandEnvironmentStrings("%TEMP%") & "\YWPushLog.txt"
'Logi funktsioon
Set LogFile = FileSystemObject.OpenTextFile(LogFile,8,True)

'Atribuudi olemasolu kontroll
If WScript.Arguments.Count < 1 Then
	LogFile.WriteLine Now() & " Kriitiline viga! Puudu käsurea argument määramaks jaama nimi. Errorcode: 6"
	WScript.quit(6)
end If

'Muutujate määramine
'See on hardcodetud, kuna YourView path on igalpool sama.
Set RootFolder = FileSystemObject.GetFolder("C:\YourView")
'Määrab saatmise kausta tee ja faili
'Muudatus versioonis 1.1
'Algses skrptis kasutati faili jaoks arvuti nime, selletõttu on muutuja ikka ComputerName, kuigi tema sisu on muutunud.
ComputerName = WScript.Arguments.Item(0)
TransferRootFolder = RootFolder & "\" & ComputerName & "-" & Date()
TransferFile = ComputerName & "-" & Year(Date) & Right("0" & Month(Date),2) & Right("0" & Day(Date),2) & ".zip"
'1.2 lisand - eeldatavate kaustade massiiv
FolderArray = Array("CT","FD","PTU","SR","TG","WA","WIND","CT25K","FD12P","PTU_INST","SR_INST","TG_INST")
'Rohkem kui järgnev arv päevi vanad failid võetakse töötlusse
FileAge = 3
'FTP ligipääsu andmed
FTPServer = ""
FTPServerPath = ""
FTPServerUser = ""
FTPServerPassword = ""
'Väliste rakenduste pathid
SevenZipPath = Shell.ExpandEnvironmentStrings("%ProgramFiles%") & "\7-Zip\7z.exe"
'Muudatus versioonis 1.1
'CURL viitab tegelikult ncftpput'ile
CURLPath = FileSystemObject.GetSpecialFolder(1) & "\ncftpput.exe"


'Kontrolli kas YourView kaust on olemas
If Not FileSystemObject.FolderExists(RootFolder) Then
	LogFile.WriteLine Now() & " Kriitline viga! Puudu järgnev oluline kaust: " & RootFolder & " Variable: RootFolder Errorcode: 1"
	WScript.quit(1)
End If
'Kontrolli kas 7-Zip on olemas
If Not FileSystemObject.FileExists(SevenZipPath) Then
	LogFile.WriteLine Now() & " Kriitiline viga! Puudu järgnev oluline fail: " & SevenZipPath & " Variable: SevenZipPath Errorcode: 2"
	WScript.quit(2)
End If
'Kontrolli kas CURL on olemas
If Not FileSystemObject.FileExists(CURLPath) Then
	LogFile.WriteLine Now() & " Kriitiline viga! Puudu järgnev oluline fail: " & CURLPath & " Variable: CURLPath Errorcode: 2"
	WScript.quit(3)
End If


'Loo edastamise kaustastruktuuur ja liiguta andmed
If Not FileSystemObject.FolderExists(TransferRootFolder) Then
	Set CreateFolderPath = FileSystemObject.CreateFolder(TransferRootFolder)
End If
For Each SourceFolder in RootFolder.SubFolders
	'Jäta vahele edastuskaust ise
	If Not SourceFolder = TransferRootFolder Then
		TransferPath = TransferRootFolder & "\" & SourceFolder.Name
		If Not FileSystemObject.FolderExists(TransferPath) Then
			Set CreateFolderPath = FileSystemObject.CreateFolder(TransferPath)
		End If
		For Each FileItem in SourceFolder.Files
			If DateDiff("d",FileItem.DateLastModified,Now()) > FileAge Then
				FileSystemObject.MoveFile SourceFolder & "\" & FileItem.Name , TransferPath & "\" & FileItem.Name
			End If
		Next
	End If
Next


'Paki andmed kokku 7Zip kasutades. See loopib et vea korral uuesti proovida
'Määra käsurea parameetrid
SevenZipExec = chr(34) & SevenZipPath & chr(34) & " a -tzip " & chr(34) & TransferRootFolder & "\" & TransferFile & chr(34) & " " & chr(34) & TransferRootFolder & chr(34)
'Nulli tsüklikordaja
i=0
'Käivita tsükkel 3 korda
Do While (i<3)
	'Käivita peidetuna ning oota käivituse lõppu.
	Run7Zip = Shell.Run(SevenZipExec,0,True)
	'Kui pakkimine õnnestus, välju tsüklist
	If (Run7Zip = 0) Then Exit Do
	'Kui 3 korda proovitud, kirjuta logisse ning välju skriptist veakoodiga 4
	'Jäta vahele andmete saatmine, kui seda pole niikuinii pakitud
	If (i = 2) Then
		LogFile.WriteLine Now() & " Fataaalne viga pakkimisel! Proovitud 3 korda pakkida. Errorcode 4 ReturnCode: " & Run7Zip & " SevenZipExec: " & SevenZipExec
		WScript.quit(4)
	End If
	'Kui oli viga, siis kirjuta ReturnCode ja käivitatud käsurida logisse
	If Not (Run7Zip = 0) Then LogFile.WriteLine Now() & " Viga pakkimisel! Proovin uuesti. ReturnCode: " & Run7Zip & " SevenZipExec: " & SevenZipExec
	'Suurenda tsüklikordajat
	i = i+1
	'Oota 10 minutit
	WScript.Sleep 600000
Loop


'Edasta andmed CURL kasutades. See loopib et vea korral uuesti proovida
'Määra käsurea parameetrid
'Muudatus versioonis 1.1
'Parameetrid on ncftpput jaoks
CURLExec = chr(34) & CURLPath & chr(34) & " -u " & FTPServerUser & " -p " & Base64Decode(FTPServerPassword) & " -T . " & FTPServer & " " & FTPServerPath & " " & chr(34) & TransferRootFolder & "\" & TransferFile & chr(34)
'Nulli tsüklikordaja
i=0
'Käivita 10 korda
Do While (i<10)
	'Käivita peidetuna ning oota käivituse lõppu.
	RunCURL = Shell.Run(CURLExec,0,True)
	'Kui pakkimine õnnestus, välju tsüklist
	If (RunCURL = 0) Then Exit Do
	'Kui 10 korda proovitud, kirjuta logisse ning välju skriptist veakoodiga 5
	If (i = 9) Then
		LogFile.WriteLine Now() & " Fataaalne viga saatmisel! Proovitud 10 korda saata. Errorcode 5 ReturnCode: " & RunCURL & " CURLExec: " & CURLExec
		WScript.quit(5)
	End If
	'Kui oli viga, siis kirjuta ReturnCode ja käivitatud käsurida logisse
	If Not (RunCURL = 0) Then LogFile.WriteLine Now() & " Viga saatmisel! Proovin uuesti. ReturnCode: " & RunCURL & " CURLExec: " & CURLExec
	'Suurenda tsüklikordajat
	i = i+1
	'Oota 10 minutit
	WScript.Sleep 600000
Loop
'Kui kõik ikkagi õnnestus kirjuta logisse maha
LogFile.WriteLine Now() & " Kõik OK!"

'Eemalda edastatud andmed
FileSystemObject.DeleteFolder TransferRootFolder
'Korista ära ja välju ilma veata
'Lisa 1.2
'Loopib läbi kõik kaustad ning võrdleb neid teadaolevate kaustadega - kui kaust pole teadaolev, kustuta.
'Lisa 1.2a
'Kustutaja välja lülitatud, kuna mõned kaustad teadmata põhjusel kustutatakse valesti
'For Each CleanupFolder in RootFolder.SubFolders
'	IsKnownFolder=False
'	For Each FolderEntry in FolderArray
'		If CleanupFolder = "C:\YourView\" & FolderEntry Then
'			IsKnownFolder=True
'		End If
'	Next
'	If IsKnownFolder = False Then
'		FileSystemObject.DeleteFolder CleanupFolder
'	End If
'Next
WScript.quit()

'Väline libra Base64 dekodeerimiseks
Function Base64Decode(ByVal base64String)
  Const Base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
  Dim dataLength, sOut, groupBegin
  base64String = Replace(base64String, vbCrLf, "")
  base64String = Replace(base64String, vbTab, "")
  base64String = Replace(base64String, " ", "")
  dataLength = Len(base64String)
  If dataLength Mod 4 <> 0 Then
    Err.Raise 1, "Base64Decode", "Bad Base64 string."
    Exit Function
  End If
  For groupBegin = 1 To dataLength Step 4
    Dim numDataBytes, CharCounter, thisChar, thisData, nGroup, pOut
    numDataBytes = 3
    nGroup = 0
    For CharCounter = 0 To 3
      thisChar = Mid(base64String, groupBegin + CharCounter, 1)
      If thisChar = "=" Then
        numDataBytes = numDataBytes - 1
        thisData = 0
      Else
        thisData = InStr(1, Base64, thisChar, vbBinaryCompare) - 1
      End If
      If thisData = -1 Then
        Err.Raise 2, "Base64Decode", "Bad character In Base64 string."
        Exit Function
      End If
      nGroup = 64 * nGroup + thisData
    Next
    nGroup = Hex(nGroup)
    nGroup = String(6 - Len(nGroup), "0") & nGroup
    pOut = Chr(CByte("&H" & Mid(nGroup, 1, 2))) + _
      Chr(CByte("&H" & Mid(nGroup, 3, 2))) + _
      Chr(CByte("&H" & Mid(nGroup, 5, 2)))
    sOut = sOut & Left(pOut, numDataBytes)
  Next
  Base64Decode = sOut
End Function