Shell

獲取目前終端內容的文本“截圖”

  • April 3, 2022

我想每隔 30 秒左右將某個終端或終端仿真器的所有文本複製到一個文件中,並以conky. 我不是在談論簡單的重定向 ( command > file),它不適用於 ncurses 程序或 NetHack 等遊戲。

我怎麼能這樣做呢?

沒有可移植的方式要求終端仿真器進行螢幕轉儲。您可以通過在 GNU screen 或 tmux 中執行您的應用程序並使用它們來執行螢幕轉儲來解決此問題。

GNU screen 可以做到這一點:

同樣,有一個tmux 外掛可以進行螢幕截圖。

擷取程序的可見輸出(文本截圖)

這將呈現特殊字元,如輸入 ( \r) 和其他終端控制程式碼,因為它們對人類可見

例如,一個實時進度條應該產生

[================================>] 100%          

並不是

[==>                               ]  9%
[========>                         ] 28%
[==============>                   ] 47%
[=====================>            ] 65%
[===========================>      ] 84%
[================================>] 100%
#! /usr/bin/env bash

# text screenshot
# capture the visible output of a process
# https://unix.stackexchange.com/a/697804/295986

captureCommand="$(cat <<'EOF'
 # example: progress bar
 # https://stackoverflow.com/a/23630781/10440128
 for ((i=0; i<100; i++)); do
   sleep 0.1
   printf .
 done | pv -p -c -s 100 -w 40 > /dev/null
EOF
)"
# note: to stop the captureCommand after some time
# you can wrap it in `timeout -k 60 60`
# to stop after 60 seconds
# or use `for waiterStep in $(seq 0 60)`
# in the waiter loop

# create a new screen session. dont attach
screenName=$(mktemp -u screen-session-XXXXXXXX)
screen -S "$screenName" -d -m

# create lockfile
screenLock=$(mktemp /tmp/screen-lock-XXXXXXXX)
# remove lockfile after captureCommand
screenCommand="$captureCommand; rm $screenLock;"

echo "start captureCommand"
# send text to detached screen session
# ^M = enter
screen -S "$screenName" -X stuff "$screenCommand^M"
hardcopyFile=$(mktemp /tmp/hardcopy-XXXXXXXX)

enableWatcher=true
if $enableWatcher; then
 echo "start watcher"
 (
   # watcher: show live output while waiting
   while true
   #for watcherStep in $(seq 0 100) # debug
   do
     sleep 2
     # take screenshot. -h = include history
     screen -S "$screenName" -X hardcopy -h "$hardcopyFile"
     cat "$hardcopyFile"
   done
 ) &
 watcherPid=$!
fi

echo "wait for captureCommand ..."
while true
#for waiterStep in $(seq 0 60) # debug
do
 sleep 1
 [ -e "$screenLock" ] || break
done
echo "done captureCommand"

if $enableWatcher; then
 kill $watcherPid
fi

# take a last screenshot
screen -S "$screenName" -X hardcopy -h "$hardcopyFile"
echo "done hardcopy $hardcopyFile"

# kill the detached screen session
screen -S "$screenName" -X quit

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