BigAdmin System Administration Portal
Community-Submitted Article
Print-friendly VersionPrint-friendly Version
This content is submitted by a BigAdmin user. It has not been reviewed for technical accuracy by Sun Microsystems, though it may have been lightly edited to improve readability. If you find an error or would like to comment on the article, please contact the submitter or use the comment field at the bottom of the article. Community submissions may not follow Sun trademark guidelines. For information on Sun trademarks, please see http://www.sun.com/suntrademarks/.
 
 

Saving and Handling Your Terminal Output

István Bátori, April 2007

One of the classic UNIX commands is the script utility. This article shows you how to use this utility.

Note: These steps work on the Solaris OS for releases 8, 9, and 10; I haven't tested it on other operating systems.


A Common Way to Use the script Utility

The script utility simply starts a new shell and collects all the terminal input and output to a file:

# script utility starts a new shell
script /tmp/myterminal.log
pwd
ls
# and everything you see is in the /tmp/myterminal.log
....
# exit from the shell and close the log file
exit

It's great and it's easier to use than the following, well-known output redirection:

<command> 2>&1 | tee /tmp/command.log

What is the difference between script logging and output redirection? With script logging, all input characters, even the Backspace or the cursor moving between characters, are included in the script output. Using script logging has advantages and disadvantages. One disadvantage is that the log file is less readable, because it contains Ctrl-M and other nasty characters. Let's look at the advantages of using script logging and the benefits that result from them!


Showing Your Terminal Window to Others

Script output can be redirected to another terminal to show what you see or what you are doing. Suppose you have a problem and you call a colleague by phone to ask for help. Your colleague is not sitting next to you. However, if both of you can log in to the same server, you can redirect your terminal output to your colleague's terminal.

Since both of you need to log in to the same server, ask your colleague to get his or her terminal device, which can be found by using the following command:

tty

Or you can find it out yourself with the following command:

who | grep <colleague's user name>

Type the following into your terminal:

script /dev/null | tee -a <colleague's terminal>

Here is an example:

script /dev/null | tee -a /dev/tty3

It's wonderful! Everything you type, and everything you do, is shown on your colleague's terminal. If you edit a file using vi, if you move your cursor, if you log in to another server, it's all shown on your colleague's terminal. One small tip: tell your colleague your terminal size and ask your colleague to resize his or her terminal to the same size. Otherwise, your colleague will lose readability in some circumstances, such as when you are working in vi.

Maybe you are wondering why you can't simply use this command:

script /dev/tty<number>

The previous command is OK, but if you use it, the output is cached. Therefore, your typing cannot be followed directly character by character. Instead, your typing is followed only line by line. Editing in vi is not followed either.

It is possible to save the output in a file:

script /dev/null | tee /tmp/myterminal.log

And your colleague can join you to view this later:

tail -f /tmp/myterminal.log

Logging Your Login Sessions Automatically

You can use the script utility to log an entire login session to a separate file, and you can check the file later to see what you did in the past. Create the ~/tmp/log_session directory and put following lines into your .profile file:

if [ -z $FIRST_LOGIN ]; then
  FIRST_LOGIN="no"
  export FIRST_LOGIN
  exec script ~/tmp/log_session/session.`date +%Y.%m.%d.%H_%M_%S_%Z`.$$
  # never come here
  exit;
fi

I prefer the Bash shell, but there is a small problem with it. The script utility starts whatever shell is specified by the SHELL variable. However, script starts the shell using the name sh. If you start the Bash shell with a program name of sh, Bash mimics the classic Bourne shell, as described in the bash man page. The solution is to implement the following helper script: start_bash.sh:

$cat ~/bin/start_bash.sh
#!/usr/bin/sh
exec bash

The invocation in .profile is changed to the following:

if [ -z $FIRST_LOGIN ]; then
  FIRST_LOGIN="no"
  export FIRST_LOGIN
  export SHELL=~/bin/start_bash.sh
  exec script ~/tmp/log_session/session.`date +%Y.%m.%d.%H:%M:%S:%Z`.$$
  # never come here
  exit;
fi

Checking the Content of the script Utility's Output File

If you are interested in knowing exactly what is in the file that the script utility creates, you can simply open the file using the vi editor. Nonprinting characters are displayed. To get just the output as it was executed, you can use the cat utility.

Here is a small script to play back the script utility's output file. It copies the file character by character or line by line to your terminal window. It's best to use the same terminal size as before.

Run the script:

play_script_command_output.pl <script output file>

Here are commands you can use during playback.

n
Plays one character.
<ENTER>
Plays one line.
<SPACE>
Plays one terminal window ($terminal_lines lines).
j
Plays 10 characters.
e
Plays until end of the file.
h
Prints this help.
q or <ESC>
Exit.

The source code:

#!/usr/bin/perl

use strict;
use warnings;

use IO::Handle;
use IO::File;

eval {

 my $usage = "play_script_command_output.pl <script output file>";
 die "wrong number of argument\n$usage\n" if $#ARGV != 0;

 my $scriptFile = $ARGV[0];
 my $outputFile = $ARGV[1];

 my $inputHandle = new IO::File;
 my $terminal_lines = exists $ENV{LINES} ? $ENV{LINES} : 24;

 my $stdout = new IO::Handle;
 $stdout->fdopen(fileno(STDOUT),"a") || die "cannot open STDOUT\n";
 $inputHandle->open("< $scriptFile") || die "cannot open $scriptFile\n";
 $stdout->autoflush();

 my $stdio = new IO::Handle;
 $stdio->fdopen(fileno(STDIN),"r") || die "cannot open STDIN";

 my $help = "
------------------------------------------
commands:
  n            - Play one character
  <ENTER>      - Play one line
  <SPACE>      - Play one terminal window ($terminal_lines lines)
  j            - Play 10 characters
  e            - Play until end of the file
  h            - Print this help
  q or <ESC>   - Exit
------------------------------------------
";

  print "play the script command output: $scriptFile $help";
  # noncanonical input
  system "stty -icanon -echo min 1 time 0";
  my $i;
  while(my $char = $stdio->getc()) {
    if ($char eq 'q'  || ord($char) == 27) {
      print "\n------------------------------------------";
      print "\nexiting\n";
      last;
    } elsif ($char eq "\n") {
      $stdout->print($inputHandle->getline());
    } elsif ($char eq " ") {
      for ($i = 1; $i<$terminal_lines && ! $inputHandle->eof() ; $i++) {
        $stdout->print($inputHandle->getline());
      }
    } elsif ($char eq 'n') {
      $stdout->print($inputHandle->getc());
    } elsif ($char eq 'j') {
      for ($i = 1; $i<10 && ! $inputHandle->eof() ; $i++) {
        $stdout->print($inputHandle->getc());
      }
    } elsif ($char eq 'e') {
      while (! $inputHandle->eof()) {
        $stdout->print($inputHandle->getline());
      }
    } elsif ($char eq 'h') {
      print $help;
    }

    if ($inputHandle->eof()) {
      print "\n------------------------------------------";
      print "\nend of file reached in script file: $scriptFile\n";
      last;
    }
  }

  $inputHandle->close();
  $stdout->close();
  system "stty icanon echo";
  exit(0);
};
if ($@) {
  # end of eval, handle exception
  print "$@\n";
  system "stty icanon echo";
  exit(1);
}

Unless otherwise licensed, code in all technical manuals herein (including articles, FAQs, samples) is provided under this License.


BigAdmin
  
 
 
 
Contact About Sun News & Events Employment Site Map Privacy Terms of Use Trademarks Copyright 1994-2008 Sun Microsystems, Inc.