⬆️ ⬇️

Comprehensive automation of Firebird / InterBase database backup on Windows servers

image

The following material may be useful to novice database administrators who have realized the importance of creating a backup system, but have not yet acquired their own scripts or utilities. Below I will give the script as a command bat file used in our organization to automate the removal of backups from Firebird databases, analyze its key fragments and give examples of use. It is also suitable for Interbase or Yaffil databases, but I believe that with minimal rework of the call to the utility, it can be adapted for almost any DBMS.



First of all, I give a couple of links where you can and should read the theory of the question:

firebirdsql.org: Firebird's gbak Backup and Restore tool (eng.)

ibase.ru: GBAK, Firebird and InterBase Utility



A little about terms:



So, what activities make up the database backup process, if you approach the issue in a comprehensive way, and not limited to just running gbak.exe with the necessary keys? I would single out the following main ones:

  1. Check that the destination directory exists and, if necessary, create it (not all utilities will create a directory structure, if it turns out that the output file needs to be placed in a non-existent directory).
  2. Making a backup copy of the database using standard tools supplied with the server.
  3. Optional test restore backup (alas, but occasionally there are times when the server has created a backup file, but because of errors in the metadata could not restore it to a new database ).
  4. Optional compression of the backup file by the archiver.
  5. Optional control of stored backups by the number of files and / or the space they occupy.
  6. Notify the administrator of any kind of failures that occurred in the previous steps, by e-mail, NET SEND transport or other means. It is also desirable to maintain a cumulative log failures.


Our script, of course, can do all of the above, but it can also do something else:



Entry dragged on; Under the spoiler I bring the full source of the script.

