【问题标题】:Scheduled script does not redirect output to file预定脚本不会将输出重定向到文件
【发布时间】:2016-06-05 03:34:23
【问题描述】:

我有两个类似的 PowerShell 脚本来备份文件(第一个清除网络驱动器,第二个执行实际备份)配置为每天在同一个 Windows 调度程序任务中运行(只是不同的操作):

Action: Start a program
Program/script: powershell.exe
Add arguments (optional): -command C:\Webs\Scripts\purgar-backups-dinahosting.ps1 > C:\Webs\Scripts\purgar-backups-dinahosting.log 2>&1

Action: Start a program
Program/script: powershell.exe
Add arguments (optional): -command C:\Webs\Scripts\backup-dynahosting.ps1 > C:\Webs\Scripts\backup-dynahosting.log 2>&1

我得到了预期的日志文件,但第一个总是空的(0 字节)。如果我只是从命令提示符运行命令,我会得到实际输出:

powershell.exe -command C:\Webs\Scripts\purgar-backups-dinahosting.ps1 > C:\Webs\Scripts\purgar-backups-dinahosting.log 2>&1

... 唯一的特点是它使用 Unix 换行符 (:-!)。鉴于:

  1. 两个脚本都使用 Windows 换行符保存
  2. 两个脚本都使用Write-Host 生成输出

什么可以解释第一个脚本中的那些奇怪之处1

(1) 这是代码:

$LetraUnidad = "X:"

$RecursoNFS = "xxx_removed_xxx.dinaserver.com:/usr/containers/xxx_removed_xxx"

$EspacioContratado = "xxx_removed_xxx"

$LimitePorcentaje = "xxx_removed_xxx"



Write-Host "Verificando si ya está montada la unidad de red en $LetraUnidad..."
$UnidadRed = New-Object System.IO.DriveInfo($LetraUnidad)
if ($UnidadRed.IsReady)
{
    Write-Host "Unidad de red disponible"
}
else
{
    Write-Host "Unidad de red no disponible, montando unidad..."
    net use $LetraUnidad $RecursoNFS

    if ($UnidadRed.IsReady)
    {
        Write-Host "Unidad de red disponible"
    }
    else
    {
        Write-Host "Se ha producido un error al intentar montar la unidad de red"
        exit
    }    
}



Write-Host "Obteniendo datos de espacio de la unidad $LetraUnidad..."

$EspacioOcupado = ((Get-ChildItem $LetraUnidad -Recurse | Measure-Object -property length -sum).sum) /1gb
$EspacioLibre = $EspacioContratado-$EspacioOcupado
$PorcentajeEspacioOcupado = ($EspacioOcupado*100/$EspacioContratado)


Write-Host "Espacio total:        " ([System.Math]::Round($EspacioContratado, 2)) " GB"
Write-Host "Espacio libre:        " ([System.Math]::Round($EspacioLibre, 2)) " GB"
Write-Host "Espacio ocupado:      " ([System.Math]::Round($EspacioOcupado, 2)) " GB"
Write-Host "Porcentaje ocupación: " ([System.Math]::Round($PorcentajeEspacioOcupado, 2))"%"
Write-Host

Write-Host "Comprobando si es necesario eliminar archivos..."
if($PorcentajeEspacioOcupado -gt $LimitePorcentaje)
{
    Write-Host "Poco espacio disponible, eliminando archivos..."
}
else
{
    Write-Host "Espacio disponible suficiente, no es necesario eliminar archivos"
    exit
}



foreach ($file in Get-ChildItem -path X: | where-object{-not $_.PSIsContainer} | sort -property LastWriteTime)
{
    Write-Host "Eliminando " $file.FullName
    del $file.FullName

    $EspacioOcupado = ((Get-ChildItem $LetraUnidad -Recurse | Measure-Object -property length -sum).sum) /1gb
    $EspacioLibre = $EspacioContratado-$EspacioOcupado
    $PorcentajeEspacioOcupado = ($EspacioOcupado*100/$EspacioContratado)

    if($PorcentajeEspacioOcupado -lt $LimitePorcentaje)
    {
        Write-Host
        exit
    }
}

【问题讨论】:

  • CMD 将 >2>&1 解释为重定向运算符并自行处理它们,而不会将它们传递给 PowerShell。任务调度程序将参数解释为文字字符串。这样,>2>&1 将被传递给 PowerShell 并由 PowerShell 处理。并且 PowerShell 知道,该主机流不应该被 > 操作符重定向。
  • @PetSerAl 感谢您的提醒。我从来没有真正理解为什么或何时需要将我的操作分成三个(小)文本框;这些设置实际上是一些谷歌寻宝游戏的结果。运行 *.ps1 并将其输出发送到文件的正确方法是什么?
  • 一种不需要您修改脚本的方法是:program: cmdarguments: /c powershell -command C:\Webs\Scripts\backup-dynahosting.ps1 > C:\Webs\Scripts\backup-dynahosting.log 2>&1。跨度>
  • @user4003407 这行得通,对我没有其他作用......需要指出它应该是 -file 来运行 ps1

标签: powershell scheduled-tasks powershell-3.0 windows-server-2012-r2


【解决方案1】:
Write-Host

可能不是适合该工作的工具。 由于它旨在直接将输出写入用户控制台(脚本主机)而不实际产生输出,例如重定向或管道。

它对于编写您不想在日志中看到但只能在交互式会话中看到的调试、报告或进度输出非常有用。 或者对于来自内部函数的消息,不应该“返回”该消息

尝试使用

Write-Output 

对于您希望脚本输出的所有内容。小心内部函数。

http://www.jsnover.com/blog/2013/12/07/write-host-considered-harmful/

【讨论】:

  • 就是这样!不知道为什么其他脚本确实生成了正确的日志文件,但老实说我不在乎 :)
  • '>' 告诉脚本宿主重定向脚本的输出。它不是脚本本身的一部分。我可以想象,当您使用不同的主机(powershell.exe 与 windows sheduler)运行脚本时,重定向的完成方式不同。但不管它是什么,它现在似乎工作了。感谢您将我的答案标记为已验证:)
  • 哦,在上面的评论中提出问题:尝试使用Start-Transcript -Append -Path $logFile
  • 这越来越疯狂了...我在 other 脚本(正在运行的脚本)中将Write-Host 替换为Write-Output,现在我的计划任务得到了永远停止运行并且没有做任何真正的工作......我想我只会在一个脚本中进行更改并继续前进。
  • 顺便说一句,Start-Transcript -Append -Path $logFile 到底是什么意思?任务调度程序为每个任务提供三个不同的输入框:-!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-31
  • 1970-01-01
  • 2018-01-11
  • 2020-03-22
  • 1970-01-01
相关资源
最近更新 更多