J'ai un fichier texte à un endroit du serveur. Ce fichier contient une valeur de chaîne et un horodatage . Je souhaite remplacer cette ligne spécifique par le dernier horodatage à l'aide de PowerShell.
Vous trouverez ci-dessous les données du fichier bloc-notes:
Test Service | 05-09-2017 01-09-41
Le 05-09-2017 le 01-09-41 est MM-jj-aaaa HH-mm-ss et je souhaite remplacer cette ligne par le dernier horodatage.
Donc, si après deux minutes il devrait être
Test Service | 05-09-2017 01-11-41
Voici ce que je fais:
$ReplaceString = "$ServiceName + "|" + (Get-Date).ToString('MM-dd-yyyy HH-mm-ss')"
Get-Content Path -Replace($ServiceName + "|" + $StringLastRunTime,$ReplaceString) | Set-Content Path
Mais cela ne génère pas les résultats attendus.
METTRE À JOUR
Désolé de ne pas être aussi clair avec les exigences
Je souhaite surveiller les services critiques installés sur le serveur à l'aide du script PowerShell. J'ai répertorié tous les services à surveiller dans un fichier texte et ce chemin a été mentionné dans le script. Ce script s'exécutera toutes les 5 minutes. Si le service n'est pas installé ou s'il est arrêté, il génère une notification par courrier électronique. Pour éviter l'afflux d'emails, je pense mettre à jour un horodatage avec le nom du service dans le fichier texte . Donc, si je trouve un service en mode arrêté ou non installé, j'enverrai une notification et mettrai à jour l'horodatage de la dernière ça a été envoyé. J'ai un intervalle de renvoi qui vérifie toutes les cinq minutes et si cet intervalle est passé, je dois à nouveau envoyer la notification et je veux mettre à jour l'horodatage.
Code (J'ai supprimé la partie d'envoi d'email pour le rendre moins complexe):
$ServicesList = Get-Content E:\ServiceReports\Services.txt
$ResendEmailInterval = 10 #In Minutes
foreach ($Service in $ServicesList) {
$ServiceName = $Service
$Service = Get-Service -Display $Service -ErrorAction SilentlyContinue
$serviceDisplayName = $Service.displayname
if (-Not $Service) {
#Service is not installed. So need to send an email alert and update the timestamp.
Write-Host $ServiceName.IndexOf("|")
if ($ServiceName.IndexOf("|") -gt 0) {
$ServiceName,$StringLastRunTime = $ServiceName.Split('|')
$LastRunTime = [datetime]::ParseExact($StringLastRunTime, "MM-dd-yyyy HH-mm-ss", $null)
Write-Host $ServiceName
Write-Host $LastRunTime
Write-Host (Get-Date).AddMinutes($ResendEmailInterval)
if ($LastRunTime -lt (Get-Date).AddMinutes($ResendEmailInterval)) {
Write-Host "time to run"
$ReplaceString = $ServiceName + "|" + (Get-Date).ToString('MM-dd-yyyy HH-mm-ss')
Write-Host $ServiceName"|"$StringLastRunTime
Write-Host $ReplaceString
#$ServiceName = "Test Service";
$ReplaceString = "{0}|{1}" -f $ServiceName, (Get-Date).ToString('MM-dd-yyyy HH-mm-ss');
(Get-Content -Path $ServicesListPath) -replace ('([^|]+).*', $ReplaceString) | Set-Content $ServicesListPath;
$ServicesList -replace ($ServiceName + "|" + $StringLastRunTime, $ReplaceString) | Set-Content $ServicesListPath
}
} else {
$ReplaceString = $ServiceName + "|" + (Get-Date).ToString('MM-dd-yyyy HH-mm-ss')
$ServicesList -replace ($ServiceName, $ReplaceString) | Set-Content $ServicesListPath
$i = $i+1;
}
} else {
if ($Service.Status -eq "Stopped") {
Write-Host "Service is stopped"
#Time to send email and update the time stamp
$i = $i+1;
} else {
#Write-Host "Service is running. Nothing to do."
}
}
}
Vous pouvez le faire en utilisant un regex:
$filePath = 'yourPath'
(Get-Content $filePath -raw) -replace '([^|]+).*', ('$1|{0:MM-dd-yyyy HH-mm-ss}' -f (Get-Date)) |
Set-Content $filePath
Je souhaite surveiller les services critiques installés sur le serveur à l'aide du script PowerShell.
Puisque cela semble être votre motivation pour faire tout ce script, je vais vous dire un meilleur moyen de surveiller les services que d'écrire des horodatages dans un fichier:
PowerShell
en tant que programme et c:\path\to\your\script.ps1
en tant que paramètre.Étant donné que votre fichier est utilisé comme base de données, vous devriez plutôt utiliser un stockage basé sur CSV, tout d'abord parce que vous avez des applets de commande conçues pour analyser des fichiers CSV, à savoir Import-CSV
et Export-CSV
, deuxièmement, car avec CSV, vous pouvez enregistrer des informations de type pour les colonnes. . De cette façon, vous pouvez générer le fichier CSV approprié une fois, puis exécuter Import-CSV
, ce qui donne un tableau de PSObject
s, puis traiter chacune d’elles en mettant à jour l’horodatage avec (get-date)
ou [DateTime]::Now
, puis en remplaçant Export-CSV
les données enregistrées par une sauvegarde éventuelle, copie de travail. Comme ça:
$ServicesList=Import-CSV E:\ServiceReports\Services.txt -encoding UTF8
foreach ($service in $serviceslist) {
# a PSObject expected to have "Service" and "Timestamp" fields
$servicename=$service.service
$ts=$service.timestamp
if ($ts -eq "") { $ts=get-date "01.01.2000 00:00:00" }
$sysservice=get-service -displayname $servicename -ea silentlycontinue
if (-not $sysservice) {
if ($ts -lt [DateTime]::Now.AddMinutes(-1*$ResendEmailInterval)) {
# send email - no service
$service.timestamp=[DateTime]::Now # just that
}
} elseif ($sysservice.status -eq 'Stopped') {
write-Host "Service $servicename is stopped"
if ($ts -lt [DateTime]::Now.AddMinutes(-1*$ResendEmailInterval)) {
# send email - service stopped
$service.timestamp=[DateTime]::Now # update timestamp
}
} else {
#service is running, set timestamp to "zero"
$service.timestamp=get-date "01.01.2000 00:00:00"
}
}
$ServicesList | Export-CSV E:\ServiceReports\Services.txt -encoding UTF8
Avant cela, remplissez le fichier avec le contenu suivant, en fournissant les noms réels des services que vous souhaitez surveiller:
"Service","Timestamp"
"First service",""
"Second service",""
...
En regardant votre code fourni et sans savoir quelle est la sortie réelle, je m'attendrais à ce que votre $ReplaceString
soit erroné. Vos citations ne s'additionnent pas. Cela devrait fonctionner pour cela:
$ReplaceString = $ServiceName + "|" + (Get-Date).ToString('MM-dd-yyyy HH-mm-ss')
OK, alors votre exemple ...
$ReplaceString = "$ServiceName + "|" + (Get-Date).ToString('MM-dd-yyyy HH-mm-ss')"
Get-Content Path -Replace($ServiceName + "|" + $StringLastRunTime,$ReplaceString) | Set-Content Path
Pourrait probablement être corrigé.
La chaîne que vous recherchez avec -replace
doit être une regex. Le caractère |
est spécial dans une expression régulière et doit être échappé. Je composais le regex sur une ligne séparée et le stockais dans une variable nommée $ regex pour que je n'oublie pas.
Vous voulez exécuter le remplacement sur chaque ligne sortant de Get-Content, vous devez donc le faire dans une étape de pipeline distincte, en utilisant% (abréviation de "foreach-object").
J'utiliserais une interpolation de chaîne pour former les chaînes. C'est facultatif, mais je vais vous montrer ce que je veux dire ...
Je présume que Path
devrait être une variable et non le nom littéral du fichier.
Obtenir et définir le contenu du même fichier dans un seul pipeline risque de générer un conflit. Le faire sur deux lignes différentes est le plus simple.
Une version corrigée pourrait ressembler à ceci:
$regex = "^$([regex]::Escape($serviceName))\|.*"
$ReplaceString = "${ServiceName}|$((Get-Date).ToString('MM-dd-yyyy HH:mm:ss'))"
$result = Get-Content $Path | %{ $_ -replace($regex,$ReplaceString)}
Set-Content $Path -Value $result
P.S. La partie [regex] :: Escape est juste au cas où ServiceName aurait des caractères spéciaux dedans ...
De plus, ce script ne garde pas le fichier verrouillé pendant la période qui s’écoule entre les deux dernières lignes, donc une autre application pourrait le mettre à jour entre les deux. Avec les fichiers texte, le dernier rédacteur l'emporte. Ainsi, en cas de collision, certaines mises à jour risquent d'être perdues.
Le code que vous avez ajouté à la description ne semble pas fonctionner. De plus, je suggère d'utiliser l'opérateur de formatage pour les chaînes.
$ServiceName = "Test Service";
$ReplaceString = "{0}|{1}" -f $ServiceName, (Get-Date).ToString('MM-dd-yyyy HH-mm-ss');
(Get-Content -Path $Path) -replace ('([^|]+).*', $ReplaceString) | Set-Content $Path;