Take text “screenshot” of current terminal contents

I would like to, every 30 seconds or so, copy all text of a certain terminal or terminal emulator to a file, and display it in conky. I’m not talking about simple redirection (command > file), which doesn’t work for ncurses programs or games such as NetHack.

How could I go about doing this?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

There is no portable way to ask a terminal emulator to do screen dumps. You can work around this by running your application in GNU screen or tmux and using them to carry out the screen-dumps.

GNU screen can do this:

Likewise, there is a plugin for tmux to do screen captures.

Method 2

capture the *visible* output of a process (text screenshot)

this will render special characters like carriage return (r) and other terminal control codes as they would be visible to a human

for example, a live progress bar should produce

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

and not

[==>                               ]  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


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x