通过 PowerShell 脚本比较两个工具中的服务器 ID

Comparing Server IDs in two tools via PowerShell script

我正在制作一个 PowerShell 脚本,用于检索和比较我们正在使用的两个工具中的服务器 ID - Octopus 工具和 MOSS(目的是检查 Octopus 中的所有服务器是否也在 MOSS 中注册) .通过 MySQL 查询在 PowerShell 上访问 Octopus,通过 API 调用访问 MOSS。目前我能够成功检索 sql 查询并将其格式化为 JSON 以便 MOSS 能够读取。但是,我不知道如何检查服务器 ID 是否也存在于 MOSS 中。该脚本所做的只是从 Octopus SQL 中检索 ID,然后将它们解析为 JSON 并对 MOSS 进行空调用。如果有人知道如何从 PowerShell 进行 MOSS 调用,将不胜感激。

当前脚本是:

# Extract RDS and servers from Octopus

# Define log file path
$date = $(get-date).tostring()
$currentdate = get-date -format yyyy-MM-dd
$log_file_path = "C:\Program Files\test\logs\"+$currentdate+"_extract_rds_and_servers_from_octopus.log"
$errorlog_file_path = "C:\Program Files\test\logs\errors\errors.log"

# 0. Exclude Admin Users before getting the RDS licenses which need to be reported
#& ((Split-Path $MyInvocation.InvocationName) + "\exclude_users.ps1") -log_file_path $log_file_path -errorlog_file_path $errorlog_file_path


# 1. Extract ObjectID from Octopus API for current month for each RDP user

try {
    $month = (Get-Date -UFormat "%Y%m")
    $UrlHost = "https://octopus.mos-windows.eu01.stackit.cloud/api/workspace/55cd5c70-d188-4ac3-b946-f1afec8764ad/report/licensing/spla-usage-reseller?&payload[month_id]=$month&payload[with_itemized]=1&_format=json&_token=j8FE4wZDmBITewHUc7lyYeX9XVVjt3dqz0ID4S6A9KQjkMeKfO7_EcgV7Qshuuw1&_tenant=TlXcM&_language=en&payload[flat_structure]=1"
    $HostResponse = Invoke-RestMethod -Uri $UrlHost -Method Get
    $users = $HostResponse.itemized

    $objectids = @()
    foreach ($user in $users.PSObject.Properties) {

        if ($user.Value.readable_label -eq "Windows Server Remote Desktop Services")
        {
        $objectid = $user.Value.object_id
        $objectids += $objectid
        }
    }
}
catch {
$date+" - Error in Octopus API Call: "+$_ | Out-File -Append $errorlog_file_path
exit
}



# 2. Get access device ids from Octopus Database

Import-Module -Name "C:\Program Files\test\request_database.ps1" -ArgumentList $log_file_path, $errorlog_file_path -Verbose

$get_users_devices_query = 
@"
    select user_id, access_device_ids from oc_reporter.ws_installed_software where user_id is not null;
"@

$ui_ad = execute_db_query $get_users_devices_query
$access_device_ids = $users_devices.access_device_ids
$user_ids = $users_devices.user_id


# 3. Get all openstack server id from Octopus Database 

$get_access_device_server_ids_query = 
@"
    select id, lower(SUBSTRING_INDEX(SUBSTRING_INDEX(ref_id, "-", -6), "-", 5)) as server_id, ref_id, label from ws_device 
    where type_id = "vm" and operating_system like "%Windows%" and created > 1644820951;
"@

$ad_si = execute_db_query $get_access_device_server_ids_query


# 4. Map the users/objectids with access device ids and server ids

# Create array with UserID filtered by ObjectID and map each AccessDeviceID(s) to corresponding ServerID

