在 sh
脚本中执行 PHP 并捕获异常
在编写 Shell 脚本时,有时需要执行 PHP 脚本并捕获其中的异常或错误。为了实现这一目标,我们需要确保 PHP 脚本执行过程中产生的异常或错误可以反馈给 Shell 脚本,并根据这些错误执行不同的操作。
一、问题分析
在 sh
脚本中执行 PHP 脚本的基本步骤通常如下:
- 调用 PHP 脚本。
- 捕获 PHP 脚本的输出和错误。
- 根据 PHP 脚本的退出码判断是否发生异常或错误。
- 执行相应的错误处理逻辑。
二、捕获 PHP 异常的方法
在 PHP 中,异常或错误会影响脚本的退出状态。通过检查 PHP 的返回码,我们可以确定是否发生了错误。此外,还可以将 PHP 脚本的标准输出和错误输出分别重定向到不同的文件或变量中,以进一步处理。
1. 使用 PHP 的 try-catch
结构
在 PHP 脚本中,使用 try-catch
块来捕获异常并返回非零的退出码,便于在 Shell 脚本中检测。
示例 PHP 脚本 script.php
:
<?php
try {
// 可能抛出异常的代码
throw new Exception("Something went wrong!");
} catch (Exception $e) {
// 输出错误消息
fwrite(STDERR, $e->getMessage() . "\n");
exit(1); // 返回非零值表示异常
}
解释:
try-catch
块:捕获异常,确保异常不会导致 PHP 脚本崩溃,而是输出错误消息到标准错误流(STDERR
),并返回退出状态码1
。
2. 在 sh
脚本中捕获异常
Shell 脚本可以通过 $?
获取上一个命令的退出状态码。0 表示成功,非零表示错误。我们可以根据这个状态码来判断 PHP 脚本是否执行成功。
示例 sh
脚本 run_php.sh
:
#!/bin/sh
# 执行 PHP 脚本,并将输出和错误分别重定向到不同的文件
php script.php > output.log 2> error.log
EXIT_CODE=$?
# 检查 PHP 脚本的退出码
if [ $EXIT_CODE -ne 0 ]; then
echo "PHP 脚本执行出错,错误信息如下:"
cat error.log # 输出错误日志
else
echo "PHP 脚本执行成功,输出如下:"
cat output.log # 输出正常日志
fi
# 清理日志文件
rm -f output.log error.log
解释:
php script.php > output.log 2> error.log
:将 PHP 脚本的标准输出重定向到output.log
文件,错误输出重定向到error.log
文件。$?
:捕获 PHP 脚本的退出状态码,并存储在变量EXIT_CODE
中。if [ $EXIT_CODE -ne 0 ]
:判断退出码是否非零,非零表示执行出错。cat error.log
和cat output.log
:分别输出错误日志和正常日志内容。- 清理日志文件:脚本结束时删除生成的日志文件,确保不留下临时文件。
三、使用 set -e
强化错误处理
为了确保 Shell 脚本在发生任何错误时立即停止执行,可以使用 set -e
命令。set -e
命令会让脚本在遇到任何返回非零状态的命令时立即退出。
示例 sh
脚本:
#!/bin/sh
set -e # 开启遇错即停模式
# 尝试执行 PHP 脚本
php script.php > output.log 2> error.log
# 如果 PHP 脚本执行成功,输出日志
echo "PHP 脚本执行成功,输出如下:"
cat output.log
# 清理日志文件
rm -f output.log error.log
解释:
set -e
:开启错误处理,遇到任何命令返回非零状态时立即退出脚本。- 如果 PHP 脚本执行失败,Shell 脚本会立即退出,而不会执行后续的日志输出和清理操作。
四、示例场景扩展
1. 捕获并处理不同类型的错误
有时我们需要根据错误类型进行不同的处理。可以在 PHP 中通过不同的异常处理逻辑返回不同的退出码,在 Shell 脚本中根据退出码执行不同的处理。
示例 PHP 脚本:
<?php
try {
// 模拟不同的错误情况
if (rand(0, 1)) {
throw new Exception("General error");
} else {
throw new RuntimeException("Runtime error");
}
} catch (RuntimeException $e) {
fwrite(STDERR, $e->getMessage() . "\n");
exit(2); // 返回不同的状态码
} catch (Exception $e) {
fwrite(STDERR, $e->getMessage() . "\n");
exit(1);
}
在 sh
脚本中,根据不同的退出码进行不同的处理:
#!/bin/sh
php script.php > output.log 2> error.log
EXIT_CODE=$?
case $EXIT_CODE in
1)
echo "通用错误发生,错误信息如下:"
;;
2)
echo "运行时错误发生,错误信息如下:"
;;
*)
echo "未知错误,退出码:$EXIT_CODE"
;;
esac
cat error.log
rm -f output.log error.log
五、总结
通过在 sh
脚本中调用 PHP 脚本,并捕获其异常和错误,可以更灵活地控制脚本的执行流程。在实际应用中,这种方式可以有效提升自动化脚本的健壮性和可维护性。无论是处理单一错误还是根据不同错误进行不同处理,使用 Shell 脚本结合 PHP 的 try-catch
机制,可以实现更复杂的错误处理逻辑。
步骤 | 解释 |
---|---|
编写 PHP 脚本 | 使用 try-catch 机制捕获异常并返回不同的退出码 |
执行 PHP 脚本 | 在 Shell 脚本中使用 php 命令执行 PHP 脚本,并捕获输出和错误 |
捕获 PHP 脚本的退出状态码 | 通过 $? 捕获退出状态码,判断是否发生错误 |
根据错误类型处理 | 使用 case 或 if 判断不同的退出码,执行相应的错误处理逻辑 |