实时输出不占用当前提示位置的命令?

实时输出不占用当前提示位置的命令?

我有命令:ps -o pid,user,%cpu,command | head -n 30

我想打印上述命令的输出并更新它,但保持打印与之前的输出相同,而不刷新整个终端(alacrtty)。

基本上,目的是运行脚本并实时观察 ps 命令的变化,但不会弄乱当前提示位置,并且不应刷新 how 终端(这可能导致闪烁)。

我尝试了watch命令,但它会吞掉整个终端/tmux 的窗格。

我也尝试过 tput 但无法让它工作。

先谢谢了。

答案1

假设终端光标下方至少有 30 行,并且您的终端支持这些转义序列,您可以使用sc(保存光标) 和rc(恢复光标) 转义序列:

tput sc
while true; do
  tput ed
  ps -o pid,user,%cpu,command | head -n 30
  tput rc
  sleep 1
done

(如果您不支持/ / ...,另请参阅echoti sc或)。$terminfo[sc]zshtputscrced

要在运行时隐藏光标,并在每次提示之前未执行此操作的 shell 中断时清除屏幕底部,您可以这样做。

my_processes() (
  trap 'tput rc; tput ed; tput cnorm; exit' EXIT INT
  tput sc; tput civis
  while true; do
    tput ed
    ps -o pid,user,%cpu,command | head -n 30
    tput rc
    sleep 1
  done
)

ed您可以通过减少序列和输出之间的延迟来减少闪烁ps

my_processes() (
  for c in sc rc ed cnorm civis; do eval "$c=\$(tput $c)"; done

  trap 'printf %s "$rc$ed$cnorm"; exit' EXIT INT

  printf %s "$sc$civis"

  while true; do
    printf %s "$ed$(ps -o pid,user,%cpu,command | head -n 30)$rc"
    sleep 1
  done
)

这些terminfo功能在手册页中进行了描述terminfo(5)

  • sc:保存当前光标位置
  • rc: 将光标恢复到最后一个save_cursor:的位置
  • ed:清除到屏幕末尾
  • civis: 使光标不可见
  • cnorm:使光标正常显示(撤消civis/ cvvis)。
  • cuu <n>1:光标向上<n>

(在 中zsh,您可以跳过声明所有这些$sc/ $rc... 变量并使用$terminfo[sc]...)

在 中zsh,您还可以使用其调度程序在 zle 消息区域中显示ps输出,同时仍然能够使用 shell(尽管这会使完成操作更难使用):

zmodload zsh/sched
my-processes() {
  if [[ $1 = stop ]]; then
    sched -$zsh_scheduled_events[(i)*:$0]
  else
    if {zle} zle -M "$(ps -o pid,user,%cpu,command | head -n 30)"
    sched +1 $0
  fi
}

运行my-processes开始和my-processes stop停止。您可以通过按键来打开和关闭它:

toggle-my-processes() {
  local event
  if (( event = zsh_scheduled_events[(I)*:my-processes] )); then
    sched -$event
    zle redisplay
  else
    my-processes
  fi
}
zle -N toggle-my-processes
bindkey '\ep' toggle-my-processes

(这里绑定的是ESC p字符序列,一般是按Alt+时终端发送的P


yes '' | head -n30; tput cuu 30如果您愿意,您可以运行以确保光标下方有 30 行。但如果您要报告的进程较少,则可能没有必要。

相关内容