1

我有以下代码..

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

..如果由于权限被拒绝等错误而无法复制文件,我希望脚本停止。

脚本的输出没有在权限被拒绝错误上产生错误代码..

+ 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

如果出现错误,如何让脚本暂停?

非常感谢。

4

1 回答 1

3

一些阴险的小事,希望不会过长:

  • 第一个问题是$?返回最后一个退出错误代码
    因此,当您echo $?在以下行中执行时,您设置$?了一个新值,0在这种情况下:我看不出echo命令必须失败的原因。

  • 第二个更隐蔽的问题是前面的命令是一个管道。所以要使用的变量 is${PIPESTATUS[0]}和 not $?。(这是[0]因为它是一个数组,我们希望存储在第一个组件中的值是第一个命令的退出状态)。
    您可以再次将此值存储在变量中,也可以在测试后立即执行。否则使用其他命令将再次重置变量值。

  • 要暂停脚本的执行,写一个输入行就足够了read -p x < /dev/tty。这次阴险的是标准输入刷新,我们克服了从tty.

  • 它通常比使用更read -r安全read

    -r 原始输入 - 在读取的数据中禁用反斜杠转义和行继续的解释

所以代码变体应该是:

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

注意:正如 chepner 所建议的,捕获退出状态的问题cp也可以通过将 while 循环的标准输出传递给对 的单个调用tee而不是单独的调用来cp解决echo,这更加优雅。当然,在这种情况下,您将在输出文件中写入循环中打印的所有文本 while,甚至不需要我添加的 “按 CTRL-C 中断,返回继续”行。

于 2014-06-16T11:54:18.193 回答