delanguageRegister | Login
fingerprint

Login

call

Contact

help

Help

SCP: Send file to remote host

2 ratings
transfer filewindows to linuxscpposh-sshfilecopy

What it does

Kopiert von einem Windows System eine Datei via SCP zu einem Linux Host. In diesem PowerShell Script wird immer die letzte Datei (LastWriteTime) von einem vorher definierten Verzeichnis auf ein Linux System übertragen. Das Modus Posh-SSH wird verwendet.

Description

Sending a file to remote linux host via SCP. This resource takes the last file from a local folder and send it with SCP. Module POSH-SSH is required.

Creation Details

  • Author: Sebastian Renners
  • Created: 01.04.2021 12:26:47
  • Last modification: 22.04.2022 22:15:30
Resource Image:

Input Parameters

Name: remotehost

Description: Enter the remote linux host name (or IP) as a destination for the file copy.

Name: remoteusername

Description: Enter the ssh user for this remote linux host.

Name: remotepath

Description: Enter the remote directory path you want to copy the file in. Use the unix notation: "/home/example/".

Name: localpath

Description: Enter the local path you want to scan for the last file (sort by lastwritetime). Use the windows notation (C:\folder\)

Resource Parameters

No resource parameters set

Code

[CmdletBinding()]
Param(
    [Parameter(Mandatory=$false)]
    [string]$installPath="not-set",
    [Parameter(Mandatory=$false)]
    [string]$jobId="not-set",
    [Parameter(Mandatory=$false)]
    [string]$action="not-set"
)

$debugScript = 0;
if ($debugScript -eq 1) {
    $installPath = "C:\addy\" #Debugging
    $jobId = "jobXXXXXX" #only for debugging #

    function Write-Log2
    {
        [CmdletBinding()] 
        Param 
        ( 
            [Parameter(Mandatory=$true, 
            ValueFromPipelineByPropertyName=$true)] 
            [ValidateNotNullOrEmpty()] 
            [Alias("LogContent")] 
            [string]$Message, 
            [Parameter(Mandatory=$false)] 
            [ValidateSet("Error","Warn","Info")] 
            [string]$Level="Info"
        ) 
        write-host $Message
    }
}
#Only use TLSv1.1 and TLSv1.2
$AllProtocols = [System.Net.SecurityProtocolType]'Tls11,Tls12'
[System.Net.ServicePointManager]::SecurityProtocol = $AllProtocols


$errorCount = 0 #counting errors. If this variable is greater than 0, the script should not run
#loading functions #this is important!
write-host "$(get-date -f  "dd.MM.yyyy HH:mm:ss") include functions"
if (test-path "$($installPath)scripts\functions.global.ps1") {
    write-host "Functions-File exists"
    import-module "$($installPath)scripts\functions.global.ps1" -force
} else {
    write-host "Functions-File do not exist. Increasing ErrorCounter." 
    $errorCount++
}

#setting the location
set-location $installPath

#generate a unique machineID #this is important
$machineId = Get-MachineId
  
#write a log online and offline
if ($debugScript -eq 0) {
    write-log2 -Message "All parameter initialized"
}

#####Handling with parameters

if ($debugScript -eq 0) {
    ### Load parameter information about this job
    $jsonBody = @{ localCurrentTime = $(get-date -f  "dd.MM.yyyy HH:mm:ss")}
    $body = (ConvertTo-Json -Depth 4 $jsonBody) 
    $resultInitializeInvoke = Invoke-RestMethod -Uri "$addyhostaddress/api/v1/heartbeat-consumer?action=checkforjobs&jobId=$jobId" -Method POST -Body $body -ContentType 'application/json; charset=UTF-8' -Headers @{"Publickey"="$publickey";"Privatekey"="$privatekey";"Machineid" = "$machineId"} # -Headers @{'Authorization'='Basic YWRtaW46YWRtaW4'}
    $resultInitializeInvoke   
    #write-log2 -Message "Job details: $resultInitializeInvoke"

    ### Get all Parameter and payload details
    $resultInitializeInvoke.jobDataArray.businessAutomationJobsPendingPayload.payload

}

###################### YOUR SCRIPT STARTS HERE ############################
write-log2 -Message "Start the Script." #-Level "INFO","ERROR", "WARN"
######################################################################################################################################################################################################
######################################################################################################################################################################################################
######################################################################################################################################################################################################

$isPSelevated = ([Security.Principal.WindowsPrincipal] `
  [Security.Principal.WindowsIdentity]::GetCurrent() `
).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)

#clear the error variable
$error.clear()

write-log2 -Message "scp-file-transfer-send" #use $MyInvocation.MyCommand.Name
write-log2 -Message "Current user: $(whoami)" 
write-log2 -Message "Powershell elevated: $($isPSelevated)" 
write-log2 -Message "Script started $(whoami)" 


#for this resource we need no resource parameter. But if you want to... here are the lines
#write-log2 -Message "Initializing resource parameter"
#$addyPayloadResourceParameter = $resultInitializeInvoke.scriptParameter

## specify a resource parameter
#[string]$dhcpServerHostnameParameter = $addyPayloadResourceParameter.resParVariable #"resParVariable" is definied in the Resource Parameter. This are now a parameter for this script
#$resParVariable = $dhcpServerHostnameParameter.trim()

write-log2 -Message "Initializing resource inputs"
$jobPayload = $resultInitializeInvoke.jobDataArray.businessAutomationJobsPendingPayload.payload