source fb_backup.bat
@CLS @ECHO OFF ECHO #=============================================================================# ECHO # # ECHO # Firebird/InterBase database backup, test restore, zip and rotate script # ECHO # Ver 3.2.8 (26.01.2013) # ECHO # # ECHO # Author: arni (email:arnisoft at rambler dot ru) # ECHO # # ECHO # Format: # ECHO # FB_BACKUP [host[/port]:][path]db_file_or_alias result_dir # ECHO # [/count:backup_count] [/space:backup_space_limit] [/gc] # ECHO # [/restore] [/compress:level] [/password:SYSDBA_password] # ECHO # [other_files_to_compress [...]] # ECHO # # ECHO # Input params: # ECHO # [host[/port]:][path] : local or network, full-specified path or alias # ECHO # db_file_or_alias to the source database # ECHO # result_dir : result backup collecting directory # ECHO # /count:backup_count : backup file number to keep (30 by default) # ECHO # /space:backup_space_limit : total backup size in bytes (not use by default) # ECHO # you can use suffixes K, M or G. # ECHO # /gc : need to collect garbage in DB (OFF by default) # ECHO # /restore : need to do test restore (OFF by default) # ECHO # /compress:level : compress ratio for RAR (2 by default): # ECHO # 0: not compress, 1: fastest, 2: fast, # ECHO # 3: normal, 4: good, 5: best # ECHO # /password:SYSDBA_password : optional SYSDBA password for remote server # ECHO # (by default uses one from the source code) # ECHO # other_files_to_compress : list of files that must be add to archive # ECHO # # ECHO #=============================================================================# REM ==== Server ==================================================================== SET gbak="C:\Programs\FB25\bin\gbak.exe" SET ISC_USER=SYSDBA SET ISC_PASSWORD_LOCAL=masterkey SET ISC_PASSWORD_REMOTE= REM ==== Backup/restore preferences ================================================ SET temp_backup_dir=%TEMP% SET temp_restore_dir=%TEMP% SET backup_count=30 SET backup_space_limit=0 SET backup_ext=fbk SET garbage_collection=-g SET restore=0 REM ==== RAR ======================================================================= SET rar="C:\Program Files\WinRAR\rar.exe" SET rar_options=a -y -ep -idcd SET rar_password= SET rar_compress_ratio=2 REM ==== Mailer (see "Blat" at http://sourceforge.net/projects/blat) =============== SET blat="C:\Programs\Blat307\blat.exe" SET smtp_server=smtp.mailserver.ru SET mail_sender=foo@mailserver.ru SET mail_login=foo SET mail_password=1234 SET mail_receiver= SET mail_subject=Fail while database b/r REM ==== Other preferences ========================================================= SET include_logs_to_archive=1 SET net_send_receiver= SET error_log= REM ==== Define database location ================================================== SET full_db_specification=%~1 ECHO full_db_specification = %full_db_specification% REM Devide DB spec to network and local parts FOR /f "DELIMS=: TOKENS=1*" %%i IN ("%full_db_specification%") DO ( SET network=%%i SET local=%%j ) REM Test if spec. is alias with no network part IF "%local%" == "" ( SET network= SET local=%full_db_specification% ) REM Test if spec. is full specified file with no network part FOR /f "DELIMS=\ TOKENS=*" %%i IN ("%local%") DO IF "%local%" == "\%%i" ( SET network= SET local=%full_db_specification% ) ECHO network_specification = %network% IF "%network%" GTR "" ( REM Extract port from network spec (if exists) FOR /f "DELIMS=/ TOKENS=1*" %%i IN ("%network%") DO ( SET host=%%i SET port=%%j IF "%%j" GTR "" ( ECHO network_host = %%i ECHO network_port = %%j ) ) ) REM Test if DB is local or remote SET service_mgr_host=localhost SET is_local_db=1 IF "%network%" GTR "" IF "%host%" NEQ "127.0.0.1" IF /i "%host%" NEQ "localhost" SET is_local_db=0 IF %is_local_db% == 1 IF "%network%" GTR "" SET service_mgr_host=%network% ECHO local_db_specification = %local% IF "%local%" == "" ( SET fail=Param #1 {DB specification} missing! GOTO finish ) REM Extract file (or alias) from local part of spec. FOR /f %%i IN ("%local%") DO ( SET local_path=%%~dpi SET local_file_or_alias=%%~nxi ) IF "%local%" NEQ "%local_file_or_alias%" ( ECHO local_path = %local_path% REM Check DB file exists for local, not aliased specification IF %is_local_db% == 1 IF NOT EXIST "%local%" ( SET fail=Local DB file %local% not found! GOTO finish ) ) ECHO local_db_file_or_alias = %local_file_or_alias% REM ==== Define result directory =================================================== SET result_dir=%~2 ECHO result_dir = %result_dir% IF "%result_dir%" == "" ( SET fail=Param #2 {backup collecting directory} missing! GOTO finish ) REM Cut the result dir if it is in path-style (ends with separator) IF "%result_dir:~-1%" == "\" SET result_dir=%result_dir:~0,-1% REM Try to create the result directory if it is not exists yet IF NOT EXIST "%result_dir%" ( MD "%result_dir%" IF NOT EXIST "%result_dir%" ( SET fail=Cannot create backup collecting directory! GOTO finish ) ) REM Test if it is local or remote directory (elementary, may get wrong answer) SET is_local_result_dir=1 IF "%result_dir:~0,2%" == "\\" SET is_local_result_dir=0 REM ==== Use other command line options ============================================ :loop_options SHIFT SET next_param=%~2 IF "%next_param%" == "" GOTO print_options SET prefix=%next_param:~0,1% IF "%prefix%" == "/" SET next_param=%next_param:~1% IF "%prefix%" == "-" SET next_param=%next_param:~1% IF "%next_param%" GTR "" ( FOR /f "DELIMS=: TOKENS=1*" %%i IN ("%next_param%") DO ( SET value=%%j IF /i "%%i" == "count" IF "%%j" GTR "" GOTO count IF /i "%%i" == "space" IF "%%j" GTR "" GOTO space IF /i "%%i" == "gc" GOTO gc IF /i "%%i" == "restore" GOTO restore IF /i "%%i" == "compress" IF "%%j" GTR "" GOTO compress IF /i "%%i" == "password" IF "%%j" GTR "" GOTO password IF EXIST "%next_param%" GOTO add_file_to_compress IF "%prefix%" GTR "/" GOTO add_file_to_compress ECHO unknown param found: %next_param% GOTO loop_options ) ) ELSE ( ECHO empty param found! GOTO loop_options ) REM ==== Define file count in the result dir ======================================= :count SET /a backup_count=0+%value% GOTO loop_options REM ==== Define allowed backup space limit ========================================= :space SET suffix=%value:~-1% IF "%suffix%" GTR "9" ( SET value=%value:~0,-1% IF /i "%suffix%" == "K" ( SET file_size_shift=0 SET /a value*=1000 ) IF /i "%suffix%" == "M" ( SET file_size_shift=3 SET /a value*=1000 ) IF /i "%suffix%" == "G" ( SET file_size_shift=6 SET /a value*=1000 ) ) SET /a backup_space_limit=0+%value% GOTO loop_options REM ==== Define need of garbage collection ========================================= :gc SET garbage_collection= IF "%value%" == "0" SET garbage_collection=-g IF /i "%value%" == "N" SET garbage_collection=-g IF /i "%value%" == "NO" SET garbage_collection=-g IF /i "%value%" == "OFF" SET garbage_collection=-g GOTO loop_options REM ==== Define need of test restore =============================================== :restore SET restore=1 IF "%value%" == "0" SET restore=0 IF /i "%value%" == "N" SET restore=0 IF /i "%value%" == "NO" SET restore=0 IF /i "%value%" == "OFF" SET restore=0 GOTO loop_options REM ==== Define need of backup compression and compress ratio ====================== :compress IF "%value%" GEQ "0" IF "%value%" LEQ "5" SET rar_compress_ratio=%value% GOTO loop_options REM ==== Define SYSDBA password (in addition or for replace source code given) ===== :password if "%ISC_PASSWORD_LOCAL%" GTR "" if "%ISC_PASSWORD_REMOTE%" GTR "" ( SET ISC_PASSWORD_LOCAL=%value% SET ISC_PASSWORD_REMOTE=%value% ) if "%ISC_PASSWORD_LOCAL%" == "" SET ISC_PASSWORD_LOCAL=%value% if "%ISC_PASSWORD_REMOTE%" == "" SET ISC_PASSWORD_REMOTE=%value% GOTO loop_options REM ==== Define file list to compress (in addition to backup and maybe logs) ======= :add_file_to_compress IF "%backup_files%" == "" ( SET backup_files="%next_param%" ) ELSE ( SET backup_files=%backup_files% "%next_param%" ) GOTO loop_options REM ==== Print predefined or recognized in command line options ==================== :print_options IF %backup_count% GTR 0 ( ECHO backup_count = %backup_count% ) ELSE ( ECHO backup_count = OFF ) IF "%file_size_shift%" == "" SET file_size_shift=0 IF %backup_space_limit% GTR 0 ( IF %file_size_shift% == 6 ( ECHO backup_space_limit = %backup_space_limit% Mb ) ELSE IF %file_size_shift% == 3 ( ECHO backup_space_limit = %backup_space_limit% Kb ) ELSE ECHO backup_space_limit = %backup_space_limit% bytes ) ELSE ( ECHO backup_space_limit = OFF ) IF "%garbage_collection%" == "-g" ( ECHO garbage_collection_flag = OFF ) ELSE ( ECHO garbage_collection_flag = ON ) IF %restore% == 0 ( ECHO test_restore_flag = OFF ) ELSE ( ECHO test_restore_flag = ON ) IF %rar_compress_ratio% == 0 ( ECHO backup_compressing = OFF ) ELSE ( ECHO backup_compressing = ON, RAR-ratio=%rar_compress_ratio% ) REM ==== Define backup file and backup log ========================================= SET datetime=%date:~-2%%date:~3,2%%date:~0,2%_%time:~0,2%%time:~3,2% SET finish_file=%result_dir%\%local_file_or_alias%.%datetime: =0%.%backup_ext% SET direct_backup=0 IF %rar_compress_ratio% == 0 ( IF %is_local_result_dir% == 1 SET direct_backup=1 IF %restore% == 0 SET direct_backup=1 ) IF %direct_backup% == 1 ( SET backup_file=%finish_file% ) ELSE ( SET backup_file=%temp_backup_dir%\%local_file_or_alias%.%backup_ext% IF NOT EXIST "%temp_backup_dir%" ( MD "%temp_backup_dir%" IF NOT EXIST "%temp_backup_dir%" ( SET fail=Cannot create backup directory! GOTO finish ) ) ) ECHO backup_file = %backup_file% SET backup_log=%result_dir%\%local_file_or_alias%.backup.log ECHO backup_log = %backup_log% REM ==== Define restore file and restore log ======================================= SET restore_file=%temp_restore_dir%\%local_file_or_alias%.testrest IF %restore% GTR 0 ( IF NOT EXIST "%temp_restore_dir%" ( MD "%temp_restore_dir%" IF NOT EXIST "%temp_restore_dir%" ( ECHO temp_restore_dir = %temp_restore_dir% SET fail=Cannot create restore directory! GOTO finish ) ) ECHO restore_file = %restore_file% SET restore_log=%result_dir%\%local_file_or_alias%.restore.log ) IF "%restore_log%" GTR "" ( ECHO restore_log = %restore_log% ) else ( SET restore_log=just_a_stub ) REM ==== Define compresed file ===================================================== SET compressed_file=%finish_file%.rar IF %rar_compress_ratio% GTR 0 ( ECHO compressed_file = %compressed_file% SET finish_file=%compressed_file% ) REM ==== Delete not actual files (over defined count) ============================== SET /a over=%backup_count%-1 IF %backup_count% == 1 ( ECHO deleting_old_files = %result_dir%\%local_file_or_alias%.*.%backup_ext%* DEL "%result_dir%\%local_file_or_alias%.*.%backup_ext%*" /q ) ELSE IF %backup_count% GTR 1 ( FOR /f "SKIP=%over%" %%f IN ('DIR "%result_dir%\%local_file_or_alias%.*.%backup_ext%*" /a:-D /b /o:-N 2^>NUL') DO ( IF EXIST "%result_dir%\%%f" ( ECHO deleting_old_file = %result_dir%\%%f DEL "%result_dir%\%%f" /q ) ) ) REM ==== Perform backup ============================================================ IF EXIST "%backup_log%" DEL "%backup_log%" /q ECHO backup_start = %date% %time:~0,8% SET is_local_backup=0 IF %is_local_db% == 1 ( IF %is_local_result_dir% == 1 SET is_local_backup=1 IF %direct_backup% == 0 SET is_local_backup=1 SET ISC_PASSWORD=%ISC_PASSWORD_LOCAL% ) ELSE ( SET ISC_PASSWORD=%ISC_PASSWORD_REMOTE% ) IF "%rar_password%" == "" SET rar_password=%ISC_PASSWORD% IF %is_local_backup% == 1 ( ECHO %gbak% -b %garbage_collection% -se %service_mgr_host%:service_mgr %local% "%backup_file%" -v -y "%backup_log%" %gbak% -b %garbage_collection% -se %service_mgr_host%:service_mgr %local% "%backup_file%" -v >"%backup_log%" 2>&1 ) ELSE ( ECHO %gbak% -b %garbage_collection% "%full_db_specification%" "%backup_file%" -v -y "%backup_log%" %gbak% -b %garbage_collection% "%full_db_specification%" "%backup_file%" -v >"%backup_log%" 2>&1 ) IF %ERRORLEVEL% GTR 0 ( IF EXIST "%backup_log%" ( SET fail=Backup fail! See %backup_log% for details. ) ELSE ( SET fail=Backup fail! ) GOTO finish ) IF NOT EXIST "%backup_log%" ( SET fail=Backup fail! GOTO finish ) REM ==== Perform test restore ====================================================== IF %restore% GTR 0 ( IF EXIST "%restore_log%" DEL "%restore_log%" /q IF "%ISC_PASSWORD_LOCAL%" GTR "" ( SET ISC_PASSWORD=%ISC_PASSWORD_LOCAL% ) ELSE ( SET ISC_PASSWORD=%ISC_PASSWORD_REMOTE% ) ECHO restore_start = %date% %time:~0,8% ECHO %gbak% -rep -se %service_mgr_host%:service_mgr "%backup_file%" "%restore_file%" -v -y "%restore_log%" %gbak% -rep -se %service_mgr_host%:service_mgr "%backup_file%" "%restore_file%" -v >"%restore_log%" 2>&1 IF %ERRORLEVEL% GTR 0 ( IF EXIST "%restore_log%" ( SET fail=Test restore fail! See %restore_log% for details. ) ELSE ( SET fail=Test restore fail! ) GOTO finish ) IF NOT EXIST "%restore_log%" ( SET fail=Test restore fail! GOTO finish ) ) REM ==== Perform RAR-compression or copy backup into destination dir =============== IF "%rar_password%" GTR "" SET rar_password=-p%rar_password% SET rar_options=%rar_options% -m%rar_compress_ratio% SET backup_files="%backup_file%" %backup_files% IF %include_logs_to_archive% == 1 ( IF %restore% GTR 0 ( SET backup_files=%backup_files% "%backup_log%" "%restore_log%" ) ELSE ( SET backup_files=%backup_files% "%backup_log%" ) ) IF %rar_compress_ratio% GTR 0 ( ECHO compressing_start = %date% %time:~0,8% ECHO %rar% %rar_options% "%compressed_file%" %backup_files% %rar% %rar_options% %rar_password% "%compressed_file%" %backup_files% IF %ERRORLEVEL% GTR 0 ( SET fail=Compression fail! GOTO finish ) ) ELSE IF %direct_backup% == 0 ( ECHO copying_start = %date% %time:~0,8% ECHO COPY "%backup_file%" "%finish_file%" COPY "%backup_file%" "%finish_file%" ) REM ==== Delete not actual files (over defined space) ============================== IF %backup_space_limit% GTR 0 ( SETLOCAL EnableDelayedExpansion IF %ERRORLEVEL% GTR 0 ( ECHO You must enable var delayed expansion by CMD.EXE /V:ON or at registry key ECHO Software\Microsoft\Command Processor\DelayedExpansion: HKLM or HKCU GOTO finish ) FOR /f %%f IN ('DIR "%result_dir%\%local_file_or_alias%.*.%backup_ext%*" /a:-D /b /o:-N') DO ( FOR %%i in ("%result_dir%\%%f") DO ( SET size=%%~zi IF %file_size_shift% == 3 SET size=!size:~0,-3! IF %file_size_shift% == 6 SET size=!size:~0,-6! IF "!size!" == "" SET size=0 IF "!total_space!" == "" ( SET /a total_space=!size! ) ELSE ( IF !total_space! LEQ %backup_space_limit% SET /a total_space+=!size! IF !total_space! GTR %backup_space_limit% ( ECHO deleting_overquota_file = %result_dir%\%%f DEL "%result_dir%\%%f" /q ) ) ) ) ) REM ==== Report when fail or exit ================================================== :finish IF "%fail%" == "" ( ECHO Finish = %date% %time:~0,8% GOTO exit ) ECHO #=============================================================================# ECHO # %fail% ECHO #=============================================================================# SET fail=%fail%, DB: %full_db_specification%, Dest: %result_dir% IF "%net_send_receiver%" GTR "" ( ECHO NET SEND %net_send_receiver% "%fail%" NET SEND %net_send_receiver% "%fail%" ) IF "%blat%" GTR "" IF "%smtp_server%" GTR "" IF "%mail_sender%" GTR "" IF "%mail_login%" GTR "" IF "%mail_receiver%" GTR "" ( ECHO %blat% -to "%mail_receiver%" -subject "%mail_subject%" -body "%fail%" -server %smtp_server% -f "%mail_sender%" -u "%mail_login%" -pw "*******" %blat% -to "%mail_receiver%" -subject "%mail_subject%" -body "%fail%" -server %smtp_server% -f "%mail_sender%" -u "%mail_login%" -pw "%mail_password%" ) SET time_ex=%time: =0% IF "%error_log%" GTR "" ( ECHO %date% %time_ex:~0,8% %fail% >> "%error_log%" ) EXIT /b 1 :exit 


