【问题标题】:Bash scripting, checking for errors, loggingBash 脚本,检查错误,记录
【发布时间】:2010-03-02 10:00:52
【问题描述】:

这是 bash-fu 巫师的一个。不,实际上,我只是在开玩笑,除了我之外,你们可能都知道这一点..

我正在尝试创建一个备份 shell 脚本。这个想法相当简单:在某个文件夹中查找超过 7 天的文件,将它们 tar/gzip 压缩到另一个目录,然后删除它们。问题是,我不确定我是否有足够的权限在目标目录中创建 tar/gzip 文件。是否有任何(正确的)方法来检查文件是否已成功创建,如果是,则删除文件。否则,请跳过该部分并且不要破坏客户的数据。我听说他们不太喜欢那个。

这是我目前所拥有的:

01: #!/bin/bash
02: 
03: ROOTDIR="/data/www"
04: 
05: TAR="${ROOTDIR}/log/svg_out_xml/export_out_ack_$(date +%Y-%m-%d).tar"
06: cd ${ROOTDIR}/exchange/export/out_ack/
07: find . -mtime +7 -type f -print0 | xargs -0 tar -cf "${TAR}"
08: gzip ${TAR}
09: find . -mtime +7 -type f -print0 | xargs -0 rm -f

基本上,我需要检查第 7 行和第 8 行是否一切正常,如果是,则执行第 9 行。

另外,我想为这些操作创建一个日志文件,这样我就知道一切正常(这是一个每晚的 cron 作业)。

【问题讨论】:

  • 所有的 cmets 都来了,使用一些预先做好的保险柜。
  • 经验之谈,递归? :)
  • 你的标签是“bash”,但你的 shebang 是“sh”。
  • 我接受了 Dennis Williamson 的回答,因为他是唯一解决日志记录问题的人,但所有建议都非常有帮助,谢谢大家!

标签: bash shell logging scripting


【解决方案1】:

对于日志记录,您可以将脚本的各个部分用大括号括起来,并将标准输出重定向到日志文件:

{
    script_command_1
    script_command_2
    script_command_3
} >> /path/to/log_file

【讨论】:

  • Kewl,如果我这样写,我希望它能起作用:} >> ${LOG} 2>&1
【解决方案2】:

对于日志记录,您可以安排将标准输出和/或标准错误上的所有输出写入文件。这样,您就不需要重定向每个命令的输出:

# Save standard output and standard error
exec 3>&1 4>&2
# Redirect standard output to a log file
exec 1>/tmp/stdout.log
# Redirect standard error to a log file
exec 2>/tmp/stderr.log

# Now the output of all commands goes to the log files
echo "This goes to /tmp/stdout.log"
echo "This goes to /tmp/stderr.log" 1>&2
...

# Print a message to the original standard output (e.g. terminal)
echo "This goes to the original stdout" 1>&3

# Restore original stdout/stderr
exec 1>&3 2>&4
# Close the unused descriptors
exec 3>&- 4>&-

# Now the output of all commands goes to the original standard output & error
...

要仅在前一个命令成功时执行命令,您可以使用条件链接它们:

# Execute command2 only if command1 succeeds, and command3 only if both succeed:
command1 && command2 && command3

# Execute command2 only if command1 fails
command1 || command2

这样你就可以做类似的事情

{ find . -mtime +7 -type f -print0 | xargs -0 tar -cf "${TAR}" &&
  gzip ${TAR} && 
  find . -mtime +7 -type f -print0 | xargs -0 rm -f } || 
    { echo "Something failed" 1>&2; exit 1 }

或在日志输出中提供详细信息:

find . -mtime +7 -type f -print0 | xargs -0 tar -cf "${TAR}" || 
  { echo "find failed!!" 1>&2; exit 1 }
gzip ${TAR} || 
  { echo "gzip failed!!" 1>&2; exit 1 }
find . -mtime +7 -type f -print0 | xargs -0 rm -f || 
  { echo "cleanup failed!!" 1>&2; exit 1}

【讨论】:

    【解决方案3】:

    简单的方法,但没有明确的错误消息,将-e 添加到shebang,即#!/bin/sh -e,如果命令失败,这将导致shell 退出..

    我猜 Cron 应该会通过邮件给你一个错误消息。

    不过,如果您想使用完整的备份方案,我建议您使用已经制作好的东西。那里有很多,而且大多数都工作得很好。

    【讨论】:

    • 很好的建议。我总是在我的脚本中使用-e
    • 感谢您的提示,非常有用!不幸的是,cron 不会向我们发送任何内容,因为我们不是该系统的管理员。不过会很好..
    • @dr: 如果你在你的 crontab 中定义 MAILTO,它会。
    • 请参阅 BashFAQ/105 关于 bash -e。 tl;dr -“不要使用set -e
    【解决方案4】:

    GNU tar 有--remove-files,一旦文件被添加到存档中,它将删除文件。 v 将导致它在添加文件时列出文件。 z 将通过 gzip 即时通过管道传输 tar。

    您的find 解决方案很活泼;文件可能符合两次调用之间的条件,因此会被删除但不会备份。

    【讨论】:

    • 感谢您的回答。文件不太可能适合两次调用,因为该脚本将在凌晨 4 点运行,此时不应在我正在备份的文件夹中创建任何文件。当然,总有一个用户..
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-15
    • 2020-12-07
    相关资源
    最近更新 更多