Loading... ## 在 `sh` 脚本中执行 PHP 并捕获异常 在编写 Shell 脚本时,有时需要执行 PHP 脚本并捕获其中的异常或错误。为了实现这一目标,我们需要确保 PHP 脚本执行过程中产生的异常或错误可以反馈给 Shell 脚本,并根据这些错误执行不同的操作。 ### 一、问题分析 在 `sh` 脚本中执行 PHP 脚本的基本步骤通常如下: 1. 调用 PHP 脚本。 2. 捕获 PHP 脚本的输出和错误。 3. 根据 PHP 脚本的退出码判断是否发生异常或错误。 4. 执行相应的错误处理逻辑。 ### 二、捕获 PHP 异常的方法 在 PHP 中,异常或错误会影响脚本的退出状态。通过检查 PHP 的返回码,我们可以确定是否发生了错误。此外,还可以将 PHP 脚本的标准输出和错误输出分别重定向到不同的文件或变量中,以进一步处理。 #### 1. 使用 PHP 的 `try-catch` 结构 在 PHP 脚本中,使用 `try-catch` 块来捕获异常并返回非零的退出码,便于在 Shell 脚本中检测。 示例 PHP 脚本 `script.php`: ```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`: ```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` 脚本: ```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 <?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` 脚本中,根据不同的退出码进行不同的处理: ```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` 判断不同的退出码,执行相应的错误处理逻辑 | 最后修改:2024 年 08 月 31 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