Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I have sshed into a linux box and I'm using dvtm and bash (although I have also tried this with Gnu screen and bash). I have two terminals, current /dev/pts/29 and /dev/pts/130. I want to redirect the input from one to the other.

From what I understand, in /dev/pts/130 I can type:

cat </dev/pts/29

And then when I type in /dev/pts/29 the characters I type should show up in /dev/pts/130. However what ends up happening is that every other character I type gets redirected. For example, if I type "hello" I get this:

/dev/pts/29        |        /dev/pts/130

$                  |        $ cat </dev/pts/29
$ el               |        hlo

This is really frustrating as I need to do this in order to redirect the io of a process running in gdb (I've tried both run /dev/pts/# and set inferior-tty /dev/pts/# and both resulted in the aforementioned behavior). Am I doing something wrong, or is this a bug in bash/screen/dvtm?

share|improve this question

2 Answers 2

up vote 7 down vote accepted

In your simplified example, you have two processes (your shell, and the cat) trying to read from the “slave” side of the tty. The result is that one process gets some of the characters, the other gets the others.

What do you mean by “redirect the input from one [terminal] to the other”? In your real situation, what processes are trying to read from each terminal? What do you want to do with your captured input once you have it? What, exactly, are you actually trying to accomplish?

To me, “redirect the io of a process running in gdb” seems more like re-opening stdin/stdout/stderr inside a process that is already running.

You can change stdin/stdout/stderr of a running process with (among other things) GDB. An answer to “Redirect STDERR / STDOUT of a process AFTER it’s been started, using command line?” shows how it can be done. You would want to substitute a tty pathname for /dev/null in the answer, and you probably want to handle stdin, too, but the technique is still applicable.


You should be able to make your simplified example work robustly, but I am not convinced that it does what you actually want to do (keep in mind that a pseudo terminal is actually a pair of devices, like two ends of a bidirectional pipe; but all your example does it interact with the ‘slave’ halves).

The key to fixing your example is to get all but one of the competing process to (temporarily) stop read from the terminal. If, like your example, you have a shell running on the side from which you would like to capture data, then you can do something like this:

(
    s="$(stty -g)"
    exec 3<&0
    trap 'stty "$s" 0<&3;exit' 0 INT QUIT

    cat <<EOM
In some other terminal, run the command

    cat <$(tty)

Press ^C or ^\ to quit.
EOM

    stty raw isig brkint susp '' dsusp ''
    while true; do sleep 3600; done </dev/null
)
share|improve this answer
    
My goal was to run a process within gdb, but interact with the process in another terminal. This was prompted because I set up pyclewn and when run in a terminal it redirects the process' io to /dev/null making it impossible to interact with. However I just realized that I'm an idiot since I can just attach gdb to a process running in a separate terminal completely bypassing my problem. –  Niki Yoshiuchi May 26 '10 at 21:23
    
I was looking for this too (debug curses with curses). It deserve itself an sole explanation. Save old stdin, reload old stdin on quit, and best of all unbuffered input. Anyway it's not working perfect on Ubuntu. A reset is needed at exit, but using man should be enough to tweak it, great! –  albfan Jun 16 at 21:08

Very interesting. I have not seen that done before... the way you have it working anyway. I confirmed on my computer that your technique seems to randomly decide if its going to send the character over to the other terminal.

I've seen something similar done... which works a bit differently. You can directly send text to another terminal with this:

echo "hello" >/dev/pts/1

where /dev/pts/# is the number you get when you use the tty command on the remote terminal.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.