try {
    $filteredsi = @()
    foreach ($userid in $ui_ad)
    {
        if ($objectids -contains $userid.user_id)
        {
        $filteredad = $userid
    
            foreach ($id in $ad_si)
            {
                if ($filteredad.access_device_ids.split(',') -contains $id.id)
                {
                $filteredsi += [PSCustomObject]@{"userid" = $filteredad.user_id; "serverid" = $id.server_id} 
                }
            }
        }
    }
}
catch {
$date+" - Error in Mapping userIDs/objectIDs/accessdeviceIDs/serverIDs: "+$_ | Out-File -Append $errorlog_file_path
exit
}


# Preparation for MOSS

# Create JSON contentblock with looped $filteredsi array 

try {
    $myArray = $filteredsi
    $uniqueUsers = [System.Collections.ArrayList]::new()
    for($i = 0; $i -lt $myArray.Count; $i++){
        if(!$uniqueUsers.Contains($myArray[$i].userid)){
            $uniqueUsers.Add($myArray[$i].userid)
        }
    }
    $allMappings = [System.Collections.ArrayList]::new()
    for($i = 0; $i -lt $uniqueUsers.Count; $i++){
        $singleMapping = [PSCustomObject]@{id = $uniqueUsers[$i]; servers = $null}
        $serverids = [System.Collections.ArrayList]::new()
        for($j = 0; $j -lt $myArray.Count; $j++){
            if($myArray[$j].userid -eq $uniqueUsers[$i]){
                $serverids.Add($myArray[$j].serverid)
            }
        }
        $singleMapping.servers = $serverids
        $allMappings.Add($singleMapping)
    }
    $mosscontent = $allMappings | ConvertTo-Json
    $mosscontent
}
catch {
$date+" - Error in creating content block for MOSS: "+$_ | Out-File -Append $errorlog_file_path
exit
}


# Create complete array including contentblock for MOSS API call

try {
$moss = @"
{
    "type": "server.usage",
    "data": {
        "users": $mosscontent
    }
}
"@
}
catch {
$date+" - Error in creating array for POST to MOSS: "+$_ | Out-File -Append $errorlog_file_path
exit
}



# 5. Call MOSS prod, dev and qa with the whole list of servers and users

# Authenticating to MOSS

$query_file_path_dev_pw  = "~\Documents\MOSSDevEncryptedPassword_"
$query_file_path_qa_pw   = "~\Documents\MOSSQaEncryptedPassword_"
$query_file_path_prod_pw = "~\Documents\MOSSProdEncryptedPassword_"

# Function to store credentials

function get_encrypted_content {

    param (
    [String] $file_path,
    [String] $password
  )

    # Check if credentials file exis
    if ( -Not (Test-Path -Path $file_path)) {

        switch ($password) {
            dev { 
                # Get credentials
                Read-Host -Prompt "Enter password for mos-windows-us-dev-client-id" -AsSecureString | ConvertFrom-SecureString | Out-File -FilePath $file_path
            }
            qa { 
                # Get credentials
                Read-Host -Prompt "Enter password for mos-windows-us-qa-client-id" -AsSecureString | ConvertFrom-SecureString | Out-File -FilePath $file_path
            }           
            prod { 
              # Get credentials
              Read-Host -Prompt "Enter password for mos-windows-us-prod-client-id" -AsSecureString | ConvertFrom-SecureString | Out-File -FilePath $file_path
            }
            
        }

    }

    # Read credentials from file
    $Encrypted_value = Get-Content -Path $file_path

    # Decrypt credentials from file
    return [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR((ConvertTo-SecureString $Encrypted_value)))

}

# Define username and password

$clientid_dev = "mos-windows-us-dev"
$clientid_qa = "mos-windows-us-qa"
$clientid_prod = "mos-windows-us-prod"

$dev_pass = get_encrypted_content $query_file_path_dev_pw "dev"
$qa_pass = get_encrypted_content $query_file_path_qa_pw "qa"
$prod_pass = get_encrypted_content $query_file_path_prod_pw "prod"

[System.Security.SecureString]$clientsecret_dev = ConvertTo-SecureString -String $dev_pass -AsPlainText -Force
[System.Security.SecureString]$clientsecret_qa = ConvertTo-SecureString -String $qa_pass -AsPlainText -Force
[System.Security.SecureString]$clientsecret_prod = ConvertTo-SecureString -String $prod_pass -AsPlainText -Force

