Issue Details (XML | Word | Printable)

Key: CORE-5520
Type: Bug Bug
Status: Open Open
Priority: Major Major
Assignee: Unassigned
Reporter: Beto Neto
Votes: 2
Watchers: 5
Operations

If you were logged in you would be able to see more operations.
Firebird Core

gbak isn't returning exit code about errors when using service manager (-se)

Created: 13/Apr/17 06:55 PM   Updated: 09/May/17 11:11 AM
Component/s: GBAK
Affects Version/s: 2.1.7, 2.5.7
Fix Version/s: None

Environment: Windows 10 pro + Firebird 2.5.7 and 2.1.7

QA Status: No test


 Description  « Hide
I'm trying to restore a corrupted backup file.
My shell script takes care about this process using the gbak, and analyzes the exit code from it.

Without using the "-se" option, everything goes ok!

    gbak -c corrupted.fbk restore.fdb -user sysdba -password masterkey -v
    echo %errorcode%

This command will print "2".

But, when I run the restore with the service manager option it doesn't returns the error code:

    gbak -c corrupted.fbk restore.fdb -user sysdba -password masterkey -v -se 127.0.0.1/3050:service_mgr
    echo %errorcode%

This command will print "0"


 All   Comments   Change History   Subversion Commits      Sort Order: Ascending order - Click to sort in descending order
Alexander Peshkov added a comment - 14/Apr/17 08:33 AM
Works for me - may be it's windows specific issue?

localhost bin # ./gbak -rep `pwd`/gbak.corr tmp -user sysdba -password masterkey -v -se 127.0.0.1/3050:service_mgr
gbak:opened file /opt/firebird.CS.2.5/bin/gbak.corr
gbak:transportable backup -- data in XDR format
gbak: backup file is compressed
gbak:created database tmp, page_size 4096 bytes
gbak:started transaction
gbak:restoring domain FIRSTNAME
...........
gbak:restoring domain DEPTNO
gbak: ERROR:do not recognize record type 0
gbak: ERROR: Exiting before completion due to errors
gbak:Exiting before completion due to errors
localhost bin # echo $?
1
localhost bin # ./gbak -z
gbak:gbak version LI-V2.5.7.27037 Firebird 2.5

Beto Neto added a comment - 14/Apr/17 10:49 AM - edited

Hans Thielen added a comment - 05/May/17 09:45 AM
If you restore a database and deny access to the restore.log, you got the same behaviour, i.e.:

e:\Dbs>"C:\Program Files\Firebird\Firebird_2_5\bin\GBAK" -REP -v -y Restore.log -user sysdba -pas masterkey WORK.GBK WORK.GDB -se service_mgr
gbak:cannot open status and error output file .\Restore.log
e:\Dbs>echo %errorlevel%
0

e:\Dbs>"C:\Program Files\Firebird\Firebird_2_5\bin\GBAK" -REP -v -y Restore.log -user sysdba -pas masterkey WORK.GBK WORK.GDB
gbak:cannot open status and error output file .\Restore.log
e:\Dbs>echo %errorlevel%
1

Pavel Zotov added a comment - 07/May/17 04:19 PM
> If you restore a database and deny access to the restore.log ...

OFFTOP.

IMO it is wrong way to assume that logs for storing STDOUT & STDERR results should be always avaliable.
At least one of them can be opened by some viewer (for example, in Far Manager, open any file by pressing F3 key) - and you will not be able to drop this file for new writing in it.

So, the first thing your script (.bat) should do is get ensurance that both logs can be:
1) created
2) dropped.

One may to do that by using following scratch:
===
@echo off
setlocal enabledelayedexpansion enableextensions

set logdir=c:\temp\gbak-results
set logname=tmpc5520.log
set errname=tmpc5520.err

