1

I have the following code ..

while read copy
do
  cp -v $copy | tee -a $LOGFILE
  echo $?
    if [[ $? -ne 0 ]]
      then
        echo "Error copying files. Exiting ..." | tee -a $LOGFILE
        exit 1
    fi

done < copy_new_files.tmp

.. and I would like the script to halt if a file cant be copied for an error such as permission denied.

The output from the script isn't producing an error code on the permission denied error ..

+ read copy
+ cp -v acts035.fmt /home/test/gp/efin/source/pl/acts035.fmt
cp: cannot create regular file `/home/test/gp/efin/source/pl/acts035.fmt': Permission denied
+ tee -a /home/test/gp/efin/fixes/12345/efin_fix_copy_12345.log
`acts035.fmt' -> `/home/test/gp/efin/source/pl/acts035.fmt'
+ echo 0
0

How can I get the script to pause if there is an error ?

Many thanks.

fedorqui
  • 275,237
  • 103
  • 548
  • 598
  • This `Permission denied` suggests you have no rights to write in the log file. – fedorqui Jun 16 '14 at 11:41
  • 1
    Using `$?` twice looks suspicious. `echo $?` changes it. Maybe you should store the value before using it. – andrjas Jun 16 '14 at 11:46
  • 1
    if you need to pause in an interactive mode it's enough to write instead of `exit 1` a line like `read ppppp`. And press return when you want to go forward – Hastur Jun 16 '14 at 11:51
  • please post some lines from `copy_new_files.tmp`. – Hastur Jun 16 '14 at 12:07
  • The script you posted did not produce the error messages you posted. The script you posted would have `cp` complaining about not having enough arguments - it requires at least two, and you have only given it one. – twalberg Jun 16 '14 at 14:44
  • I update the script in the answer using ${PIPESTATUS[0]} instead of $?. There is a _pipe_ you need to catch the exit status of the 1st command. – Hastur Jun 16 '14 at 15:04

1 Answers1

3

Some little insidious things, I hope to be not overlong:

  • A first problem was that $? returns the last exit error code.
    So when you execute echo $? in the following line, you set $? to a new value, 0 in this case: I see no reason for which the echo command have to fail.

  • A second more insidious problem was that the precedent command is a pipe. So the variable to be used is ${PIPESTATUS[0]} and not $?. (There is [0] because it is an array and we want the value stored in the 1st component that is the exit status of the 1st command).
    Once again you can store in a variable this value or you can execute immediately after the test. Otherwise the use of other commands will reset again the variable values.

  • To pause the execution of the script it should enough to write an input line like read -p x < /dev/tty. To be insidious this time is the standard input flushing that we overcame asking input from tty.

  • It is generally safer to use read -r than read.

    -r raw input - disables interpretation of backslash escapes and line-continuation in the read data

so a code variant should be:

while read -r copy
do
  cp -v $copy  |  tee -a $LOGFILE
  # echo $? ${PIPESTATUS[0]}              # NOT HERE  else you loose it
    if [[ ${PIPESTATUS[0]} -ne 0 ]]       # $? was referred to the last command. 
      then                                # Use ${PIPESTATUS[0]} instead
        echo "Error copying files. ${copy}  Exiting ..." | tee -a $LOGFILE
                                          # It will wait that you press return
        read -p "Press CTRL-C to interrupt, RETURN to continue " x < /dev/tty 
        # exit 1                          # It will not exit: (#) means comment.
    fi
done < copy_new_files.tmp

Note: as suggested by chepner The issue with capturing the exit status of cp can also be fixed by piping the standard output of the while loop to a single call to tee, rather than the cp and the echo individually, that is even more elegant. Of course in that case you will write in the output file all the text printed in the cycle while, and even the not needed "Press CTRL-C to interrupt, RETURN to continue " lines I added.

Community
  • 1
  • 1
Hastur
  • 2,470
  • 27
  • 36
  • 1
    Dont need the "aaaaa". `read` already has a default variable `$REPLY`, so if you're not using the variable might as well just write `read` –  Jun 16 '14 at 12:14
  • Thanks, it's right like the sun shines :-). My purpose was to keep that value to skip the pause or to exit directly the next time that an error is found. There are another couple of things to fix, I'm waiting he posts some lines of the source file. – Hastur Jun 16 '14 at 12:28
  • 1
    The issue with capturing the exit status of `cp` can also be fixed by piping the standard output of the `while` loop to a single call to `tee`, rather than the `cp` and the `echo` individually. – chepner Jun 16 '14 at 15:06