#Prepare static variables 

$MOSSToken_dev = 'https://auth.00.idp.eu01.stackit.cloud/oauth/token'
$MOSSToken_qa = 'https://auth.01.idp.eu01.stackit.cloud/oauth/token'
$MOSSToken_prod = 'https://auth.01.idp.eu01.stackit.cloud/oauth/token'

$MOSSUrl_dev = "https://stackit-service-mos-dev.apps.01.cf.eu01.stackit.cloud/v1/events"
$MOSSUrl_qa = "https://stackit-service-mos-qa.apps.01.cf.eu01.stackit.cloud/v1/events"
$MOSSUrl_prod = "https://stackit-service-mos.apps.01.cf.eu01.stackit.cloud/v1/events"

$body = @{grant_type='client_credentials'}    

#Set function to get all customerinfo from all portals

function call_moss {

    param (
    [String] $clientid,
    [SecureString] $clientsecret,
    [String] $MOSSToken,
    [String] $MOSSUrl
    
    )
    
$cred = New-Object -typename System.Management.Automation.PSCredential -ArgumentList $clientid, $clientsecret

#Get Token from MOSS
$Response = Invoke-RestMethod -Uri $MOSSToken -Method Post -Credential $cred -Body $body -ContentType "application/x-www-form-urlencoded"
$Token = $Response.access_token
$Tokenfinal = "Bearer " + $Token

#Post Content to MOSS
Invoke-RestMethod -Uri $MOSSUrl -Method Post -Headers @{'Authorization' = $Tokenfinal } -Body $moss -ContentType "application/json"
}

#Call function to Call MOSS
try
{
Write-Host "Call to MOSS Dev.."
call_moss $clientid_dev $clientsecret_dev $MOSSToken_dev $MOSSUrl_dev
Write-Host "Call to MOSS QA.."
call_moss $clientid_qa $clientsecret_qa $MOSSToken_qa $MOSSUrl_qa
Write-Host "Call to MOSS Prod"
call_moss $clientid_prod $clientsecret_prod $MOSSToken_prod $MOSSUrl_prod
}
catch 
{
$date+" - Error in calling MOSS: "+$_ | Out-File -Append $errorlog_file_path
exit
}



# 6. Create daily logs with users reported to MOSS

$date = $(get-date).tostring()
$log = foreach ($item in $filteredsi) 
{
$item
}
echo $date $log | Out-file -Append $log_file_path

# delete logs older than 60 days
$limit = (Get-Date).AddDays(-60)
$path = "C:\Program Files\test\logs"

# Delete files older than the $limit.
Get-ChildItem -Path $path -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit } | Remove-Item -Force



# Create activity file to check if script is working

$temp_file_path = "C:\Program Files\test\tempfile*"
if (Test-Path $temp_file_path) 
{
Remove-Item $temp_file_path
}

[string]$filePath = "C:\Program Files\test\tempfile";
[string]$directory = [System.IO.Path]::GetDirectoryName($filePath);
[string]$strippedFileName = [System.IO.Path]::GetFileNameWithoutExtension($filePath);
[string]$extension = [System.IO.Path]::GetExtension($filePath);
[string]$newFileName = $strippedFileName + "_" + (Get-Date).ToString('MM-dd-yyyy') + $extension;
[string]$newFilePath = [System.IO.Path]::Combine($directory, $newFileName);

New-Item $newFilePath

正在调用的其他脚本: -> request_database.ps1

# 1. Get path for log files
param(
    [string]$log_file_path = "C:\Program Files\test\logs\request_database.log",
    [string]$errorlog_file_path = "C:\Program Files\test\logs\request_database_errors.log"
)


# 2. Get credentials to access Octopus DB

