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:
- Can I take a text screenshot of a GNU Screen session?
- Taking a screenshot of screen session over ssh
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