I will also give a log generated by running the script in the simplest form: no additional keys, all parameters by default, only the database address and the destination directory are transferred

fb_backup.bat localhost: p: \ MSO \ DB \ MS_ORDERS.FDB \\ 192.168.1.1 \ disk_a1 \ exchange> fb_backup.log
 #=============================================================================# # # # Firebird/InterBase database backup, test restore, zip and rotate script # # Ver 3.2.7 (11.11.2012) # # # # Author: arni (email:arnisoft at rambler dot ru) # # # # Format: # # FB_BACKUP [host[/port]:][path]db_file_or_alias result_dir # # [/count:backup_count] [/space:backup_space_limit] [/gc] # # [/restore] [/compress:level] [/password:SYSDBA_password] # # [other_files_to_compress [...]] # # # # Input params: # # [host[/port]:][path] : local or network, full-specified path or alias # # db_file_or_alias to the source database # # result_dir : result backup collecting directory # # /count:backup_count : backup file number to keep (30 by default) # # /space:backup_space_limit : total backup size in bytes (not use by default) # # you can use suffixes K, M or G. # # /gc : need to collect garbage in DB (OFF by default) # # /restore : need to do test restore (OFF by default) # # /compress:level : compress ratio for RAR (2 by default): # # 0: not compress, 1: fastest, 2: fast, # # 3: normal, 4: good, 5: best # # /password:SYSDBA_password : optional SYSDBA password for remote server # # (by default uses one from the source code) # # other_files_to_compress : list of files that must be add to archive # # # #=============================================================================# full_db_specification = localhost:p:\MSO\DB\MS_ORDERS.FDB network_specification = localhost local_db_specification = p:\MSO\DB\MS_ORDERS.FDB local_path = p:\MSO\DB\ local_db_file_or_alias = MS_ORDERS.FDB result_dir = \\192.168.1.1\disk_a1\ backup_count = 30 backup_space_limit = OFF garbage_collection_flag = OFF test_restore_flag = OFF backup_compressing = ON, RAR-ratio=2 backup_file = C:\WINDOWS\TEMP\MS_ORDERS.FDB.fbk backup_log = \\192.168.1.1\disk_a1\\MS_ORDERS.FDB.backup.log compressed_file = \\192.168.1.1\disk_a1\\MS_ORDERS.FDB.121111_1621.fbk.rar backup_start = 11.11.2012 16:21:48 "C:\Programs\FB25\bin\gbak.exe" -b -g -se localhost:service_mgr p:\MSO\DB\MS_ORDERS.FDB "C:\WINDOWS\TEMP\MS_ORDERS.FDB.fbk" -v -y "\\192.168.1.1\disk_a1\\MS_ORDERS.FDB.backup.log" compressing_start = 11.11.2012 16:21:51 "C:\Program Files\WinRAR\rar.exe" a -y -ep -idcd -m2 "\\192.168.1.1\disk_a1\\MS_ORDERS.FDB.121111_1621.fbk.rar" "C:\WINDOWS\TEMP\MS_ORDERS.FDB.fbk" "\\192.168.1.1\disk_a1\\MS_ORDERS.FDB.backup.log"   \\192.168.1.1\disk_a1\\MS_ORDERS.FDB.121111_1621.fbk.rar  C:\WINDOWS\TEMP\MS_ORDERS.FDB.fbk 6% 12% 18% 24% 30% 36% 42% 48% 54% 60% 66% 72% 78% 84% 86% OK  \\192.168.1.1\disk_a1\\MS_ORDERS.FDB.backup.log 92% 98%100% OK Finish = 11.11.2012 16:21:51 