try {
    # Define username and password security string files
    $mysql_user_file_path = "~\Documents\ue_"
    $mysql_pass_file_path = "~\Documents\pe_"

    # Functions
    function get_encrypted_content {

        param (
            [String] $file_path,
            [String] $user_or_pass
        )

        # Check if credentials file exist
        if ( -Not (Test-Path -Path $file_path)) {

            switch ($user_or_pass) {
                msqu { 
                    # Get credentials
                    Read-Host -Prompt "Please, enter MySQL username" -AsSecureString | ConvertFrom-SecureString | Out-File -FilePath $file_path
                }
                msqp { 
                    # Get credentials
                    Read-Host -Prompt "Please, enter MySQL password" -AsSecureString | ConvertFrom-SecureString | Out-File -FilePath $file_path
                }           
                 
            }

        }

        # Read credentials from file
        $Encrypted_value = Get-Content -Path $file_path

        # Decrypt credentials from file
        return [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR((ConvertTo-SecureString $Encrypted_value)))

    }


    # Define username and password

    $my_sql_user = get_encrypted_content $mysql_user_file_path "msqu"
    $my_sql_pass = get_encrypted_content $mysql_pass_file_path "msqp"

    [System.Security.SecureString]$SecPwd = ConvertTo-SecureString -String $my_sql_pass -AsPlainText -Force
    $Credential = new-object -typename System.Management.Automation.PSCredential -argumentlist @($my_sql_user,$SecPwd)
}
catch {
    $(get-date).tostring() +" - Error in fetching SQL user/pwd: "+$_ | Out-File -Append $errorlog_file_path
    exit
}


$error_string = ""
# 3. Execute DB query
# If you want the script to continue on error you have to provide $true as second parameter
# Example: execute_db_query $exclude_stackitadmin_users_query $true 
function execute_db_query {

    param (
        [String] $query,
        [bool] $continueOnError = $false
    )

    try {
        # Query Octopus DB
        Connect-MySqlServer -Credential $Credential -Server localhost 
       
        if ($continueOnError) {
            $query_results = Invoke-MySqlQuery -Query $query
        } else {
            $query_results = Invoke-MySqlQuery -Query $query -ErrorAction Stop
        }
        Disconnect-MySqlServer

        return $query_results
    }
    catch {
        $error_message = $(get-date).tostring() + " - Error in DB Query 1: " + $_
        $error_message | Out-File -Append $errorlog_file_path
        Write-Error $error_message
        exit
    }
}

-> exclude_users.ps1(任务可能不需要,但没有它整个脚本将无法运行)

# 1. Get path for log files or use default
param(
    [string]$log_file_path = "C:\Program Files\test\logs\exclude_users.log",
    [string]$errorlog_file_path = "C:\Program Files\test\logs\errors\exclude_users_errors.log"
)

Import-Module -Name "C:\Program Files\test\request_database.ps1" -ArgumentList $log_file_path, $errorlog_file_path -Verbose

# Exclude StackitAdmin users

$exclude_stackitadmin_users_query = 
@"
   update oc_reporter.ws_user as updated_user,
        (
            select id from oc_reporter.ws_user
            where username = "StackITAdmin" and exclude_spla = "no"
        ) as us
    set
        exclude_spla = "yes",
        exclude_spla_reason = "nh"
    where updated_user.id = us.id;
"@

execute_db_query($exclude_stackitadmin_users_query)