#specify an input parameter
write-log2 -Message "Remote Host: $($jobPayload.remotehost)" 

#specify an input parameter
write-log2 -Message "Local Path: $($jobPayload.remoteusername)" 

#specify an input parameter
write-log2 -Message "Remote Path: $($jobPayload.remotepath)" 

#specify an input parameter
write-log2 -Message "Local Path: $($jobPayload.localpath)" 
#########################################################################


function checkModule ($m) {

    # If module is imported say that and do nothing
    if (Get-Module | Where-Object {$_.Name -eq $m}) {
        write-host "Module $m is already imported."
        return $true
    }
    else {

        # If module is not imported, but available on disk then import
        if (Get-Module -ListAvailable | Where-Object {$_.Name -eq $m}) {
            Import-Module $m -Verbose
            return $true
        }
        else {

            # If module is not imported, not available on disk, but is in online gallery then install and import
            if (Find-Module -Name $m | Where-Object {$_.Name -eq $m}) {
                Install-Module -Name $m -Force -Verbose -Scope CurrentUser
                Import-Module $m -Verbose
                return $true
            }
            else {

                # If module is not imported, not available and not in online gallery then abort
                write-host "Module $m not imported, not available and not in online gallery, exiting."
                return $false
            }
        }
    }
}

$resultLoadModule = checkModule "Posh-SSH" # Use "PoshRSJob" to test it out

if ($resultLoadModule -eq $false) {
    Write-Log2 "Posh-SSH Module cannot be loaded" -Level Error
    $errorCount++
}

if ($errorCount -eq 0) {
    write-log2 "Set the variables"
    $credSSHusername = $jobPayload.remoteusername
    $remoteSSHcomputer = $jobPayload.remotehost
    $remoteSSHpath = $jobPayload.remotepath
    $localPath = $jobPayload.localpath

    write-log2 "credSSHusername: $credSSHusername, remoteSSHcomputer: $remoteSSHcomputer, remoteSSHpath: $remoteSSHpath, localPath: $localPath"
    
    $credSecureStringFilename = Get-StringHash -String $($credSSHusername + $(whoami))
    $SecureStringPath = "$($installPath)SecureStrings\$credSecureStringFilename.txt"

    if (test-path $SecureStringPath) {
        write-host "SecureString FullPath exist."
    } else {
        write-host "Type in the password. The password will be stored as a secure string in a textdocument with a hashvalue as filename. The complete path will be $SecureStringPath"

        $credPasswordSecureString = read-host -assecurestring "Password for $credSSHusername"
            
        #save and store SecureString
        $credSecureStringContent = $credPasswordSecureString | ConvertFrom-SecureString 

        #check if the folder exists
        if (test-path "$($installPath)SecureStrings\") {
            write-host "SecureString Folder already exist"
        } else {
            write-host "SecureString Folder structure does not exist"
            new-item -ItemType Directory -Path "$($installPath)\SecureStrings\" -ErrorAction Continue | Out-Null
        }
            
        write-host "Create SecureString file"    
        Set-Content $SecureStringPath $credSecureStringContent -Force
    }

    $credSSHpassword = get-content $SecureStringPath | convertto-securestring
    $credSSH = New-Object System.Management.Automation.PSCredential -ArgumentList $credSSHusername,$credSSHpassword
    #$credSSH = Get-Credential #for troubleshooting

    #download a file from remote host
    #Get-SCPFolder -ComputerName 'yourremotemachine' -Credential $credSSH -LocalFolder 'C:\MyFolder' -RemoteFolder '/someLinuxFolder'

    #create a duplicate copy of the text with utf8
    #Get-Content -Path 'C:\MyFolder\file' | Out-File -Encoding utf8 -Path 'C:\MyFolder\fileWindows'

    #get the last element in local folder
    $LastItem = get-childitem -Path $localPath | Sort-Object $_.LastWriteTime -Descending | Select-Object -first 1

    write-log2 "Local file: $($LastItem.Name)"

    #copy a single file to remote host
    $remoteFileFullpath = "$($remoteSSHpath)$($LastItem.Name)"
    
    #do the copy and check if an error occured. 
    try { 
        Set-SCPFile -ComputerName $remoteSSHcomputer -Credential $credSSH -RemotePath $remoteSSHpath -LocalFile $LastItem.FullName -AcceptKey:$true
    }
    catch { 
        write-log2 "Error occured" -level ERROR
        write-log2 "Error: $($Error[0].Exception.Message)"
        $errorCount++
    }
    if (!$error) { 
        #"No Error Occured" 
    }

} #if ($errorCount -eq 0) {
else {
    write-log2 "An Error occured. Script failed." -Level ERROR
}

###################### YOUR SCRIPT ENDS HERE ############################
#setting the state. This is important!
if ($debugScript -eq 0) {
    write-log -Message "update state of this job to done" -MachineId $machineId -Privatekey $privatekey -Publickey $publickey -jobId $jobId -path "$($installPath)logs\$($jobId).txt"
    update-modifiedState -jobId $jobId -modifiedState "done" -publickey $publickey -privatekey $privatekey -machineId $machineId

    Start-Sleep 5 
    write-log -Message "End of script reached" -MachineId $machineId -Privatekey $privatekey -Publickey $publickey -jobId $jobId -path "$($installPath)logs\$($jobId).txt"

    Start-Sleep 1
    exit
}

Rating

login and obtain the library resource to set a rating.