Bash: capturing *Anything* which showed on screen

Hi,

I have a simple question about I/O redirection. the question is:
"How can I redirect all characters from a Bash screen to a file?"

Let me describe a little more: I know about I/O Redirection in Bash.
and also about stdin/stdout/stderr. something like: # ls 2>&1 1>ls.out

But! sometimes it's not possible to capture output of some Apps.
SSH is a good sample. I tried to capture a complete output of an
ssh session but it was not possible! when you are trying to do an
ssh for the first time, it will shows a message like this:

 
The authenticity of host '192.168.1.1 (192.168.1.1)' can't be established.
RSA key fingerprint is ****
Are you sure you want to continue connecting (yes/no)? 

And, this message couldn't be captured!

Any suggestions would be appreciated :slight_smile:

Certain things like ssh (and many other authentication systems) don't use stdin/stdout/stderr but directly open the controlling terminal, often /dev/tty (which on linux at least is kind of 'magic' in that /dev/tty is always your own terminal, no matter what that may be.) This happens after the shell runs the program, and can't be redirected.

You'd need to create your own virtual terminal device to intercept traffic at this level. The virtual terminal would be the controlling terminal and ssh would open and interact with it. This is how the expect language is able to interact with programs that demand a terminal device.

Thanks for these helpful information.

So, if it's using /dev/tty* why we can't redirect it? ("is kind of 'magic'"!)
Assume that we create a link from /dev/tty* to /dev/stdout and then handle it like any other output of stdout, isn't it possible?

Just as a Clarification:

Your shell can only redirect its own file descriptors. It can't stop any program from opening new ones.

Security-wise, unencrypted passwords are grade-A dangerous. They shouldn't ever get stored in any retrievable form, and should go directly from actual humans to system logins in as few vulnerable steps as possible.

The obvious way to tell a human apart from an intermediate program is that humans will always be found using terminals... ssh, and indeed most login systems(su, sudo), demand that an actual terminal be used to enter passwords. Pipes, files, and sockets won't do.

There's another property a process has beyond stdin/stdout/stderr, the controlling terminal. If there's a terminal in charge of a process, there's probably a logged-in human behind it that's using that terminal. They can be contacted directly via opening /dev/tty regardless of whether a program inherited any references to that terminal or not.

So, to guarantee that they're getting passwords from a human and not an automated password cracker or an in-between password recorder, and talking to a human and not a script -- and to let su - work even if it's crammed in the middle of a pipe chain! -- these things go directly to the terminal in charge of the process and accept nothing less.

/dev/tty knows what your terminal is without any effort on your part. Open it and it acts like you opened your proper terminal, which might be /dev/pts/3, or /dev/tty1, or any of a lot of possibilities.

No. It uses a system call to see whether what it's opened is actually a terminal. You'd probably mess up some important things by playing with device files like that anyway.

The solution is to open your own virtual terminal, and use that to control your program. It's as good as any other terminal as far as ssh's concerned. The expect language does this. Otherwise this'd mean some C coding.

1 Like

Your abstract questions of late need the context of a commercial requirement.

Hard to guess the requirement in this case:

1) If you are trying to write shell to answer the SSH question, it is better to configure the system so it does not ask the question.

2) If you just need to record screen output for documentation purposes, maybe consider quality PC-based terminal emulation software with screen logging features. This is not quite as sophisticated as it sounds because CRT terminals in the 1980s were capable of repeating the screen output to a serial port on the same terminal.

Ps. We don't want to make public information about unix terminal I/O which would assist anybody to write a keylogger, a password cracker or a virus.

1 Like

Whoa...dont you mean

ls 1>ls.out 2>&1

...the order IS important.

I would be surprised if you couldn't capture this....have you tried something like "script" ? That seems to capture my ssh sessions fine...
If that captures it, then anything can (cos it doesnt run setuid)

BTW, There are oddities that you have to be aware of, for example if you have:

cat /tmp/foo | more

The "more" command throws up a prompt onto the users screen, and waits for the user to press a key. This obviously isnt from stdin (as it takes that from the cat /tmp/foo). Actually what the shell does is to pass the stderr to the "more" command and the more command checks to see if that is attached to a tty and then does its input/output through that....but thats another story)

Although its theoretically possible for programs to open /dev/tty, this is almost never done by useful applications. This is because the shell would normally be in control of the tty, and uses it for job control. If another program opened /dev/tty and started trying to do I/O through it, the shell would probably quit out or get arsey.

I hope this makes things a little clearer

---------- Post updated at 11:48 PM ---------- Previous update was at 11:35 PM ----------

