如何在 shell 中从提示符停止执行命令?

如何在 shell 中从提示符停止执行命令?

我的提示符包含有关当前目录下 git repo 的一些信息。当我做某事时cd,我的 shell 会执行一些命令(即git status)。

有没有办法通过同一终端停止执行此类命令?从键盘发送信号(例如通过Ctrl+ c)不起作用。

更新#1

我不想永久禁用这些命令 - 我只是希望它们开始运行然后在运行时停止它们。

答案1

这些命令是某种形式的 shell 的子进程。如果您pstree -p $$会列出当前在您的 shell 下运行的进程。然后您可以运行与 Ctrl-C (SIGINT) 相同的终止命令。这是一个手动后台命令的示例,但它对于您的提示更新应该是相同的。作为解释,$$pstree 是 shell 进程 id 的替代品,pstree 将显示父/子关系中的所有进程,并且 -p 选项将其限制为当前 shell。当然不要杀死你的shell pid,只杀死你想杀死的孩子。

$ find / 2> /dev/null > /dev/null &
[1] 916595
$ pstree -p $$
bash(915332)─┬─find(916595)
             └─pstree(916598)
$ kill 916595
[1]+  Terminated              find / 2> /dev/null > /dev/null
$
`

答案2

如果你这样做:

PS1='$(set -x; sleep 3; echo STATUS)$ '

你会发现这^C有效。只是 bash 尝试重新绘制提示符并sleep 3再次运行。

同样的情况:

$ PROMPT_COMMAND='git_status=$(set -x; sleep 3; echo STATUS)' PS1='$git_status$ '

这可以通过以下方法解决:

PROMPT_COMMAND='
  interrupted=0
  trap interrupted=1 INT QUIT
  git_status=$(set -x; sleep 3; echo STATUS)
  trap - INT QUIT
  if (( interrupted )); then
    git_status+="<INTERRUPTED>"
  fi'
PS1='$git_status$ '

我们在 SIGINT 上添加一个处理程序。当信号被处理并$PROMPT_COMMAND正常完成时,bash 不会重绘提示符。我们还可以在提示符中添加命令被中断的信息。

您可以将set -x; sleep 3; echo STATUS此处用作示例占位符的内容替换为您的占位git status符或同等内容。


在 zsh 中,您可以使用以下命令执行类似且更干净的操作:

precmd() {
  set -o localoptions -o localtraps
  local interrupted=0
  trap interrupted=1 INT QUIT
  psvar[1]=$(set -x; sleep 3; echo STATUS)
  if (( interrupted )) psvar[1]+='<INTERRUPTED>'
}
PS1='%1v$ '

答案3

您是否使用 bash(echo $0 查看)?如果cd没有别名为其他内容(尝试unalias cdunset cd),那么我怀疑 shell 启动中的某些内容导致了此行为。在 bash 上,这可能位于 .profile、.bashrc 或系统 bashrc 中。在超级用户,建议是--noprofile --norc在 ssh 进入盒子时使用,或者在仅从现有终端中调用新终端时使用。所以,

  • 以调用 Bash 的方式启动,sh无需 .bashrc。您可以在“错误”终端会话中执行此操作
  • ssh -t [email protected]并且-t会绕过bashrc(没有尝试过)
  • ssh [email protected] bash --noprofile --norc听起来更安全(没试过)

相关内容