Linux

實時輸出不佔用目前提示位置的命令?

  • July 2, 2021

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

我想列印上述命令的輸出並對其進行更新,但在不刷新整個終端(alacritty)的情況下保持與先前輸出相同的列印輸出。

基本上目的是執行腳本並實時觀察 ps 命令的變化,但不會弄亂目前提示位置,並且不應該刷新終端(可能導致閃爍)。

我嘗試watch了命令,但它會吞噬整個終端/tmux 的窗格。

我也嘗試過 tput 但無法正常工作。

先謝謝了。

假設終端在游標下方至少有 30 行¹,並且您的終端支持這些轉義序列,您可以使用sc(save cursor) 和rc(restore cursor) 轉義序列:

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]在中)。zsh``tput``sc``rc``ed

要在執行時隱藏游標並在每次提示之前沒有執行此操作的外殼中斷時清除螢幕底部,您可以做到。

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>¹:游標向上<n>

(在 中zsh,您可以跳過聲明所有這些$sc/ $rc… 變數並使用$terminfo[sc]…)

zsh中,您還可以使用它的調度程序ps在 zle 消息區域中顯示該輸出,同時仍然能夠使用 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 行。如果您要報告的流程較少,這可能沒有必要。

引用自:https://unix.stackexchange.com/questions/656713