4

I'm looking for a solution (similar to the bash code below) to copy both stdout and stderr to a file in addition to the screen within ksh on Solaris.

The following code works great in the bash shell:

#!/usr/bin/bash

# Clear the logfile
>logfile.txt

# Redirect all script output to a logfile as well as their normal locations
exec >  >(tee -a logfile.txt)
exec 2> >(tee -a logfile.txt >&2)
date
ls -l /non-existent/path

For some reason this is throwing a syntax error on Solaris. I assume it's because I can't do process substitution, and I've seen some posts suggesting the use of mkfifo, but I've yet to come up with a working solution.

Does anyone know of a way that all output can be redirected to a file in addition to the default locations?

HuggieRich
  • 43
  • 1
  • 1
  • 4

3 Answers3

3

How about this:

(some commands ...) 2>&1 | tee logfile.txt

Add -a to the tee command line for subsequent invocations to append rather than overwrite.

twalberg
  • 59,951
  • 11
  • 89
  • 84
  • I don't want to have to do this for every command, ideally, I'd like something I can put at the top of the script like in the example above. – HuggieRich Aug 22 '12 at 15:22
  • I should also mention that it must be done inside the script. I have a daemon running the script that captures all output to a logfile, so I don't have control over the invocation on the command line. – HuggieRich Aug 23 '12 at 08:18
3

Which version of ksh are you using? The >() is not supported in ksh88, but is supported in ksh93 - the bash code should work unchanged (aside from the #! line) on ksh93.

If you are stuck with ksh88 (poor thing!) then you can emulate the bash/ksh93 behaviour using a named pipe:

#!/bin/ksh 
# Clear the logfile  
>logfile.txt  

pipe1="/tmp/mypipe1.$$"
pipe2="/tmp/mypipe2.$$"
trap 'rm "$pipe1" "$pipe2"' EXIT
mkfifo "$pipe1"
mkfifo "$pipe2"
tee -a logfile.txt < "$pipe1" &
tee -a logfile.txt >&2 < "$pipe2" &

# Redirect all script output to a logfile as well as their normal locations  
exec >"$pipe1"
exec 2>"$pipe2"

date   
ls -l /non-existent/path  

The above is a second version to enable stderr to be redirected to a different file.

cdarke
  • 42,728
  • 8
  • 80
  • 84
  • this is almost what I need, but this doesn't keep the STDOUT and STDERR file descriptors separate. If I invoke the script like `./script.sh >out.log 2>err.log` then all the output goes to out.log, but some should go to the err.log – HuggieRich Aug 23 '12 at 13:54
  • ksh in Solaris 10 does support process substitution, but apparently it doesn't work for `exec` – sendmoreinfo Aug 06 '14 at 10:42
  • I guess the tee processes runs forever. May be we need a cleanup code, kill %tee to be done twice. – KRoy Aug 30 '17 at 20:10
  • @shuva `tee` exits when it gets EOF (End-Of-File) from its `stdin`. – cdarke Aug 31 '17 at 21:08
1

In ksh, the following works very well for me

LOG=log_file.$(date +%Y%m%d%H%M%S).txt
{
ls
date
... whatever command
} 2>&1 | tee -a $LOG
Luís Cruz
  • 14,780
  • 16
  • 68
  • 100
JBat
  • 21
  • 2