How to Get Start-Job working with TimeStamp Pipe [duplicate] - powershell

This question already has answers here:
How to pass a custom function inside a ForEach-Object -Parallel
(3 answers)
PowerShell Use UDF in ForEach-Object -Parallel [duplicate]
(1 answer)
Closed 10 months ago.
I have a powershell line that works great:
Start-Job { plink.exe -telnet 000.000.000.000 -P 1000 > LogFile.txt }
Job runs as expected in the background, text file is created.
When I throw TimeStamp in there than run the job, Get-Job shows it completed, and the file is not created. Not sure if it makes the connection or not in this case.
Start-Job { plink.exe -telnet 000.000.000.000 -P 1000 | TimeStamp > LogFile.txt }
When I run the above without Start-Job and with TimeStamp it works fine. Obviously it is finishing the job at TimeStamp. Any ideas for a workaround or another way to get the timestamp in the log file. Running it as a job is the way i want to go mainly So I can stop it at a specific time, parse the logs than restart with a new file name. Here the rest of the script:
filter timestamp {"$(Get-Date -Format MM/dd/yyyy_HH:mm:ss) $_"}
Start-Job -Name Logging { c:\plink.exe -telnet 000.000.000.000 -P 10000 | TimeStamp
> c:\users\User\"LogFile_$(get-date -f MM-dd-yyyy).txt" }
[datetime]$JobEndTime = '23:50'
$AddDaysWhenInPast = 1
[datetime]$CurrentTime = Get-Date
If ($JobEndTime -lt $CurrentTime) { $JobEndTime =
$JobEndTime.AddDays($AddDaysWhenInPast) }
[int]$WaitSeconds = ( $JobEndTime - $CurrentTime ).TotalSeconds
#Debug
#write-Host $JobEndTime
#Write-Host $AddDaysWhenInPast
#Write-Host $CurrentTime
#Write-Host $WaitSeconds
#Write-Host $AddDaysWhenInPast
#Pause
Stop-Job logging
Set-Content -Path C:\users\User\"LogFile_$(get-date -f MM-dd-yyyy).txt" -Value (get-
content -Path C:\users\users\User\"LogFile_$(get-date -f MM-dd-yyyy).txt" | Where-
Object { $i % 2 -eq 0; $i++ })
Set-Content -Path C:\users\User\"LogFile_$(get-date -f MM-dd-yyyy).txt" -Value (get-
content -Path C:\users\User\"LogFile_$(get-date -f MM-dd-yyyy).txt" | Select-String -
Pattern '00000' -NotMatch)
(loops back to top)

Related

How can I check error code inside foreach loop? [duplicate]

This question already has answers here:
How to handle errors for the commands to run in Start-Job?
(1 answer)
Silent installation by using Powershell scripting
(2 answers)
Closed 4 years ago.
I need to make a simple script for DB logical dump. The goal to use the script for two purposes.
If I run it with parameter (DB names) it shall create a logical dump of those DBs.
If I run without parameters it starts command for a list of DBs (hardcoded).
I want to check error code for each command start (pg_dump) inside foreach loop, log it and continue.
What's the best way to do it?
So far I dicovered that I can use try and catch.
Side-note: In my code I tried try..catch only once for testing purposes.
$path = '"C:\Program Files\PostgreSQL\version\bin\pg_dump.exe"'
$backup_path = 'D:\Backups\test\'
$limit = (Get-Date).AddDays(-2)
$logdate = (Get-Date).ToString("yyyy-MM-dd")
$pg_suffix = "pg_dump"
#$LogFile = $backup_path\$pg_suffix_$(Get-Date -f yyyy-MM-dd) + '.log'
$pg_dump_error = "pg_dump has failed"
$p = $args
[array]$DB_Array = #('postgres', 'db02', 'db03')
if ($p -ne $null) {
try {
foreach ($DB in $p) {
$backup_path_temp = $backup_path + $DB + '_' + $(Get-Date -f yyyy-MM-dd) + '.backup'
cmd /c "$path -w -h localhost -U postgres -Z3 -Fd -j 12 -f $backup_path_temp $DB"
}
} catch {
#"Error! $pg_dump_error" | Tee-Object -FilePath $LogFile -Append | Write-Error }
Write "Error: $file.name: $_" >>D:\\Backups\logfile.txt
}
continue;
} else {
foreach ($DB in $DB_Array) {
$backup_path_temp = $backup_path + $DB + '_' + $(Get-Date -f yyyy-MM-dd) + '.backup'
cmd /c "$path -w -h localhost -U postgres -Z3 -Fd -j 12 -f $backup_path_temp $DB"
}
}
# Delete files older than the $limit.
Get-ChildItem -Path $backup_path -Force |
Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit } |
Remove-Item -Force -Recurse
Use $LastExitcode automatic variable for getting the exit code of a executable in PowerShell.