# Exclude users on dev & qa environment
$exclude_users_on_dev_qa_query = 
@"
    update oc_reporter.ws_installed_software as updated_software, 
    (
            select ws.access_device_ids, min(ws.access_device_labels), min(ws.user_label), excluded_users, min(ws.id) as id from oc_reporter.ws_user
            join oc_reporter.ws_installed_software as ws 
                on ws.user_id = ws_user.id
            join oc_reporter.ws_customer as wc
                on wc.id = ws_user.customer_id
            left join 
                (select access_device_ids, count(1) as excluded_users from oc_reporter.ws_user as wu
                join oc_reporter.ws_customer as wc
                    on wc.id = wu.customer_id
                join oc_reporter.ws_installed_software as ws
                    on ws.user_id = wu.id
                where 
                    (internal_id like "d-%" or internal_id like "q-%") and
                    locate(',', access_device_ids) = 0 and
                    ws.exclude_spla = "yes" and
                    ws.label = "Microsoft Remote Desktop Services" and
                    wu.username != "StackitAdmin"
                group by access_device_ids, wu.exclude_spla) as servers
            on servers.access_device_ids = ws.access_device_ids
            where 
                ws.exclude_spla = "no" and 
                ws.label = "Microsoft Remote Desktop Services" and
                (internal_id like "d-%" or internal_id like "q-%") and
                locate(',', ws.access_device_ids) = 0 
            group by ws.access_device_ids
            having (excluded_users = 1 or excluded_users is null)
     ) as us
    set 
        exclude_spla = "yes",
        exclude_spla_reason = "admin"
    where updated_software.id = us.id;
"@

# run twice to exlude 2 users per vm
execute_db_query($exclude_users_on_dev_qa_query)
execute_db_query($exclude_users_on_dev_qa_query)


# Exclude users from our mos-windows-2 project
$exclude_users_from_our_projects = 
@"
    update oc_reporter.ws_installed_software as ins,
    (
        select ws.access_device_ids, min(ws.access_device_labels), min(ws.user_label), excluded_users, min(ws.id) as id, min(wu.id) from oc_reporter.ws_user as wu
        join oc_reporter.ws_installed_software as ws
            on ws.user_id = wu.id
        join oc_reporter.ws_device as wd
            on wd.id = ws.access_device_ids
        left join (
            select ws.access_device_ids, min(ws.id), min(wu.id), count(1) as excluded_users from oc_reporter.ws_user as wu
            join oc_reporter.ws_installed_software as ws
                on ws.user_id = wu.id
            join oc_reporter.ws_device as wd
                on wd.id = ws.access_device_ids
            where
                ws.exclude_spla = "yes" and
                ws.label = "Microsoft Remote Desktop Services" and
                LOCATE(',',access_device_ids) = 0 and 
                (
                    hkey like "%d57abb0200304506879bd8037f7a49cb%" or
                    hkey like "%fce60e2c938c49e4a37687492a45b652%" or
                    hkey like "%8eb91d45f25b45978b71abb0e06a0443%" or
                    hkey like "%66ad75e4ff624f7e940dc363549c8404%" or 
                    hkey like "%351aa84fb9b54be896112b36ae15dd48%" or
                    hkey like "%64edd6c19e17417d86094e6a02610eed%"
                ) and
                wu.username != "StackitAdmin"
            group by ws.access_device_ids
            ) as excluded_ws
        on 
            excluded_ws.access_device_ids = ws.access_device_ids
        where
            ws.exclude_spla = "no" and
            ws.label = "Microsoft Remote Desktop Services" and
            LOCATE(',',ws.access_device_ids) = 0 and 
            (
                hkey like "%d57abb0200304506879bd8037f7a49cb%" or
                hkey like "%fce60e2c938c49e4a37687492a45b652%" or
                hkey like "%8eb91d45f25b45978b71abb0e06a0443%" or
                hkey like "%66ad75e4ff624f7e940dc363549c8404%" or 
                hkey like "%351aa84fb9b54be896112b36ae15dd48%" or
                hkey like "%64edd6c19e17417d86094e6a02610eed%"
            ) and
            wu.domain not like "%HOP01%" and 
            wu.domain not like "%WSUS01%" and 
            wu.domain not like "%OCKMS%" and
            wu.domain not like "%AZDVOP%"
        group by ws.access_device_ids
        having (excluded_users = 1 or excluded_users is null)
    ) as rds
    set 
            exclude_spla = "yes",
            exclude_spla_reason = "admin"
    where ins.id = rds.id;  
"@

# run twice to exlude 2 users per vm
execute_db_query($exclude_users_from_our_projects)
execute_db_query($exclude_users_from_our_projects)

