批处理循环中的 PSQL 错误级别

PSQL Error Level in Batch For Loop

我正在尝试从批处理文件中 运行 postgres 查询。但是,到目前为止,我无法检测到命令何时失败。以下是我迄今为止尝试过的方法:

@FOR /F %%A IN ('PSQL -U userName -d dbName -t -c "SELECT * FROM nonExistantTable" 2^>^&1') DO @(
    ECHO !ERRORLEVEL!
)

我也试过以下方法:

1) 在 sql 命令之前添加 "CALL" (CALL PSQL -U ...)
2) 将“-v ON_ERROR_STOP=1”添加到 sql 命令中,无论是否使用 "CALL" 命令 (PSQL -U ... -v ON_ERROR_STOP=1)

但是,ERRORLEVEL 的值始终为零。有谁知道如何使用批处理检测 PSQL 调用中的错误?具体来说,我收到的错误是 table 不存在。谢谢

for /f 在单独的 cmd 实例中执行命令,并且此实例中的 errorlevel 不会导出到 do 子句中的代码。

在纯批处理中更好的处理方式是:

  • 将程序的输出发送到临时文件
  • 检查错误级别
  • 如果没有错误处理文件输出
  • 无论如何删除末尾的临时文件

类似

set "tempFile=%temp%\%~n0.%random%%random%%random%.tmp"
> "%tempFile%" 2>&1 (
    PSQL -U userName -d dbName -t -c "SELECT * FROM nonExistantTable"
)
if not errorlevel 1 (
    for /f "usebackq delims=" %%g in ("%tempFile%") do (
        echo %%g
    )
) else (
    echo ERRORLEVEL: %errorlevel%
)
del /q "%tempFile%"

@MCND的回答可以概括为:

1) 运行 命令正常,将 stdout 重定向到临时文件
2)根据ERRORLEVEL

处理文件内容

基于这个答案,我想出了一个解决方案,它可以用更少的代码满足我的特定需求。我的情况有点特殊,因为 PSQL 命令恰好执行以下操作之一:

1) 将结果写入标准输出,并且return归零
2) 将错误写入 stderr,并且 returns 非零

在案例 #1 中,我希望我的批处理文件打印结果 return 0。在案例 #2 中,我想执行一些自定义逻辑,打印错误,并且 return非零。对于这个逻辑,我发现以下方法效果更好:

:: Get a temporary file name
@SETLOCAL
@SET TEMP_OUT="%TEMP%\myScriptError.log"

:: Create the command that will be executed
@SET DB_SELECT=SELECT * FROM nonExistantTable
@SET DB_COMMAND=PSQL -U userName -d dbName -t -c "%DB_SELECT%"

:: Run the command
@FOR /F %%A IN ('%DB_COMMAND% 2^>%TEMP_OUT%') DO @(
    REM This code only runs if there are no errors
    SET EXIT_CODE=0
    GOTO :CLEANUP
)

:: Uh-oh, there was an error.  Print it to stderr, and set the exit code.
@MORE %TEMP_OUT% 1>&2
@SET EXIT_CODE=1
...

:: Clean up the temp file and return the result
:CLEANUP
@DEL /F /Q %TEMP_OUT%
@ENDLOCAL & EXIT /B %EXIT_CODE%