Get-Content mosquitto_pub

I have a tool that logs some data onto a file. I'd like to tail the file and send the last line of data via mosquitto_pub.
I've used powershell "Get-Content" command without succes.
Here's my command:
Get-Content -Path "C:\test.txt" -Wait | .\mosquitto_pub.exe -t "Events"
But nothing is published by mosquitto_pub.
If I use Get-Content -Path "C:\test.txt" -Wait
I see the tail of the file in stdout.
What's wrong with my solution?
Thanks!
Read this Q and A.
An alternate approach
$minsToRunFor = 10
$secondsToRunFor = $minsToRunFor * 60
foreach ($second in $secondsToRunFor){
$lastline = Get-Content -Path "C:\test.txt" | Select-Object -last 1
# added condition as per VonPryz's good point
# (otherwise will add lastline regardless of whether it's new or not)
if ($lastline -ne $oldlastline){
.\mosquitto_pub.exe -t "Events" -m "$lastline"
}
$oldlastline = $lastline
Start-Sleep 100
}

Pipe all Write-Output to the same Out-File in PowerShell

As the title suggests, how do you make it so all of the Write-Outputs - no matter where they appear - automatically append to your defined log file? That way the script will be nicer to read and it removes a tiny bit of work!
Little example below, id like to see none of the "| Out-File" if possible, yet have them still output to that file!
$Author = 'Max'
$Time = Get-Date -Format "HH:mm:ss.fff"
$Title = "Illegal Software Removal"
$LogName = "Illegal_Remove_$($env:COMPUTERNAME).log"
$Log = "C:\Windows\Logs\Software" + "\" + $LogName
$RemoteLog = "\\Server\Adobe Illegal Software Removal"
Set-PSBreakpoint -Variable Time -Mode Read -Action { $global:Time = Get-Date -format "HH:mm:ss.fff" } | Out-Null
If((Test-Path $Log) -eq $False){ New-Item $Log -ItemType "File" -Force | Out-Null }
Else { $Null }
"[$Time][Startup] $Title : Created by $Author" | Out-File $Log -Append
"[$Time][Startup] Configuring initial variables required before run..." | Out-File $Log -Append
EDIT: This needs to work on PS v2.0, I don't want the output to appear on screen at all only in the log. So I have the same functionality, but the script would look like so...
"[$Time][Startup] $Title : Created by $Author"
"[$Time][Startup] Configuring initial variables required before run..."
You have two options, one is to do the redirection at the point the script is invoked e.g.:
PowerShell.exe -Command "& {c:\myscript.ps1}" > c:\myscript.log
Or you can use the Start-Transcript command to record everything (except exe output) the shell sees. After the script is done call Stop-Transcript.

Wait for a script to finish