顺序错误,还有很多不必要的元素导致错误和崩溃。

当前的工作代码是:

# Compare the data between the MOSS and the Octopus

# Define log file path
$date = $(get-date).tostring()
$currentdate = get-date -format yyyy-MM-dd
$log_file_path = "[FILE PATH]"
$errorlog_file_path = "[FILE PATH]"

# 1. Call MOSS (dev, qa, prod) to get the data for all servers created in the last 48 hours

# Authenticating to MOSS

$query_file_path_dev_pw  = "[FILE PATH]"
$query_file_path_qa_pw   = "[FILE PATH]"
$query_file_path_prod_pw = "[FILE PATH]"

# Function to store credentials

function get_encrypted_content {

    param (
    [String] $file_path,
    [String] $password
  )

    # Check if credentials file exis
    if ( -Not (Test-Path -Path $file_path)) {

        switch ($password) {
            dev { 
                # Get credentials
                Read-Host -Prompt "Enter password for mos-windows-us-dev-client-id" -AsSecureString | ConvertFrom-SecureString | Out-File -FilePath $file_path
            }
            qa { 
                # Get credentials
                Read-Host -Prompt "Enter password for mos-windows-us-qa-client-id" -AsSecureString | ConvertFrom-SecureString | Out-File -FilePath $file_path
            }           
            prod { 
              # Get credentials
              Read-Host -Prompt "Enter password for mos-windows-us-prod-client-id" -AsSecureString | ConvertFrom-SecureString | Out-File -FilePath $file_path
            }
            
        }

    }

    # Read credentials from file
    $Encrypted_value = Get-Content -Path $file_path

    # Decrypt credentials from file
    return [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR((ConvertTo-SecureString $Encrypted_value)))

}

# Define username and password

$clientid_dev = "[USERNAME]"
$clientid_qa = "[USERNAME]"
$clientid_prod = "[USERNAME]"

$dev_pass = get_encrypted_content $query_file_path_dev_pw "dev"
$qa_pass = get_encrypted_content $query_file_path_qa_pw "qa"
$prod_pass = get_encrypted_content $query_file_path_prod_pw "prod"

[System.Security.SecureString]$clientsecret_dev = ConvertTo-SecureString -String $dev_pass -AsPlainText -Force
[System.Security.SecureString]$clientsecret_qa = ConvertTo-SecureString -String $qa_pass -AsPlainText -Force
[System.Security.SecureString]$clientsecret_prod = ConvertTo-SecureString -String $prod_pass -AsPlainText -Force

# Time variable

$date48h = ("{0:yyyy-MM-ddThh:mm:ss}" -f ((get-date).Addhours(-48))).split("T").split(":")
$date = $date48h[0]
$hour = $date48h[1]
$min = $date48h[2]
$sec = $date48h[3]

#Prepare static variables 

$MOSSToken_dev = '[URL]'
$MOSSToken_qa = '[URL]'
$MOSSToken_prod = '[URL]'

$MOSSUrl_dev = "[URL]"
$MOSSUrl_qa = "[URL]"
$MOSSUrl_prod = "[URL]"

$body = @{grant_type='client_credentials'}    

#Set function to get all customerinfo from all portals

function call_moss {

    param (
    [String] $clientid,
    [SecureString] $clientsecret,
    [String] $MOSSToken,
    [String] $MOSSUrl
    
    )
    
$cred = New-Object -typename System.Management.Automation.PSCredential -ArgumentList $clientid, $clientsecret

#Get Token from MOSS
$Response = Invoke-RestMethod -Uri $MOSSToken -Method Post -Credential $cred -Body $body -ContentType "application/x-www-form-urlencoded"
$Token = $Response.access_token
$Tokenfinal = "Bearer " + $Token

#Post Content to MOSS
Invoke-RestMethod -Uri $MOSSUrl -Method Get -Headers @{'Authorization' = $Tokenfinal } -ContentType "application/json"
}

