【问题标题】:powershell processing command outputpowershell处理命令输出
【发布时间】:2018-10-31 16:30:41
【问题描述】:

我希望我能在这里得到帮助。我喜欢 linux shell 脚本,因此我决定尝试使用 Windows Powershell 来应对以下挑战,但我失败了。

我想运行以下命令,将 GPU 温度和 CPU 利用率输出为第 4 列和第 5 列。如果第 4 列低于 50,或者第 5 列低于 80,我想重新启动系统。

"C:\Program Files\NVIDIA Corporation\NVSMI>nvidia-smi" --query-gpu=timestamp,name,pci.bus_id,temperature.gpu,utilization.gpu,utilization.memory --format=csv -l 5

命令每 5 秒打印一次的示例:

2018/05/21 21:21:54.118, GeForce GTX 1060 6GB, 00000000:01:00.0, 63, 100 %, 93 % 2018/05/21 21:21:59.121, GeForce GTX 1060 6GB, 00000000:01:00.0, 64, 100 %, 95 % 2018/05/21 21:22:04.122, GeForce GTX 1060 6GB, 00000000:01:00.0, 64, 100 %, 94 %

我可以使用 bash 轻松做到这一点,我将如何使用 Powershell 来解决这个问题?我希望学习这将使我了解 Powershell。谢谢。

【问题讨论】:

    标签: powershell command output


    【解决方案1】:

    我开始掌握这个窍门。 Powershell 知道输出的实际名称对我来说仍然很神奇。它是如何做到的?是看我传给命令的参数吗?

    这是我的新代码,如果温度低于 50,它将停止 ethminer 进程并重新启动它。问题是,一旦重新启动 ethminer,我让它等待 120 秒,但循环的下一次迭代是温度120 秒前。我必须打破循环还是有一种很酷的 Powershell 方法告诉它使用最后一个输出?

    $cmd = "& 'C:\Program Files\NVIDIA Corporation\NVSMI\nvidia-smi' --query-gpu=timestamp,name,pci.bus_id,temperature.gpu,utilization.gpu,utilization.memory --format=csv -l 5"
    
    invoke-expression $cmd | ConvertFrom-CSV | ForEach-Object {
      $_
      if ([int]$_.'temperature.gpu' -lt 50) {
        "temp $($_.'temperature.gpu') is less than 50 restarting ethminer"
        $process = Get-Process -Name "ethminer"
        Stop-Process -InputObject $process
        Get-Process | Where-Object {$_.HasExited}
        Start-Process "C:\Users\svill\Desktop\start - gpu 1.bat.lnk"
        Start-Sleep -s 120
      }
    }
    

    更新:这是代码的工作版本,一遍又一遍地运行命令,输出只有 1 行:

    $cmd = "& 'C:\Program Files\NVIDIA Corporation\NVSMI\nvidia-smi' --query-gpu=timestamp,name,pci.bus_id,temperature.gpu,utilization.gpu,utilization.memory --format=csv"
    
    while($true)
    {
      invoke-expression $cmd | ConvertFrom-CSV | ForEach-Object {
        $_
        if ([int]$_.'temperature.gpu' -lt 45) {
          "temp $($_.'temperature.gpu') is less than 45 restarting ethminer"
          $process = Get-Process -Name "ethminer"
          Stop-Process -InputObject $process
          Get-Process | Where-Object {$_.HasExited}
          Start-Process "C:\Users\svill\Desktop\start - gpu 1.bat.lnk"
          Start-Sleep -s 60
        }
        Start-Sleep -s 5
      }
    }
    

    【讨论】:

    • Select-Object -Last 1 from stackoverflow.com/questions/4546567/…
    • 或者,可以告诉nvidia-smi 只输出一 (1) 行吗?
    • 我尝试将 Select-Object -Last 1 作为循环中的最后一行,但不幸的是它不起作用,所以我选择了使用单个输出运行命令的路线,效果很好。跨度>
    • 减少数据的操作应尽早在管道中进行。我可能会将Select-Object -Last 1 放在ConvertFrom-CSV 之后(或之前)。
    • @lit 假设我有 6 行 GPU 统计数据通过一次运行命令输出,我想稍后打印这些数据,我是否必须创建一个数组来存储它以供检索?
    【解决方案2】:

    要克服的最大障碍是 PowerShell 的面向对象。

    要从熟悉的领域开始,您可以使用正则表达式从字符串中解析出数字。

    PS C:\src\t> $s = '2018/05/21 21:21:54.118, GeForce GTX 1060 6GB, 00000000:01:00.0, 63, 100 %, 93 %'
    PS C:\src\t> $s -match '.*, (\d*) %, (\d*) %$'
    True
    PS C:\src\t> $Matches
    
    Name                           Value
    ----                           -----
    2                              93
    1                              100
    0                              2018/05/21 21:21:54.118, GeForce GTX 1060 6GB, 00000000:01:00.0, 63, 100 %, 93 %
    
    
    PS C:\src\t> $Matches[1]
    100
    PS C:\src\t> $Matches[2]
    93
    

    向我们展示一些您可能从中创建的代码,有人可能会对进一步提出建议。

    【讨论】:

    • 它被导出为 csv。他实际上可以通过管道转换为从-csv
    • 好的,所以我尝试了以下操作,这让我大吃一惊:$cmd = "& 'C:\Program Files\NVIDIA Corporation\NVSMI\nvidia-smi' --query-gpu=timestamp,name,pci.bus_id,temperature.gpu,utilization.gpu,utilization.memory --format=csv -l 5" invoke-expression $cmd | ConvertFrom-CSV 它会自动将时间戳和名称等标签与正确的值相关联 - MAGIC。
    猜你喜欢
    • 2018-12-31
    • 1970-01-01
    • 1970-01-01
    • 2019-11-15
    • 1970-01-01
    • 1970-01-01
    • 2014-04-04
    • 2010-10-23
    • 1970-01-01
    相关资源
    最近更新 更多