if exist %logdir%\nul (

    @rem Dir "%logdir%" DOES exist.

    set fc=0
    set fd=0

    for /f %%a in ('copy %~dp0\nul %logdir%\%errname% 2^>nul ^| findstr /c:"1"') do (
        set fc=1
    )
    if !fc! equ 0 (
        echo Can not CREATE empty "%logdir%\%errname%" - file for storing STDERR results.
        echo Perhaps it is opened by another process or you have access rghts problem.
        goto final
    )

    if !fc! equ 1 (
        del %logdir%\%errname%
        if NOT exist %logdir%\%errname% set fd=1
    )

    if !fd! equ 0 (
        echo Can not REMOVE "%logdir%\%errname%" - file for storing STDOUT results.
        echo Perhaps it is opened by another process or you have access rghts problem.
        goto final
    )


    set fc=0
    set fd=0

    for /f %%a in ('copy %~dp0\nul %logdir%\%logname% 2^>nul ^| findstr /c:"1"') do (
        set fc=1
    )
    if !fc! equ 0 (
        echo Can not CREATE empty "%logdir%\%logname%" - file for storing STDOUT results.
        echo Perhaps it is opened by another process or you have access rghts problem.
        goto final
    )

    if !fc! equ 1 (
        del %logdir%\%logname%
        if NOT exist %logdir%\%logname% set fd=1
    )

    if !fd! equ 0 (
        echo Can not REMOVE "%logdir%\%logname%" - file for storing STDOUT results.
        echo Perhaps it is opened by another process or you have access rghts problem.
        goto final
    )

) else (
    echo Dir "%logdir%" does NOT exist. Can not proceeed anything.
    goto final
)

echo Check access to directory and STDOUT and STDERR logs passed OK.

@rem -------------- here we can start gbak ---------------------------

:final
===


As of gbak results you may need redirect BOTH stdout and stderr to the same file.
After backup/restore will finish, you can open this log and look there for string "gbak: ERROR:".
If this text will be found then your backup failed:
===
set host=localhost
set port=3400
set srcfdb=C:\temp\some_broken_database.fdb
set tgtfbk=C:\temp\foo.fbk

gbak -se %host%/%port%:service_mgr -rep %srcfdb% %tgtfbk% 1>c:\temp\backup-results.log 2>&1
findstr /m /b /i /c:"gbak: ERROR:" c:\temp\backup-results.log >nul
if NOT errorlevel 1 (
    echo . . . ACHTUNG. . . BACKUP FINISHED ABNORMALLY . . . CHECK ITS LOG. . .
) else (
    echo Backup finished without errors.
)
===

Hans Thielen added a comment - 08/May/17 08:44 AM
>> If you restore a database and deny access to the restore.log ...
>
>OFFTOP.

I just wanted to create a reproduceable error.

> ...After backup/restore will finish, you can open this log and look there for string "gbak: ERROR:".

Ahh, that was cool 1982... (maybe)
I expect an exe to behave like this:
"All right" -> %errorlevel% = 0
"Something failed" -> %errorlevel% != 0
The -se switch must not have any influence on that behaviour.


Beto Neto added a comment - 08/May/17 11:08 PM
> I expect an exe to behave like this:
> "All right" -> %errorlevel% = 0
> "Something failed" -> %errorlevel% != 0
> The -se switch must not have any influence on that behaviour.

+1

Pavel Zotov added a comment - 08/May/17 11:22 PM - edited
Still can't understand: why priority of this ticket is "Critical" ? IMO workaround (check access rights for logs and parse them after gbak will finish) is not too hard to be implemented...

Hans Thielen added a comment - 09/May/17 07:32 AM
A "global" try catch is also not too hard to implement?!

Maybe it is not a critical bug, I did not prioritize this ticket. Anyway I think it is critical to suggest workarounds to cover up the deficiency of the software instead of just fixing it.

Beto Neto added a comment - 09/May/17 11:11 AM
I think this maybe isn't critical, but is out of standars.

I have created an updater for my application, as it primary step it executes an backup and restore of the database to garantee database consistence.

I was assuming blindly that the gbak exit code was following the standards, "a utility must return an exit code different of zero when errors occurs".

As a workaround I must now catch the syserr and everything printed on it will signal an "exit error code". I hope with this solution I do not have any new surprises, like "error messages printed in sysout".

Please fix it.