100

最近我不得不运行一个命令,不幸的是要求我在命令行上输入密码。

之后,我用“清除”清除了我的屏幕,但也想清除命令历史记录,这样有问题的命令就不会出现在会话历史记录中。不幸的是,Clear-History cmdlet 似乎并没有真正做到其文档所声称的 - 运行 Clear-History 似乎对会话历史没有任何影响。

我仍然可以在弹出的历史菜单中看到以前的命令,并通过按向上键滚动浏览旧命令。这是一个演示问题的屏幕截图:

PowerShell 清除历史记录失败

我已经使用Get-Command验证了Clear-History 确实正在执行预期的内置 PowerShell cmdlet。

我尝试了一些变体,例如“Clear-History -count 10 -newest”,但都没有显示出任何效果。当我指定一个准确的历史 ID,例如“Clear-History -id 3”时,我收到如下错误:

Clear-History : Cannot locate history for Id 3.

即使我可以在屏幕上看到命令#3。

4

4 回答 4

169

在 Windows 10上,历史记录和敏感数据会在以后的会话中再次出现,即使在 Alt+F7 和clear-history. 事实证明,历史记录存储在一个文本文件中,位于:

(Get-PSReadlineOption).HistorySavePath

从该文件中删除违规行并结束当前会话(或通过CB's answer清除它)。

您可以对此请求投赞成票,以便以更简单的方式暂时禁用历史记录。

于 2016-04-27T20:17:34.280 回答
92

tl;博士

  • 两个历史要清除

    • PowerShell 自己的 ( Clear-History)
    • 此外,在控制台(终端)中,在 PowerShell v5+ ( )PSReadLine中默认用于命令行编辑的模块[Microsoft.PowerShell.PSConsoleReadLine]::ClearHistory()
  • 版本 1.2+ 中PSReadLine(用 验证Get-Module PSReadLine) , press会为您Alt+F7执行两个调用,因此会完全清除会话中的历史记录

    • 但是,它不会清除到目前为止累积的已保存历史记录,因此即使已清除的会话的历史记录也会在以后的会话中重新出现。

    • 要清除保存的历史记录,您必须手动删除存储会话的文件( (Get-PSReadlineOption).HistorySavePath),如下所述,并由Clear-SavedHistory底部的函数包装。


为了补充CB. 的有用答案JVimes 的有用答案

  • PowerShell 自己的历史记录机制 ( Get-History, Clear-History) 是独立于主机的,这就是为什么 - 有点出乎意料 -您还需要单独清除主机的命令历史记录

  • 至于控制台主机自己的历史功能

    • doskey-style 历史功能PSReadline,在PowerShell 附带模块之前(见下文):

      • 没有保存的历史记录- 历史记录仅在当前会话期间保留。
      • Alt+F7必须用于清除控制台的历史记录,没有(明显的)编程方式(在cmd.exe您可以使用的控制台窗口doskey /reinstall中,但这在 PS 中不起作用)。
      • CB. 的回答向您展示了如何模拟这种键盘组合;请记住:除了 . 之外,还必须使用它Clear-History
    • PSReadline模块在 Windows 10 上随 PowerShell v5 和 v5.1 一起提供,还将随 Windows Server 2016 一起提供,并且还随跨平台Powershell (Core) v7+版本一起提供;它用更复杂的功能替换了doskey-style 行编辑和命令历史功能;也可以使用PowerShell 库(PSv3 和 PSv4 必须首先安装PowerShellGet)来改造旧的 Windows 版本/PS 版本(>= v3)版本。

      • 命令历史现在跨会话保存在文件中
        (Get-PSReadlineOption).HistorySavePath
      • [Microsoft.PowerShell.PSConsoleReadLine]::ClearHistory()可用于清除当前会话的历史(注意v1.2+还支持Alt+F7交互式清除当前历史)。
        • CAVEAT:使用PSReadline的默认历史保存样式,SaveIncrementally任何敏感命令在您调用时 已经保存[Microsoft.PowerShell.PSConsoleReadLine]::ClearHistory(),并将在下一个会话中重新出现
        • 处理此问题的唯一方法是删除保存的历史文件,如JVimes 的回答所示,然而,它总是会清除整个历史
        • 如果您将个人资料设置为Set-PSReadlineOption -HistorySaveStyle SaveAtExit每次会话开始时调用 - 该设置显然不会“坚持”本身 - 您应该能够只调用[Microsoft.PowerShell.PSConsoleReadLine]::ClearHistory()(除了Clear-History)而不必删除保存的历史文件,在这种情况下,您不会丢失以前会话中保存的历史记录。但是,从 v2.1.0(撰写本文时的最新版本)开始,SaveAtExit完全被破坏了- 根本没有保存任何历史记录;见https://github.com/lzybkr/PSReadLine/issues/262

以下高级功能捆绑了清除命令历史记录所需的所有命令(适用于 PowerShell 本身和控制台),适用于doskey-style 和PSReadline-module PowerShell 控制台窗口:

笔记:

  • 因为它是(当前)唯一安全的选项,所以PSReadline保存的历史文件也会被删除,这意味着整个历史记录,包括以前的会话,都会被清除

  • 因此,默认情况下会显示确认提示。

<#
# .SYNOPSIS
#  Clears the command history, including the saved-to-file history, if applicable.
#>
function Clear-SavedHistory {
  [CmdletBinding(ConfirmImpact='High', SupportsShouldProcess)]
  param(    
  )

  # Debugging: For testing you can simulate not having PSReadline loaded with
  #            Remove-Module PSReadline -Force
  $havePSReadline = ($null -ne (Get-Module -EA SilentlyContinue PSReadline))

  Write-Verbose "PSReadline present: $havePSReadline"

  $target = if ($havePSReadline) { "entire command history, including from previous sessions" } else { "command history" } 

  if (-not $pscmdlet.ShouldProcess($target))
  {
        return
  }

  if ($havePSReadline) {
    
    Clear-Host

    # Remove PSReadline's saved-history file.
    if (Test-Path (Get-PSReadlineOption).HistorySavePath) { 
      # Abort, if the file for some reason cannot be removed.
      Remove-Item -EA Stop (Get-PSReadlineOption).HistorySavePath 
      # To be safe, we recreate the file (empty). 
      $null = New-Item -Type File -Path (Get-PSReadlineOption).HistorySavePath
    }

    # Clear PowerShell's own history 
    Clear-History

    # Clear PSReadline's *session* history.
    # General caveat (doesn't apply here, because we're removing the saved-history file):
    #   * By default (-HistorySaveStyle SaveIncrementally), if you use
    #    [Microsoft.PowerShell.PSConsoleReadLine]::ClearHistory(), any sensitive
    #    commands *have already been saved to the history*, so they'll *reappear in the next session*. 
    #   * Placing `Set-PSReadlineOption -HistorySaveStyle SaveAtExit` in your profile 
    #     SHOULD help that, but as of PSReadline v1.2, this option is BROKEN (saves nothing). 
    [Microsoft.PowerShell.PSConsoleReadLine]::ClearHistory()

  } else { # Without PSReadline, we only have a *session* history.

    Clear-Host
    
    # Clear the doskey library's buffer, used pre-PSReadline. 
    # !! Unfortunately, this requires sending key combination Alt+F7.
    # Thanks, https://stackoverflow.com/a/13257933/45375
    $null = [system.reflection.assembly]::loadwithpartialname("System.Windows.Forms")
    [System.Windows.Forms.SendKeys]::Sendwait('%{F7 2}')

    # Clear PowerShell's own history 
    Clear-History

  }

}
于 2016-08-06T18:49:21.953 回答
46

要清除屏幕显示历史记录 ( F7),您必须按Alt+ F7

此历史记录由控制台缓冲区管理,而不是由可通过Clear-Historycmdlet 清除其历史记录的 PowerShell 管理。

要编写脚本,请尝试:

[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[System.Windows.Forms.SendKeys]::Sendwait('%{F7 2}')
于 2012-11-06T19:24:17.290 回答
2

根据@mklement0的最佳答案,我最终得到了下一个函数,该函数位于我的$PROFILE

我真的不关心任何其他会话,我只想清除那些愚蠢的历史,仅此而已。

Cmdlet 名称Clear-History尽可能地混淆。

# it's a default alias for Get-History cmdlet
Remove-Alias history

# Usage: history      - just print the history, same as call Get-History
# Usage: history -c   - really clears the history
function history {
    param (
        # Clears history
        [Parameter()]
        [Alias("c")]
        [Switch]
        $Clear
    )

    if ($Clear){
        Clear-History
        [Microsoft.PowerShell.PSConsoleReadLine]::ClearHistory()
        return
    }

    Get-History
}
于 2022-01-31T10:02:31.680 回答