#Call function to Call MOSS
try
{
Write-Host "Call to MOSS Dev.."
$get_moss_dev = call_moss $clientid_dev $clientsecret_dev $MOSSToken_dev $MOSSUrl_dev
Write-Host "Call to MOSS QA.."
$get_moss_qa = call_moss $clientid_qa $clientsecret_qa $MOSSToken_qa $MOSSUrl_qa
Write-Host "Call to MOSS Prod"
$get_moss_prod = call_moss $clientid_prod $clientsecret_prod $MOSSToken_prod $MOSSUrl_prod
}
catch 
{
$date+" - Error in calling MOSS: "+$_ | Out-File -Append $errorlog_file_path
exit
}

$moss_dev_serverids = $get_moss_dev.items.id
$moss_qa_serverids = $get_moss_qa.items.id
$moss_prod_serverids = $get_moss_prod.items.id
$moss_serverid_arr = @($moss_dev_serverids, $moss_qa_serverids, $moss_prod_serverids)

# 2. Call Octopus to get the data for new servers created in the last 36 hours

Import-Module -Name "[FILE PATH]" -ArgumentList $log_file_path, $errorlog_file_path -Verbose

# Calculate timestamp

$DateTime = Get-Date #or any other command to get DateTime object
$CurrentUnixTime = ([DateTimeOffset]$DateTime).ToUnixTimeSeconds()
$queryTime = $CurrentUnixTime - (36 * 3600)

$get_new_servers_query_oc = 
@"
    select id, lower(SUBSTRING_INDEX(SUBSTRING_INDEX(ref_id, "-", -6), "-", 5)) as server_id, ref_id, label from oc_reporter.ws_device where type_id = "vm" and operating_system like "%Windows%" and created > $queryTime;
"@

$query = execute_db_query $get_new_servers_query_oc
$serverid_oc = $query.server_id
$serverid_oc_arr = @($serverid_oc)

# 3. Compare the properties in MOSS and Octopus
$unmatching_serverids = $serverid_oc_arr | Where {$moss_serverid_arr -NotContains $_}
$error_report = @($unmatching_serverids)

# Create daily logs with servers in Octopus that are unregistered in MOSS

$date = $(get-date).tostring()
$log = $error_report 
echo $date $log | Out-file -Append $log_file_path

# delete logs older than 60 days
$limit = (Get-Date).AddDays(-60)
$path = "[FILE PATH]"

# Delete files older than the $limit.
Get-ChildItem -Path $path -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit } | Remove-Item -Force

# 4. Generate summary with all errors and send a notification if there is an error. Schedule a task to check once per day.
If ($error_report.Count -eq 0) {
   exit
}
else {
   $JSONBody = [PSCustomObject][Ordered] @{
        "type"      = "MessageCard"
        "title"     = "Octopus Alerts"
        "text"      = "Servers located in Octopus, that are not registered in MOSS. <br>
                       Please check logs."
   }

   $TeamsMessageBody = ConvertTo-Json $JSONBody

   $parameters = @{
       "URI"          = '[URL]'
       "Method"       = 'POST'
       "Body"         = $TeamsMessageBody
       "ContentType"  = 'application/json'
   }

   Invoke-RestMethod @parameters
}

# Create activity file to check if script is working

$temp_file_path = "[FILE PATH]"
if (Test-Path $temp_file_path) 
{
Remove-Item $temp_file_path
}

[string]$filePath = "[FILE PATH]";
[string]$directory = [System.IO.Path]::GetDirectoryName($filePath);
[string]$strippedFileName = [System.IO.Path]::GetFileNameWithoutExtension($filePath);
[string]$extension = [System.IO.Path]::GetExtension($filePath);
[string]$newFileName = $strippedFileName + "_" + (Get-Date).ToString('MM-dd-yyyy') + $extension;
[string]$newFilePath = [System.IO.Path]::Combine($directory, $newFileName);

New-Item $newFilePath

此外,如前所述,完全不需要 exclude_users 脚本。唯一额外包含的脚本是 request_database 脚本。