Let's analyze the script fragments:

header part
The header contains a link to the authorship, the current version, but the main thing is the description of the call format: which parameters are basic, which are optional, which default values ​​are optional parameters.

Optional parameters can be in any order, and they should be preceded by standard characters of the command line key: a forward slash [/] or a dash [-].
 @CLS @ECHO OFF ECHO #=============================================================================# ECHO # # ECHO # Firebird/InterBase database backup, test restore, zip and rotate script # ECHO # Ver 3.2.8 (26.01.2013) # ECHO # # ECHO # Author: arni (email:arnisoft at rambler dot ru) # ECHO # # ECHO # Format: # ECHO # FB_BACKUP [host[/port]:][path]db_file_or_alias result_dir # ECHO # [/count:backup_count] [/space:backup_space_limit] [/gc] # ECHO # [/restore] [/compress:level] [/password:SYSDBA_password] # ECHO # [other_files_to_compress [...]] # ECHO # # ECHO # Input params: # ECHO # [host[/port]:][path] : local or network, full-specified path or alias # ECHO # db_file_or_alias to the source database # ECHO # result_dir : result backup collecting directory # ECHO # /count:backup_count : backup file number to keep (30 by default) # ECHO # /space:backup_space_limit : total backup size in bytes (not use by default) # ECHO # you can use suffixes K, M or G. # ECHO # /gc : need to collect garbage in DB (OFF by default) # ECHO # /restore : need to do test restore (OFF by default) # ECHO # /compress:level : compress ratio for RAR (2 by default): # ECHO # 0: not compress, 1: fastest, 2: fast, # ECHO # 3: normal, 4: good, 5: best # ECHO # /password:SYSDBA_password : optional SYSDBA password for remote server # ECHO # (by default uses one from the source code) # ECHO # other_files_to_compress : list of files that must be add to archive # ECHO # # ECHO #=============================================================================# 


