64

I need to hook onto output of currently running terminal (tty1) from virtual terminal and capture it (running X server).

3
  • 6
    While I understand that sometimes the need arises to capture content on another tty after a command is running, an ounce of prevention is worth a pound of cure, so always consider starting using screen or tmux before starting a command that you may want to access from another terminal.
    – depquid
    Apr 14, 2013 at 20:33
  • And when you can prepare it before, maybe also tmate would be a nice candidate that even works across the internet and not only local. (and has optional write access)
    – rugk
    Feb 27, 2019 at 0:39
  • duplicate of Take text "screenshot" of current terminal contents
    – milahu
    Apr 3, 2022 at 8:32

9 Answers 9

32

I came across this one tool called ttylog. It's a Perl program available on CPAN here. It has a couple caveats, one being that I could only figure out how to attach to a terminal that was created as part of someone ssh'ing into my box. The other being that you have to run it with elevated privileges (i.e. root or sudo).

But it works!

For example

First ssh into your box in TERM#1:

TERM#1% ssh saml@grinchy

Note this new terminal's tty:

TERM#1% tty
/dev/pts/3

Now in another terminal (TERM#2) run this command:

TERM#2% ttylog pts/3
DEBUG: Scanning for psuedo terminal pts/3
DEBUG: Psuedo terminal [pts/3] found.
DEBUG: Found parent sshd pid [13789] for user [saml]

Now go back to TERM#1 and type stuff, it'll show up in TERM#2.

ss of terminals

All the commands I tried, (top, ls, etc.) worked without incident using ttylog.

4
  • Exactly what I've been looking for (I've used it in the past, but forgot the name and couldn't remeber). Many thanks, I temporarily used dirty option (gdb and output replication). Apr 13, 2013 at 23:40
  • Yes, the gdb was the first option I came across, I've used it myself in the past, but it's hacky, to me at least. Glad this helped you out!
    – slm
    Apr 13, 2013 at 23:43
  • 2
    ttylog can't seem to attach to the correct process though - can anyone answer my question: serverfault.com/questions/560972/… Dec 12, 2013 at 17:05
  • @slm I have issues usin gthe command - could you please check this question: unix.stackexchange.com/questions/678315/ttylog-no-device-is-set
    – laplasz
    Nov 21, 2021 at 10:52
26

Look at:

man 1 script

For example:

script -f /dev/tty1

Source

3
  • I was looking for this. Trying to attach by screen failed miserably. It works.
    – user80158
    Jul 19, 2017 at 13:06
  • 1
    IIUC, your example would need to be run before the program you want to monitor, and it is using /dev/tty1 as the output (where it's writing the captured I/O). This is handy, but it's not solving the original problem. i.e. it is not grabbing the output on /dev/tty1 and showing it but rather the reverse.
    – jacobq
    May 26, 2021 at 18:27
23

Indeed it is. The /dev/vcs* and /dev/vcsa* devices corresponds to the /dev/tty* devices (the virtual terminals). F1=tty1=vcs1/vcsa1 and so on. The vcs/vcsa is like tty for the "current" virtual terminal.

As root, you can just cat these devices (e.g. cat /dev/vcs2), and see what's on the corresponding VT (e.g. /dev/tty2 the on on F2) like taking a snapshot. vcsa* differs from vcs* in that they include information about the dimensions of the terminal (the screen). Mind you, it's just a raw snapshot of the characters as they show on the screen - gathered from the memory allocated to the terminal - so don't expect nice, easily parseble output.

The drawback is that if the information flashes past too fast, it may be difficult to capture. Perhaps tail -f /dev/vcs1 will work, if you need to follow several screenfulls (haven't tried myself)? It may be easiest to simply redirect it to a file first. It may also be a good idea to use a VT (F1-F6) to look at it, as the terminals will have the same dimensions. In my experience, it's best to use the vcs* - not the vcsa* - devices.

If that doesn't work, perhaps one of the "big brotherish" packages that allows an admin to keep an eye on the activity on a terminal may work.

PS: I forgot to ask what OS you use. This is for Linux, though similar devices probably exists on other OSes too. Try searching for "virtual console memory" among the man-pages for devices.

3
  • Is there any way to inject input into tty1 from ssh? For example I need to work with a raspberry pi running Debian, but the problem is that it has only one usb port, it is taken up by the wifi adapter, and so I can't physically attach a keyboard to use tty1 with it. Since I need to run a script that, during the process of executing, shuts down wlan0, I actually have a catch-22 situation trying to debug where this script is failing. Suppose I can't use a usb hub... is there a way for me to pipe chars into /dev/tty1 somehow?
    – Steven Lu
    Oct 8, 2014 at 0:40
  • 2
    Well. I'm able to pipe stuff to /dev/tty1 as root but all this does is display the characters to the screen, not enter them
    – Steven Lu
    Oct 8, 2014 at 0:41
  • 1
    Sorry if this is just noise. it's not really 100% relevant. But I answered my question in the comment above with this
    – Steven Lu
    Oct 8, 2014 at 0:50
9

Use the tty command in each terminal to identify them:

$ tty
/dev/pts/0

$ tty
/dev/pts/1

Assuming these TTYs, to redirect the first's stdout to the second, run this in the first terminal:

exec 1>/dev/pts/1

Note: Now every command output will show on pts/1

To restore default behavior stdout of pts/0:

exec 1>/dev/pts/0

See this video for a demonstration.

1
  • 2
    While this is useful if you have access to both terminals, it doesn't help if there's a terminal open that you don't have access to (i.e. a terminal spawned by a subprocess or detached terminal). Jan 30, 2020 at 16:35
3

This worked for me:

  • Using a keyboard on computer "A" (i.e. the physical computer that's to be controlled), run: screen -q

  • Connect with ssh from computer "B" to computer "A".

  • In the ssh session, type: screen -ls to get a session id to connect to (4 digits on the row that contains tty).

  • Connect to the above session with: screen -x <session id> ... using the session id number received from the screen -ls command above.

Anything typed in either "session" will happen in both "sessions", so for example typing screen -d will quit BOTH sessions.

3

Open two terminals. Type tty in each and you'll get it's id as /dev/pts/nº

Then in the first you type script -f /dev/pts/nºofSecondTerminal and in the second you do the opposite script -f /dev/pts/nºofFirstTerminal so they get linked

Congrats! Both terminals outputting and receiving the same stuff. Need a third ? Well, have you studied combinations ? You'll need 6 script -f commands. Even More tty ? So on...

2

I'm sort of shocked folks are using a perl script to do this when there's a much better, modern solution.

Check out reptyr. From the readme:

reptyr is a utility for taking an existing running program and attaching it to a new terminal. Started a long-running process over ssh, but have to leave and don't want to interrupt it? Just start a screen, use reptyr to grab it, and then kill the ssh session and head on home.

Using it is really simple. Just install:

apt install repytr

Then move a program from one tty to the current one:

repytr SOME_PID

Easy-peasy.

1

Another approach is to use the gnu screen utility on your local machine. Invoke it with the -L option, or start without that option and use the ^aH command sequence. Either approach causes all input & output to be logged to a file named screenlog.x where x is the screen number.

This is a handy because nothing extra needs to be installed on the remote machine.

1

Since I didn't start tty1 with screen this script helped:

I used the answer from Baard Kopperud above. "128" is 1 line of my tty1. Sleep can be set to an appropriate number.

#!/bin/bash
while true
do
    sudo tail -c 128 /dev/vcs1 && echo ""
    sleep 10
done

I used this in terminator and sized the column so the scroll is one line of text.

1
  • Thanks for the idea, on the rasperry I simply had to do '''watch cat /dev/vcs''' To watch a process I started on a virtual console forgetting about using 'screen'. And I just adjusted my gnome-terminal i ran this in to be 80 characters wide.
    – axkibe
    Sep 13, 2017 at 12:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .