如何在Shell脚本中处理错误/异常?

6

以下是我在bash中执行的脚本。它可以正常运行。

fileexist=0
for i in $( ls /data/read-only/clv/daily/Finished-HADOOP_EXPORT_&processDate#.done); do
  mv /data/read-only/clv/daily/Finished-HADOOP_EXPORT_&processDate#.done /data/read-only/clv/daily/archieve-wip/
  fileexist=1
done

问题陈述:

在我的shell脚本中,需要使用cron job每天运行。但是我没有任何错误/异常处理机制。如果发生了任何问题,那么我就不知道出了什么问题。

因为在执行上述脚本之后,还有一些其他脚本将依赖于上述脚本提供的数据,所以我总是会收到来自依赖我的脚本数据的其他人的抱怨,说出了什么问题。

所以是否有任何方法可以在我的脚本出现问题时通知我?比如集群正在进行某些维护,并且此时我正在运行我的脚本,那么肯定会失败,所以如果我的脚本失败了,我能否得到通知,这样我就确定出了问题。

希望我的问题足够清楚。

感谢您的任何想法。


@Levon,完成了。现在好一些了吗? - arsenal
是的,我认为这看起来更好,更易读,不会吓跑潜在的帮助者 :) - Levon
好的,谢谢你的建议。下次我一定会注意的。 :) - arsenal
3个回答

11
你可以像freetx回答的那样检查每个命令的退出状态,但这是手动错误检查而不是异常处理。在sh中获取类似于异常处理的标准方式是使用set -e开始脚本。这告诉sh一旦执行的任何命令失败(即以非零退出状态退出),就会带有非零状态退出。
如果在此类脚本中有某个命令打算(可能)失败,可以使用构造COMMAND || true,这将强制该表达式具有零退出状态。例如:
#!/bin/sh

# if any of the following fails, the script fails
set -e
mkdir -p destdir/1/2
mv foo destdir/1/2
touch /done || true    # allowed to fail

确保在cron调用的脚本出现问题时有通知的另一种方法是遵循Unix约定,即仅在发生错误时打印内容。成功运行将不会引起注意,而不成功的运行将导致cron守护程序通过电子邮件通知您出现了错误。请注意,为使此方法起作用,必须在系统上正确配置本地邮件传递。


6

在Unix命令行中,每个实用程序成功返回0,失败则返回非零值。因此,您可以使用$?模式显示最后一个返回值并相应地处理事情。

例如:

> ls
> file1 file2
> echo $?
> 0
> ls file.no.exist
> echo $?
> 1

因此,您可以将其用作基本的错误检测,以查看是否出现问题。因此,正常的做法是:
some_command
if [ $? -gt 0 ]
then
handle_error here
fi

5
实际上,惯用的写法是 if ! some_command; then ... 许多人似乎没有意识到 if 的唯一目的是运行一个命令并检查它的退出代码以确定成功或失败状态。 - tripleee

0

如果其他脚本在同一台机器上,那么您可以在其他脚本中执行pgrep查找此脚本,如果发现则睡眠一段时间,稍后尝试其他脚本,重新检查进程是否已关闭。

如果脚本在另一台甚至本地的计算机上,则另一种方法是在远程计算机上生成临时文件,可通过正在运行的http浏览器访问,以便其他脚本可以检查状态,即正在运行或完成。

您还可以将脚本包装在另一个脚本周围,该脚本查找这些错误,并在找到错误时给您发送电子邮件,如果没有找到错误,则像往常一样向谁发送结果。

go=0;
function check_running() {

         running=`pgrep -f your_script.sh|wc -l `
    if [ $running -gt 1 ]; then
        echo "already running $0 -- instances found $running ";
      go=1;
}

check_running;
if [ $go -ge 1 ];then
      execute your other script
else
   sleep 120;
    check_running;
fi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接