defining default parameters
here we see 5 blocks responsible for the sections:

  • server settings;
  • b / r parameters;
  • archiver parameters;
  • mailer parameters;
  • other parameters;
 REM ==== Server ==================================================================== SET gbak="C:\Programs\FB25\bin\gbak.exe" SET ISC_USER=SYSDBA SET ISC_PASSWORD_LOCAL=masterkey SET ISC_PASSWORD_REMOTE= REM ==== Backup/restore preferences ================================================ SET temp_backup_dir=%TEMP% SET temp_restore_dir=%TEMP% SET backup_count=30 SET backup_space_limit=0 SET backup_ext=fbk SET garbage_collection=-g SET restore=0 REM ==== RAR ======================================================================= SET rar="C:\Program Files\WinRAR\rar.exe" SET rar_options=a -y -ep -idcd SET rar_password= SET rar_compress_ratio=2 REM ==== Mailer (see "Blat" at http://sourceforge.net/projects/blat) =============== SET blat="C:\Programs\Blat307\blat.exe" SET smtp_server=smtp.mailserver.ru SET mail_sender=foo@mailserver.ru SET mail_login=foo SET mail_password=1234 SET mail_receiver= SET mail_subject=Fail while database b/r REM ==== Other preferences ========================================================= SET include_logs_to_archive=1 SET net_send_receiver= SET error_log= 
Where:

  • gbak - the path to the utility utility from the server bundle;
  • ISC_USER - the user on whose behalf b / r will occur;
  • ISC_PASSWORD_LOCAL - password of the selected user on the local machine;
  • ISC_PASSWORD_REMOTE - the password of the selected user on the remote machine (it is better to send with the / password parameter: xxxxxxxx);
  • temp_backup_dir - temporary directory where backup will be made before archiving it into the destination directory; it is better to choose a physical disk that does not coincide with where the source database is located;
  • temp_restore_dir - directory where the test restore will be made; it is better to choose a physical disk that does not coincide with the location of the original database, and does not coincide with the location of the backup file;
  • backup_ext - default file extension with backup;
  • garbage_collection is the gbak.exe key, which is responsible for the default behavior regarding garbage collection during backup (it is better to control the / gc parameter);
  • restore - default behavior flag regarding the need to perform a test restore (it is better to manage the / restore parameter);
  • rar_options - default RAR archiver keys: “a” - compress; "-y" - do not ask questions; "-ep" - exclude paths; "-idcd" - do not litter the output of copyright and a mark of readiness;
  • rar_password - password for the archive (if not set, the archiver uses the password of the Firebird user);
  • rar_compress_ratio - default compression ratio (it is better to control the / compress: level parameter)
  • blat - path to mailer blat.exe;
  • smtp_server - SMTP server, through which the distribution will be made;
  • mail_sender - the mailing address of the sender;
  • mail_login - the sender's login on the server;
  • mail_password - sender password on the server;
  • mail_receiver - mailing address of the recipient;
  • mail_subject - mailing header;
  • include_logs_to_archive - flag to put b / r logs inside the archive;
  • net_send_receiver is the network name of the host to which NET SEND transport alerts will be sent;
  • error_log - file of the drive log of failures that occurred;


source definition
Here we see:

  • Reading the specification of the source database from the first passed parameter;
  • The separation of the specification into the host name, port, local path and name of the database file or its alias;
  • Printing parts of the specification to the console;
  • Finding out whether this database is local or remote (it will be important later when choosing between a classic backup or backup via services);
 REM ==== Define database location ================================================== SET full_db_specification=%~1 ECHO full_db_specification = %full_db_specification% REM Devide DB spec to network and local parts FOR /f "DELIMS=: TOKENS=1*" %%i IN ("%full_db_specification%") DO ( SET network=%%i SET local=%%j ) REM Test if spec. is alias with no network part IF "%local%" == "" ( SET network= SET local=%full_db_specification% ) REM Test if spec. is full specified file with no network part FOR /f "DELIMS=\ TOKENS=*" %%i IN ("%local%") DO IF "%local%" == "\%%i" ( SET network= SET local=%full_db_specification% ) ECHO network_specification = %network% IF "%network%" GTR "" ( REM Extract port from network spec (if exists) FOR /f "DELIMS=/ TOKENS=1*" %%i IN ("%network%") DO ( SET host=%%i SET port=%%j IF "%%j" GTR "" ( ECHO network_host = %%i ECHO network_port = %%j ) ) ) REM Test if DB is local or remote SET service_mgr_host=localhost SET is_local_db=1 IF "%network%" GTR "" IF "%host%" NEQ "127.0.0.1" IF /i "%host%" NEQ "localhost" SET is_local_db=0 IF %is_local_db% == 1 IF "%network%" GTR "" SET service_mgr_host=%network% ECHO local_db_specification = %local% IF "%local%" == "" ( SET fail=Param #1 {DB specification} missing! GOTO finish ) REM Extract file (or alias) from local part of spec. FOR /f %%i IN ("%local%") DO ( SET local_path=%%~dpi SET local_file_or_alias=%%~nxi ) IF "%local%" NEQ "%local_file_or_alias%" ( ECHO local_path = %local_path% REM Check DB file exists for local, not aliased specification IF %is_local_db% == 1 IF NOT EXIST "%local%" ( SET fail=Local DB file %local% not found! GOTO finish ) ) ECHO local_db_file_or_alias = %local_file_or_alias% 


definition of the resulting directory (where backups are added)
Here we see:

  • Reading the resulting directory from the second parameter passed to the script;
  • If the resulting directory is missing, it is created;
  • Determining the location of the directory: local or remote (network) - will be needed below to select the optimal backup strategy;
 REM ==== Define result directory =================================================== SET result_dir=%~2 ECHO result_dir = %result_dir% IF "%result_dir%" == "" ( SET fail=Param #2 {backup collecting directory} missing! GOTO finish ) REM Cut the result dir if it is in path-style (ends with separator) IF "%result_dir:~-1%" == "\" SET result_dir=%result_dir:~0,-1% REM Try to create the result directory if it is not exists yet IF NOT EXIST "%result_dir%" ( MD "%result_dir%" IF NOT EXIST "%result_dir%" ( SET fail=Cannot create backup collecting directory! GOTO finish ) ) REM Test if it is local or remote directory (elementary, may get wrong answer) SET is_local_result_dir=1 IF "%result_dir:~0,2%" == "\\" SET is_local_result_dir=0 
This block has an error handling code, in the event of which, the essence of the failure is written to the variable, after which control is transferred to the end of the script - to the feedback block with the admin. Such handlers are found in all subsequent blocks, and I will not specifically mention them further.


read remaining passed parameters
Here we see the blocks:

  • reading the next parameter;
  • separation of a key into name and value;
  • recognition of the key, the transition to its processing;
  • setting the number of stored copies;
  • setting the total volume of copies;
  • control of the garbage collection flag in the database;
  • control of test recovery flag;
  • determination of the compression ratio by the archiver;
  • Saving the SYSDBA password for the remote server;
  • reading a list of additional files for archiving;
 REM ==== Use other command line options ============================================ :loop_options SHIFT SET next_param=%~2 IF "%next_param%" == "" GOTO print_options SET prefix=%next_param:~0,1% IF "%prefix%" == "/" SET next_param=%next_param:~1% IF "%prefix%" == "-" SET next_param=%next_param:~1% IF "%next_param%" GTR "" ( FOR /f "DELIMS=: TOKENS=1*" %%i IN ("%next_param%") DO ( SET value=%%j IF /i "%%i" == "count" IF "%%j" GTR "" GOTO count IF /i "%%i" == "space" IF "%%j" GTR "" GOTO space IF /i "%%i" == "gc" GOTO gc IF /i "%%i" == "restore" GOTO restore IF /i "%%i" == "compress" IF "%%j" GTR "" GOTO compress IF /i "%%i" == "password" IF "%%j" GTR "" GOTO password IF EXIST "%next_param%" GOTO add_file_to_compress IF "%prefix%" GTR "/" GOTO add_file_to_compress ECHO unknown param found: %next_param% GOTO loop_options ) ) ELSE ( ECHO empty param found! GOTO loop_options ) REM ==== Define file count in the result dir ======================================= :count SET /a backup_count=0+%value% GOTO loop_options REM ==== Define allowed backup space limit ========================================= :space SET suffix=%value:~-1% IF "%suffix%" GTR "9" ( SET value=%value:~0,-1% IF /i "%suffix%" == "K" ( SET file_size_shift=0 SET /a value*=1000 ) IF /i "%suffix%" == "M" ( SET file_size_shift=3 SET /a value*=1000 ) IF /i "%suffix%" == "G" ( SET file_size_shift=6 SET /a value*=1000 ) ) SET /a backup_space_limit=0+%value% GOTO loop_options REM ==== Define need of garbage collection ========================================= :gc SET garbage_collection= IF "%value%" == "0" SET garbage_collection=-g IF /i "%value%" == "N" SET garbage_collection=-g IF /i "%value%" == "NO" SET garbage_collection=-g IF /i "%value%" == "OFF" SET garbage_collection=-g GOTO loop_options REM ==== Define need of test restore =============================================== :restore SET restore=1 IF "%value%" == "0" SET restore=0 IF /i "%value%" == "N" SET restore=0 IF /i "%value%" == "NO" SET restore=0 IF /i "%value%" == "OFF" SET restore=0 GOTO loop_options REM ==== Define need of backup compression and compress ratio ====================== :compress IF "%value%" GEQ "0" IF "%value%" LEQ "5" SET rar_compress_ratio=%value% GOTO loop_options REM ==== Define SYSDBA password (in addition or for replace source code given) ===== :password if "%ISC_PASSWORD_LOCAL%" GTR "" if "%ISC_PASSWORD_REMOTE%" GTR "" ( SET ISC_PASSWORD_LOCAL=%value% SET ISC_PASSWORD_REMOTE=%value% ) if "%ISC_PASSWORD_LOCAL%" == "" SET ISC_PASSWORD_LOCAL=%value% if "%ISC_PASSWORD_REMOTE%" == "" SET ISC_PASSWORD_REMOTE=%value% GOTO loop_options REM ==== Define file list to compress (in addition to backup and maybe logs) ======= :add_file_to_compress IF "%backup_files%" == "" ( SET backup_files="%next_param%" ) ELSE ( SET backup_files=%backup_files% "%next_param%" ) GOTO loop_options 
Note:

  • Boolean flags for restaurants or garbage collection take the following values: False = 0, N, NO, OFF; True = 1, Y, YES, ON.
  • The cumulative amount of stored data is transmitted in bytes. But since numbers in the command processor are limited to a 32-bit integer, then it is better to transfer values ​​above 1 GB, indicating the suffix of kilobyte (K), megabyte (M) or gigabyte (G). For example: / space: 1200K, / space: 280M, / space: 12G. In this block, you can also observe code that truncates the scale of storage units, allowing you to further operate with volumes, in excess of 32-bit command-processor arithmetic.
  • The transmitted password is interpreted as follows: if the values ​​of both the ISC_PASSWORD_LOCAL variable (local) and the ISC_PASSWORD_REMOTE variable (remote) are defined in the source code, the transferred value overrides both of these variables. In other cases (if at least one variable is not defined), the transferred value is written only to an empty variable, and the filled value retains its predefined value.
  • Additional files for compression (or file masks) are transmitted in their natural form, without the key symbol [/].


print run script summary settings
Here we see:

  • output the number of stored copies;
  • output cumulative copy storage space;
  • displaying the garbage collection flag;
  • output of the test recovery flag;
  • displaying the archive feature and compression ratio used;
 REM ==== Print predefined or recognized in command line options ==================== :print_options IF %backup_count% GTR 0 ( ECHO backup_count = %backup_count% ) ELSE ( ECHO backup_count = OFF ) IF "%file_size_shift%" == "" SET file_size_shift=0 IF %backup_space_limit% GTR 0 ( IF %file_size_shift% == 6 ( ECHO backup_space_limit = %backup_space_limit% Mb ) ELSE IF %file_size_shift% == 3 ( ECHO backup_space_limit = %backup_space_limit% Kb ) ELSE ECHO backup_space_limit = %backup_space_limit% bytes ) ELSE ( ECHO backup_space_limit = OFF ) IF "%garbage_collection%" == "-g" ( ECHO garbage_collection_flag = OFF ) ELSE ( ECHO garbage_collection_flag = ON ) IF %restore% == 0 ( ECHO test_restore_flag = OFF ) ELSE ( ECHO test_restore_flag = ON ) IF %rar_compress_ratio% == 0 ( ECHO backup_compressing = OFF ) ELSE ( ECHO backup_compressing = ON, RAR-ratio=%rar_compress_ratio% ) 


job definition
Here we see:

  • removing the timestamp to use it in the backup file name;
  • determining whether we will backup directly to the destination directory, or first to temporary storage for subsequent recovery, compression, etc .;
  • definition of the full specification of the backup file;
  • definition of the full specification of the backup log;
  • printout of calculated parameters;
  • definition and printing of the file specification for the restaurant and the restaurant log, if the restaurant flag is raised;
  • definition and printing of an archive file, if compression is requested;
 REM ==== Define backup file and backup log ========================================= SET datetime=%date:~-2%%date:~3,2%%date:~0,2%_%time:~0,2%%time:~3,2% SET finish_file=%result_dir%\%local_file_or_alias%.%datetime: =0%.%backup_ext% SET direct_backup=0 IF %rar_compress_ratio% == 0 ( IF %is_local_result_dir% == 1 SET direct_backup=1 IF %restore% == 0 SET direct_backup=1 ) IF %direct_backup% == 1 ( SET backup_file=%finish_file% ) ELSE ( SET backup_file=%temp_backup_dir%\%local_file_or_alias%.%backup_ext% IF NOT EXIST "%temp_backup_dir%" ( MD "%temp_backup_dir%" IF NOT EXIST "%temp_backup_dir%" ( SET fail=Cannot create backup directory! GOTO finish ) ) ) ECHO backup_file = %backup_file% SET backup_log=%result_dir%\%local_file_or_alias%.backup.log ECHO backup_log = %backup_log% REM ==== Define restore file and restore log ======================================= SET restore_file=%temp_restore_dir%\%local_file_or_alias%.testrest IF %restore% GTR 0 ( IF NOT EXIST "%temp_restore_dir%" ( MD "%temp_restore_dir%" IF NOT EXIST "%temp_restore_dir%" ( ECHO temp_restore_dir = %temp_restore_dir% SET fail=Cannot create restore directory! GOTO finish ) ) ECHO restore_file = %restore_file% SET restore_log=%result_dir%\%local_file_or_alias%.restore.log ) IF "%restore_log%" GTR "" ( ECHO restore_log = %restore_log% ) else ( SET restore_log=just_a_stub ) REM ==== Define compresed file ===================================================== SET compressed_file=%finish_file%.rar IF %rar_compress_ratio% GTR 0 ( ECHO compressed_file = %compressed_file% SET finish_file=%compressed_file% ) 


remove unnecessary copies from the destination directory
 REM ==== Delete not actual files (over defined count) ============================== SET /a over=%backup_count%-1 IF %backup_count% == 1 ( ECHO deleting_old_files = %result_dir%\%local_file_or_alias%.*.%backup_ext%* DEL "%result_dir%\%local_file_or_alias%.*.%backup_ext%*" /q ) ELSE IF %backup_count% GTR 1 ( FOR /f "SKIP=%over%" %%f IN ('DIR "%result_dir%\%local_file_or_alias%.*.%backup_ext%*" /a:-D /b /o:-N 2^>NUL') DO ( IF EXIST "%result_dir%\%%f" ( ECHO deleting_old_file = %result_dir%\%%f DEL "%result_dir%\%%f" /q ) ) ) 


run backup
Here we see:

  • delete the previous backup log (gbak.exe will return an error if it bumps into the old log);
  • depending on whether the database is recognized as local or remote, a password is selected;
  • depending on the location of the database and the location of the catalog for backup, we determine the ability to use the fastest possible strategy - backup through services, or classic backup otherwise;
 REM ==== Perform backup ============================================================ IF EXIST "%backup_log%" DEL "%backup_log%" /q ECHO backup_start = %date% %time:~0,8% SET is_local_backup=0 IF %is_local_db% == 1 ( IF %is_local_result_dir% == 1 SET is_local_backup=1 IF %direct_backup% == 0 SET is_local_backup=1 SET ISC_PASSWORD=%ISC_PASSWORD_LOCAL% ) ELSE ( SET ISC_PASSWORD=%ISC_PASSWORD_REMOTE% ) IF "%rar_password%" == "" SET rar_password=%ISC_PASSWORD% IF %is_local_backup% == 1 ( ECHO %gbak% -b %garbage_collection% -se %service_mgr_host%:service_mgr %local% "%backup_file%" -v -y "%backup_log%" %gbak% -b %garbage_collection% -se %service_mgr_host%:service_mgr %local% "%backup_file%" -v >"%backup_log%" 2>&1 ) ELSE ( ECHO %gbak% -b %garbage_collection% "%full_db_specification%" "%backup_file%" -v -y "%backup_log%" %gbak% -b %garbage_collection% "%full_db_specification%" "%backup_file%" -v >"%backup_log%" 2>&1 ) IF %ERRORLEVEL% GTR 0 ( IF EXIST "%backup_log%" ( SET fail=Backup fail! See %backup_log% for details. ) ELSE ( SET fail=Backup fail! ) GOTO finish ) IF NOT EXIST "%backup_log%" ( SET fail=Backup fail! GOTO finish ) 


performing test recovery
Here we see:

  • delete the previous restaurant log (gbak.exe will return an error if it stumbles upon the old log);
  • performing recovery (always via services, since both the backup file and the test database are local in this branch of the script);
 REM ==== Perform test restore ====================================================== IF %restore% GTR 0 ( IF EXIST "%restore_log%" DEL "%restore_log%" /q IF "%ISC_PASSWORD_LOCAL%" GTR "" ( SET ISC_PASSWORD=%ISC_PASSWORD_LOCAL% ) ELSE ( SET ISC_PASSWORD=%ISC_PASSWORD_REMOTE% ) ECHO restore_start = %date% %time:~0,8% ECHO %gbak% -rep -se %service_mgr_host%:service_mgr "%backup_file%" "%restore_file%" -v -y "%restore_log%" %gbak% -rep -se %service_mgr_host%:service_mgr "%backup_file%" "%restore_file%" -v >"%restore_log%" 2>&1 IF %ERRORLEVEL% GTR 0 ( IF EXIST "%restore_log%" ( SET fail=Test restore fail! See %restore_log% for details. ) ELSE ( SET fail=Test restore fail! ) GOTO finish ) IF NOT EXIST "%restore_log%" ( SET fail=Test restore fail! GOTO finish ) ) 
Note:

If you have InterBase, Yaffil or Firebird earlier than version 2.0, the recovery flag -rep should be replaced with -r


archive compression
Here we see:

  • collection of all parameters and rar keys, including archive password and compression ratio;
  • collection of all files for compression, including backup, logs (if specified by the policy) and other files (if transferred);
  • if compression is set, we compress;
  • if compression is disabled, then simply copy the backup file to the destination directory (only if the script of the script did not create it initially there);
 REM ==== Perform RAR-compression or copy backup into destination dir =============== IF "%rar_password%" GTR "" SET rar_password=-p%rar_password% SET rar_options=%rar_options% -m%rar_compress_ratio% SET backup_files="%backup_file%" %backup_files% IF %include_logs_to_archive% == 1 ( IF %restore% GTR 0 ( SET backup_files=%backup_files% "%backup_log%" "%restore_log%" ) ELSE ( SET backup_files=%backup_files% "%backup_log%" ) ) IF %rar_compress_ratio% GTR 0 ( ECHO compressing_start = %date% %time:~0,8% ECHO %rar% %rar_options% "%compressed_file%" %backup_files% %rar% %rar_options% %rar_password% "%compressed_file%" %backup_files% IF %ERRORLEVEL% GTR 0 ( SET fail=Compression fail! GOTO finish ) ) ELSE IF %direct_backup% == 0 ( ECHO copying_start = %date% %time:~0,8% ECHO COPY "%backup_file%" "%finish_file%" COPY "%backup_file%" "%finish_file%" ) 
Note:

In a number of discussions, there are examples when, in order to speed up the compression of a backup copy, gbak.exe and rar.exe are launched together, when the output of the first is fed directly to the input of the second. Unfortunately, this method has a significant drawback that does not allow recommending it for use: if gbak.exe fails, then in the end a zero (successful) return code is returned, because rar.exe honestly and accurately saved those crumbs that gbak.exe managed to transfer to it before it collapsed. Those. you will never know that the backup-making process fails until you try to restore a broken backup, or you do not accidentally pay attention to the size of the final archive.


deleting files beyond the specified disk quota
Here we see:

  • An attempt to activate the delayed expansion of variables in the command processor (in case of failure, we inform the user and exit the block), which is necessary for calculating the total volume of files;
  • Enumerate accumulated backups from the freshest to the most ancient, and counting their total volume. , . , 32- ( ), .
 REM ==== Delete not actual files (over defined space) ============================== IF %backup_space_limit% GTR 0 ( SETLOCAL EnableDelayedExpansion IF %ERRORLEVEL% GTR 0 ( ECHO You must enable var delayed expansion by CMD.EXE /V:ON or at registry key ECHO Software\Microsoft\Command Processor\DelayedExpansion: HKLM or HKCU GOTO finish ) FOR /f %%f IN ('DIR "%result_dir%\%local_file_or_alias%.*.%backup_ext%*" /a:-D /b /o:-N') DO ( FOR %%i in ("%result_dir%\%%f") DO ( SET size=%%~zi IF %file_size_shift% == 3 SET size=!size:~0,-3! IF %file_size_shift% == 6 SET size=!size:~0,-6! IF "!size!" == "" SET size=0 IF "!total_space!" == "" ( SET /a total_space=!size! ) ELSE ( IF !total_space! LEQ %backup_space_limit% SET /a total_space+=!size! IF !total_space! GTR %backup_space_limit% ( ECHO deleting_overquota_file = %result_dir%\%%f DEL "%result_dir%\%%f" /q ) ) ) ) ) 


final part
:

  • , : , , ;
  • NET SEND, ;
  • (, , , ), ;
  • - , ;
  • — , ( — ), ;
 REM ==== Report when fail or exit ================================================== :finish IF "%fail%" == "" ( ECHO Finish = %date% %time:~0,8% GOTO exit ) ECHO #=============================================================================# ECHO # %fail% ECHO #=============================================================================# SET fail=%fail%, DB: %full_db_specification%, Dest: %result_dir% IF "%net_send_receiver%" GTR "" ( ECHO NET SEND %net_send_receiver% "%fail%" NET SEND %net_send_receiver% "%fail%" ) IF "%blat%" GTR "" IF "%smtp_server%" GTR "" IF "%mail_sender%" GTR "" IF "%mail_login%" GTR "" IF "%mail_receiver%" GTR "" ( ECHO %blat% -to "%mail_receiver%" -subject "%mail_subject%" -body "%fail%" -server %smtp_server% -f "%mail_sender%" -u "%mail_login%" -pw "*******" %blat% -to "%mail_receiver%" -subject "%mail_subject%" -body "%fail%" -server %smtp_server% -f "%mail_sender%" -u "%mail_login%" -pw "%mail_password%" ) SET time_ex=%time: =0% IF "%error_log%" GTR "" ( ECHO %date% %time_ex:~0,8% %fail% >> "%error_log%" ) EXIT /b 1 :exit 


Let me give a couple of scenarios that describe the use of the script in our daily practice. Conditionally call them "night backup" and "day backup."

At night, no one works with the base, or almost no one. Server resources are idle, and therefore it is appropriate to make a full b / r cycle, namely:

- backup with garbage collection;

- test recovery;

- compression of the backup and the current version of the application, and the compression is the best;

Here is an example of running a “night backup”:

 fb_backup.bat localhost:Orma4 d:\Bak /count:99 /space:500G /compress:5 /restore /gc d:\Orma.exe >C:\Orma4.log 2>&1 


On the contrary, the launch of the “daily backup” should work as quickly as possible, straining the server as little as possible, and hence the users connected to the database. Therefore, we exclude garbage collection and test recovery, compress the fastest method, and only the backup file:

 fb_backup.bat localhost:Orma4 d:\Bak /count:99 /space:500G /compress:1 >C:\Orma4.log 2>&1 


There is another option for recording backup to a remote server (for security reasons, according to the principle “do not store all eggs in one basket”). It combines an intermediate set of keys: you need to press the most tightly, because The archiver usually manages to re-grind faster than the network copes with downloading the file, and other operations (garbage collection, test restoration, saving the application program, etc.) should be eliminated if possible, because they have already been executed by a “night backup” to the local server:

 fb_backup.bat localhost:Orma4 \\ifs\E$\backup\FirebirdDB /count:99 /space:300G /compress:5 >C:\Orma4.log 2>&1 


For those who do not know, ending the command means redirecting the output of the script (stdout) to a file, and outputting the error (stderr) to the same file.
  >C:\Orma4.log 2>&1 




A little about the limitations of the script.



')

Source: https://habr.com/ru/post/158575/



All Articles