KSH problem - how do i redirect three times?

i need to output an ls command to a file but also capture any errors from that command and output them to a log file and the screen.

if it's only possible to output them to a log file and not the screen then that's fine.

this is what i've tried so far, but it won't populate log.txt. i've purposefully added a directory (scripts) that doesn't exist to force the ls command to fail.

ls -lR  > scripts/release_file.txt 2>&1 | tee -a log.txt

i suspect it's the first redirection that's causing the problem as the command usually works if i'm not outputting the ls results to another file.

how about

cat /dev/null >log.txt; ls -lR scripts/release_file.txt >log.txt 2>&1 ; cat log.txt

the cat /dev/null >log.txt will empty the log file, then the ls is run, and the results (including any errors) are sent to log.txt, then the results are output to the screen.

cat /dev/null >log.txt; ls -lR scripts/release_file.txt >log.txt 2>&1 ; cat log.txt

the problem is, the command is part of a much larger script that outputs lots of info to the log file.

therefore, we can't empty the log file at the start...

cat /dev/null >log.txt;

or cat the log file at the end...

cat log.txt

...because of all the stuff that is already in the log file from previous commands executed in the script.

You were close...

$ ls data notthere
ls: notthere: No such file or directory
data
$ ls data not_there 2>&1 >stdout | tee stderr
ls: not_there: No such file or directory
$ cat stdout
data
$ cat stderr
ls: not_there: No such file or directory
$

Hi

If your question is to redirect the output/err to file/errr-file

This will serve the purpose

cat local.csh 1>errt.txt 2>err.txt; cat err.txt

Hope i got your question right.

Regards,
Harsha

that's it, you've cracked it.

thanks for your help, and thank you everyone else.

p.s harshakirans - your solution didn't work, i kept getting - cat: cannot open err.txt. thanks though.

sorry but i was a little premature.

things still aren't right.

the problem is, i need the script to exit if the ls command fails, but all it does is display the error and then write to the log file.

this is the ls command and the code after it

ls -lR ${BUILD_CODE} 2>&1 >${REL_FILES}/${RELNO}.txt | tee -a ${LOGFILE}
if [ $? -ne 0 ]
   then
       exit
fi

so you see, the tee command is probably successful which gives me a $status of 0.

how do i interogate the error from the ls command when it's tucked in way back there?

In bash, you can turn on the option "pipefail", and $? will return the result of the last command to fail in the pipeline (otherwise, it will return the result of the last command OF the pipeline). Use "set -o pipefail" to turn this feature on. Observe:

false | cat; echo $?
0
$ set -o pipefail
$ false | cat; echo $?
1

Otherwise, you have to do tricks like:

/bin/ls $FILE >$TMP_FILE_2 2>&1
res=$?
cat $TMP_FILE_2 >>$LOGFILE
if [ $res -ne 0 ]; then 
  exit
fi

yeah, i've already considered the extra check to see if the file was created. i was hoping there was a more direct solution using a method i've never seen before. a super advanced system admin/unix expert method.

Odd, is it not?

So can you use bash? Maybe ksh has a similar option?

;-))))

In fact there is and i am glad to be able to explain - once in a lifetime - "super advanced system admin expert methods" to the audience: You can redirect output streams with the "exec" command:

exec 2>output.stderr

Will redirect every output of every subsequent command to output.stderr.

This way you do not have to worry about truncating the file at all:

exec 2>output.stderr     # truncates the file and redirects stderr to it
job1
job2
job3
exec 2>&-                # closes stderr and removes the redirection

is equivalent to

job1 2> output.stderr
job2 2>> output.stderr
job3 2>> output.stderr

I hope this helps.

bakunin

erm...where does that fit in with my bit of code?

ls -lR ${BUILD_CODE} 2>&1 >${REL_FILES}/${RELNO}.txt | tee -a ${LOGFILE}
if [ $? -ne 0 ]
   then
       echo "ERROR - release file creation failed 
       exit
fi

i've tried not to be stupid and figure out how to use your solution but i give in.

"super advanced system admin expert methods" means writing answers without first understanding the question. :wink:

Seriously, at the *beginning* of the script, you could do something like this:

exec >standard.out 2>error.out

Every time there's an error, you stop the script and output the error.out file. However, it doesn't deal with automatically printing the normal output. However, you could go to another terminal and run:

tail -f standard.out

but I don't think that suits your purpose.

you are using err file (redirecting the error to stderr)wright?
lets take

ls data >err 2>&1 | tee -a somefile
if [ ! -s err ]
then
{do whatever you want}
fi

here as per the code the err file will load with some error message when failure occurs in ls.
is it feasible?

ha ha ha...(to your first sentence - otheus). :slight_smile:

yes, you're right that method doesn't suit my purpose. i think i'll do a simple check to see if the file got created.

ls -lR ${BUILD_CODE} 2>&1 >${REL_FILES}/${RELNO}.txt | tee -a ${LOGFILE}
if [ ! -e ${REL_FILES}/${RELNO}.txt ]
  then 
  echo "ERROR - release file creation failed 
       exit
fi

similar to your solution arunprasad.

this is all done and dusted now but i'd just like to say to Arunprasad, you were correct, it's -s i need to use, because the file gets created regardless of any errors. the indication of failure is size of the file.

thank you.

hi mjays,

-s could not be the indication of the error.
but the err file will be created while execution of that part of code wright?

err 0 bytes of size.
when the ls faces any errors that will be updated in err file.
so the size will increase

so with -s option we come to know some error is there or not!