Yep, looking at script, it allocates a new pseudoterminal (pty), which pretends to be the logged in users tty. This is the same as "expect", and indeed exactly the same method that sshd and telnetd use to emulate terminals. If you look at the code to expect or script (or indeed sshd) you will see their method of allocating pty's and from there you can do interactive I/O to any process, even the ones, like passwd, that insist on a controlling pty.

---------- Post updated 01-26-11 at 12:03 AM ---------- Previous update was 01-25-11 at 11:48 PM ----------

(BTW, I just noticed your original question contained the sentence "I have a simple question about I/O redirection. "....So, I apologise for my over complicated answer...I realise now that it probably wasn't what you were after...)

1 Like

Messing with the terminal device is unwise. It can for example make your application behave as if it is in background.

I avoided mentioning the unix "script" command because it has many quirks and limitations. There was a lengthy thread on this subject some months ago.
The main issue with automation and the "script" command is with exiting "script" without typing ctrl/D on a real keyboard.
If anybody knows how to exit the unix "script" command from a shell script, please post now !

1 Like

Corona, methyl & citaylor Thank you very much.

@Crona:
Now I got what you mean and thanks for this valuable information.
So, I need some programming but between "expect" and "C Programming" I will choose the second one :wink:

@methyl:
You told that "CRT terminals in the 1980s were capable of repeating the screen output".
Could you please give me some more info about How they did that "repeating"?

@citaylor:
Yes, your answer was complicated but at last I figured it out :wink:
And many thanks for that "pseudoterminal (pty)" hint, I read the code before but I didn't get that ponit.

---------- Post updated at 11:06 AM ---------- Previous update was at 10:57 AM ----------

P.S: I'm going to build a simple remote system manager which will acts as a remote desktop but in text-mode. The difference is: Administrator from a single screen can connects, monitor and interact with N (>100) machines simultaneously.
So, It would not be a keylogger, password cracker or virus!!!

There is a version of Expect for Perl too if you are more familar with that...

Have you investigated the command "screen" at all ? Might give you some ideas...

Good luck

1 Like

yes, a little. but I will check it again if you think that would be helpful... :slight_smile:

One example of many was the DEC VT102 VDU Video Display Terminal Information ? VT100.net. It had a serial cable to the computer (or modem) and a serial output port for a printer. It was possible to pass control codes to the terminal to cause data to go to the printer or the screen or both. The feature is known as "passthru" and still exists in some modern terminal emulators. Most modern terminal emulators actually emulate the DEC vt220 which has a similar keyboard layout to a modern PC keyboard.

Attachmate Reflections unix terminal emulator includes a feature to log screen output to a file. The product also includes a keyboard scripting language where you can do "one button" full sessions.

Nothing bad happens with trivial examples.

$ cat /usr/share/dict/cracklib-small > /dev/tty
10th
1st
2nd
3rd
4th
...
zoroaster
zounds
z's
zucchini
zurich
zygote
$ read VAR < /dev/tty
asdf
$ echo $VAR
asdf
$cat < /dev/tty
asdf
asdf
qwertyuiop
qwertyuiop
^D
$

And almost nothing bad happens with non-trivial examples:

$ cat /lib/libc.so.6 > /dev/tty
<unending pages of garbage>
$ 6;92;c^C
$ nano > /dev/tty < /dev/tty 2> /dev/tty
(normal nano behavior)
$

Which makes sense when you think about it. (nearly) any program run by the shell runs gets direct read/write access to the terminal from the get-go anyway -- if your program gets access to the terminal at all, the shell can't intermediate how you talk with it. Programs deal with the terminal direct. Reopening the terminal device isn't really different from the access you'd get from the first.

Now if that program started altering terminal settings out from under the shell that might be a different matter -- except the shell also runs programs that alter terminal settings all the time: Interactive editors, less, top, and others. The shell's expected to not go weird when running these. As long as they politely leave the terminal as they found it when they're done, nothing explodes. Even when they don't, reset\n is usually enough to put things where they belong.

In many shells, it's actually switching terminal modes by itself all the time -- putting the terminal into canonical mode whenever you run something, and switching back to non in order to process raw keystrokes. Any shell that lets you edit the commandline in a vi or emacs like fashion does this.

Finally:

$ ssh some.server.or.other > /dev/null 2> /dev/null < /dev/null
Password:

It's able to prompt me for a password with no open references to the terminal at all! When I strace it and grep for /dev/tty, it finds this:

open("/dev/tty", O_RDWR)                = 5

So ssh is quite prepared to go to the source when no other means is available.

(on further checking: In fact it seems to do so even when other means are available.)