脚本中的错误处理与日志记录
实施可靠的错误处理,重定向脚本输出,并生成有意义的日志,以监控脚本执行情况和排查问题。
脚本中的错误处理与日志记录 是 CoddyKit 上的免费 Linux Server Deployment & SSH Mastery 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Linux Server Deployment & SSH Mastery 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Linux Server Deployment & SSH Mastery 课程共包含 4 节课。
让您的脚本更可靠
想象一下,您的脚本正在服务器上运行,执行着重要任务。如果出现问题,会发生什么?
- 它会不会悄无声息地失败?
- 它会不会留下难以收拾的残局?
- 您能否判断它何时以及为何失败?
健壮的脚本能够妥善处理错误,并提供清晰的日志。本课将教您如何做到这一点!
了解退出代码
Linux 中的每个命令和脚本结束时,都会返回一个退出代码(也称退出状态)。这个数字会告诉您操作是成功还是失败。
0:表示成功!一切顺利。1-255:表示失败。特定数字可能表示错误类型。
让我们看看它的实际效果:
#!/bin/bash
# This script demonstrates exit codes
echo "Attempting a successful command..."
ls /tmp
echo "Exit code for 'ls /tmp': $?"
echo
echo "Attempting a failing command..."
ls /nonexistent_directory
echo "Exit code for 'ls /nonexistent_directory': $?"检查命令状态
任意命令运行后,您都可以使用特殊变量 $? 检查它的退出代码。这对于在脚本中做出判断非常有用。
您可以使用 if 语句来响应成功或失败:
#!/bin/bash
# Check if a file exists before trying to read it
FILENAME="test_file.txt"
touch $FILENAME # Create it for success case
if [ -f "$FILENAME" ]; then
echo "File '$FILENAME' exists. Processing..."
# ... do something with the file ...
rm $FILENAME # Clean up
else
echo "Error: File '$FILENAME' not found!"
exit 1
fi
echo "Script finished."`set -e`:出错时退出
对于简单脚本而言,到处手动检查 $? 可能很繁琐。命令 set -e 会改变脚本的行为:
- 如果任何命令以非零状态退出(即失败),脚本会立即终止。
- 这样可以防止脚本继续使用可能已损坏的数据或处于无效状态。
尝试运行此脚本。如果 cp 命令失败,会发生什么?
#!/bin/bash
set -e
echo "Starting important operations..."
mkdir my_temp_dir
cp /nonexistent_source my_temp_dir/target # This will fail
echo "This line will not be reached if cp fails."
rmdir my_temp_dir
echo "Script finished successfully."使用 `trap` 执行清理
有时,即使脚本失败,您仍然需要执行清理任务,例如删除临时文件。trap 命令允许您捕获信号(例如退出或错误信号)并运行命令。
EXIT:脚本退出时运行,无论成功还是失败。ERR:命令以非零状态退出时运行(前提是set -e处于启用状态)。
在这里,我们确保临时目录始终会被删除:
#!/bin/bash
TEMP_DIR="/tmp/my_script_temp_$(date +%s)"
function cleanup {
echo "Cleaning up temporary directory: $TEMP_DIR"
rm -rf "$TEMP_DIR"
}
trap cleanup EXIT
mkdir "$TEMP_DIR"
echo "Working in $TEMP_DIR..."
# Simulate some work, maybe it fails
# cp /nonexistent_file "$TEMP_DIR/" # Uncomment to test failure
echo "Script completed."重定向输出
脚本运行时,通常会打印消息。这些消息主要分为两类:
- 标准输出(stdout):普通消息(文件描述符 1)。
- 标准错误(stderr):错误消息(文件描述符 2)。
您可以将这些数据流重定向到文件,而不是显示在屏幕上:
command > file:将 stdout 重定向到file。command 2> file:将 stderr 重定向到file。
让我们分别保存成功消息和错误消息。
#!/bin/bash
# Redirect stdout to success.log and stderr to error.log
echo "This is a success message." > success.log
ls /nonexistent_path 2> error.log
echo "Check success.log and error.log files."
# To view them after running:
# cat success.log
# cat error.log将所有输出写入一个文件
很多时候,将标准输出和标准错误都写入同一个日志文件会很有用,这样更便于查看。实现方式有几种:
command > file 2>&1:先将 stdout 重定向到file,再将 stderr 重定向到 stdout 当前指向的位置(即该文件)。command &> file:实现相同功能的更简短、更现代的语法。
这非常适合创建全面记录脚本执行过程的日志。
#!/bin/bash
# Redirect both stdout and stderr to a single log file
LOG_FILE="combined_script.log"
echo "Starting script..." &> "$LOG_FILE"
echo "This message goes to stdout." &>> "$LOG_FILE"
ls /nonexistent_dir 2>&1 | tee -a "$LOG_FILE"
echo "Script finished." &>> "$LOG_FILE"
echo "Check the '$LOG_FILE' file for all output."为日志添加时间戳
调试时,了解某个事件何时发生至关重要。为日志消息添加时间戳,会让日志更有用。
您可以使用 date 命令,将当前日期和时间添加到每条日志记录的开头。这样有助于按时间顺序追踪事件。
#!/bin/bash
LOG_FILE="timestamped_script.log"
function log_message {
echo "$(date +%Y-%m-%d_%H:%M:%S) - $1" &>> "$LOG_FILE"
}
log_message "Script started."
sleep 1
log_message "Performing task A..."
# Simulate an error
ls /no_such_place || log_message "Error: Command failed."
sleep 1
log_message "Script finished."
echo "Check '$LOG_FILE' for timestamped entries."使用 `logger` 发送到系统日志
对于重要事件,您可能希望将消息直接发送到系统的日志记录设施(syslog)。logger 命令正是用于此目的。
- 系统日志通常由
journalctl等工具管理(在使用 systemd 的系统上)。 - 这样可以将脚本的重要消息与其他系统事件集中记录。
- 这对于记录严重错误或审计轨迹很有用。
使用 logger 发送的消息可以通过 journalctl -f 或 tail -f /var/log/syslog 查找(具体取决于您的系统)。
#!/bin/bash
# Send a message to system logs
SCRIPT_NAME="MyBackupScript"
logger -t "$SCRIPT_NAME" "Starting daily backup operation."
# Simulate a task
sleep 2
if [ $(($RANDOM % 2)) -eq 0 ]; then
logger -t "$SCRIPT_NAME" -p user.info "Backup successful."
else
logger -t "$SCRIPT_NAME" -p user.err "Backup failed: Disk full."
fi
echo "Messages sent to system logs. Check with 'journalctl -t $SCRIPT_NAME'."错误处理检查
您编写了一个用于处理一些文件的 Bash 脚本。您希望脚本在其中任何命令失败时立即退出,同时还希望无论脚本以何种方式退出,临时目录都能被清理。
要实现这两个目标,您主要会使用哪两个 Bash 命令?
回顾与后续步骤
您已经学会了如何让 Bash 脚本更加健壮,也更易于调试!
- 退出代码:了解命令是成功还是失败。
set -e:出错时自动退出。trap:脚本退出时执行清理操作。- 输出重定向:控制 stdout 和 stderr 的去向。
- 时间戳:为日志添加上下文信息。
logger:接入系统范围的日志记录功能。
应用这些技术后,您的自动化任务将更加可靠且易于管理。继续练习,构建真正经久稳定的自动化流程!
常见问题解答
「脚本中的错误处理与日志记录」课时是免费的吗?
是的 — 「脚本中的错误处理与日志记录」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Linux Server Deployment & SSH Mastery 课程的其余内容,请升级到 CoddyKit PRO。 Linux Server Deployment & SSH Mastery 课程共包含 4 节课。
「脚本中的错误处理与日志记录」这节课中我会学到什么?
实施可靠的错误处理,重定向脚本输出,并生成有意义的日志,以监控脚本执行情况和排查问题。 你通过在浏览器中直接运行的动手代码来练习 Linux Server Deployment & SSH Mastery,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Linux Server Deployment & SSH Mastery 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Linux Server Deployment & SSH Mastery 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「脚本中的错误处理与日志记录」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Linux Server Deployment & SSH Mastery 课中编写并运行代码吗?
能。每节 Linux Server Deployment & SSH Mastery 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- Bash 脚本入门
- 自动化服务器任务
- 脚本中的错误处理与日志记录
- 函数、参数与可复用脚本