I am using a script which backups the folders and than in the next block tries to delete those folder from there original location.This is the script
if ($confirmation -eq 'y') {
# 3. BACKUP script
./bakup_mysite.ps1
# 4. DELETE CONTENTS OF my_site
get-childitem "C:\inetpub\wwwroot\my_site\" -recurse | % {
remove-item $_.FullName -recurse -force
}
}
If I put a Read-Host after step 3 it does stop and ask the user to press any key and then it deletes the next block. But I want to put a wait so the user doesn't have to press any key and everything happens automatically.
This is the backup code which gets called from my_site.ps1
$Service_folder_name = 'C:\Services\'
$Pics_folder_name = 'C:\Pics\'
$Date = Get-Date
$folder_date = $Date.ToString("yyyy-MM-dd_HHmm")
$backup_folder_name = 'c:\_Backups\my_site\' + $folder_date
if (!(Test-Path -path $backup_folder_name)) {
New-Item $backup_folder_name -type directory
}
if ((Test-Path -path $Pics_folder_name)) {
gi $pics_folder_name | .\Library\out-zip.ps1 $backup_folder_name\pics.zip $_
}
if ((Test-Path -path $Service_folder_name)) {
gi $Service_folder_name | .\Library\out-zip.ps1 $backup_folder_name\Services.zip $_
}
For Powershell cmdlets or functions, PowerShell waits before starting the next command. If it is not the case for your backup script, the trick is to pipeline to Out-Null :
./bakup_mysite.ps1 | Out-Null
PowerShell will wait until your script has exited before continuing.
Another option is to use a background job:
$BackupJob = Start-Job -FilePath "\Path\To\bakup_mysite.ps1"
Wait-Job $BackupJob
Powershell will wait until the job $BackupJob has completed before moving on to the next commands.

monitor a log file with Get-Content -wait until the end of the day

I have a script monitoring a log file with get-Content and it waits for new lines to be written so it can detect the change. The logger changes the name of the log file every day to make it System_$date.log.
I am trying to make my Get-Content to wait for new lines as well as break when the date changes then to re execute itself with the new date in the filename. Does anybody have an idea how this could be done?
Thanks
Edit
The script looks like this:
Get-Content System_201371.log -wait | where {$_ -match "some regex"} |
foreach {
send_email($_)
}
The file name which is System_201371 changes everyday, it will be System_201372 and so on, Also this script runs as service, I need to it to break and re-execute itself with a new filename
You could use Jobs for this. Read the file in some background job, and let the "foreground" script wait until the day has changed. Once the day has changed, kill the old job and start a new one looking at the new file.
while($true)
{
$now = Get-Date
$fileName = 'System_{0}{1}{2}.log' -f $now.Year, $now.Month, $now.Day
$fullPath = "some directory\$fileName"
Write-Host "[$(Get-Date)] Starting job for file $fullPath"
$latest = Start-Job -Arg $fullPath -ScriptBlock {
param($file)
# wait until the file exists, just in case
while(-not (Test-Path $file)){ sleep -sec 10 }
Get-Content $file -wait | where {$_ -match "some regex"} |
foreach { send_email($_) }
}
# wait until day changes, or whatever would cause new log file to be created
while($now.Date -eq (Get-Date).Date){ sleep -Sec 10 }
# kill the job and start over
Write-Host "[$(Get-Date)] Stopping job for file $fullPath"
$latest | Stop-Job
}
This, should always monitor today's log and detect date change:
do{
$CurrentDate = get-date -uformat %Y%j
$CurrentLog = ("C:\somepath\System_" + $CurrentDate + ".log")
Start-Job -name Tail -Arg $CurrentLog -Scriptblock{
While (! (Test-Path $CurrentLog)){ sleep -sec 10 }
write-host ("Monitoring " + $CurrentLog)
Get-Content $CurrentLog -wait | where {$_ -match "some regex"} |
foreach { send_email($_) }
}
while ($CurrentDate -eq (get-date -uformat %Y%j)){ sleep -sec 10}
Stop-Job -name Tail
} while ($true)