FirebirdSQL / firebird

Firebird server, client and tools
https://firebirdsql.org
1.26k stars 218 forks source link

gbak isn't returning exit code about errors when using service manager (-se) [CORE5520] #5789

Open firebird-automations opened 7 years ago

firebird-automations commented 7 years ago

Submitted by: Beto Neto (betoneto.tbo)

Votes: 2

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"

firebird-automations commented 7 years ago

Commented by: @AlexPeshkoff

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

firebird-automations commented 7 years ago

Commented by: Beto Neto (betoneto.tbo)

Try to simulate with this backup:

https://drive.google.com/drive/folders/0B-qEIYAtH5uPcW9OV3RzMTlPc28?usp=sharing

firebird-automations commented 7 years ago

Commented by: Hans Thielen (hansthielen)

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

firebird-automations commented 7 years ago

Commented by: @pavel-zotov

> 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. )

firebird-automations commented 7 years ago

Commented by: Hans Thielen (hansthielen)

>> 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.

firebird-automations commented 7 years ago

Commented by: Beto Neto (betoneto.tbo)

> 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

firebird-automations commented 7 years ago

Commented by: @pavel-zotov

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...

firebird-automations commented 7 years ago

Commented by: Hans Thielen (hansthielen)

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.

firebird-automations commented 7 years ago
Modified by: @dyemanov priority: Critical \[ 2 \] =\> Major \[ 3 \]
firebird-automations commented 7 years ago

Commented by: Beto Neto (betoneto.tbo)

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.