/*------------------------- New Concepts Consulting ---------------------------- - Application Module Name : OS/2 - File Name : rsync_backup.cmd - Date : June 06, 2018 - Author : Dariusz Piatkowski - - Description: - This script implements a SOURCE storage to TARGET storage folder routine - utilizing the RSYNC utility. It supports the notion of NAS or LOCAL folder - destinations. The difference is due to potentially different levels of the - OS/2 extended attribute support by either platform. - - There are a couple of modes of execution: - 1) the SOURCE and/or TARGET folders can be any location, LOCAL or a NETWORK - drive, however if it is a NETWORK drive it must be mapped to the local - filesystem as a drive, for example through a NetDrive mapping - 2) the backup_type parameter is of a LOCAL or NAS type, the following are - the assumptions about what filesystem attributes are supported on each: - a) LOCAL - this supports the FULL OS/2 attributes - b) NAS - this does not support the FULL OS/2 attributes (such extended) - - Subsequently the rsync parameters are written accordingly. - - Parameters: - Usage => RSYNC_BACKUP (LOCAL/NAS) "SOURCE" "TARGET" - - Modification History - - REVISON DATE/TIME AUTHOR - - Rev 1.0.0 JUN 06, 2020 Dariusz Piatkowski - First version of the code. - - Rev 1.1.0 SEP 14, 2020 Dariusz Piatkowski - Re-defined the structure of the code so that the parameter handling is no - longer static. This approach is discussed in the OS2World forum, see - thread => https://www.os2world.com/forum/index.php/topic,2571.0.html - - Rev 1.1.1 SEP 20, 2020 Dariusz Piatkowski - Added CLI parameter processing handling as per Andreas Schnellbacher's - sample code. Much appreciated!!! - - Rev 1.1.2 SEP 25, 2020 Dariusz Piatkowski - Added the LOG and DEBUG procedures to better handle logging and debug tasks - ------------------------------------------------------------------------------*/ CALL RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs' CALL SysLoadFuncs main: /* setup the GLOBAL variables */ debug_flag =0 calling_code ='MAIN' msg_level =0 msg_text ='Initializing...' crlf ='0D0A'x /* carriage return / line feed */ /* setup some logging and control file variables */ log_file_path ='G:\tmp\log\' rsync_exclude_file ='G:\mptn\etc\rsync_exclude' rsync_password_file ='' /* not used right now */ /* pull in the CLI params */ parse arg cli_arg call debug debug_flag calling_code msg_level msg_text msg_text='CLI input params =>'cli_arg'<=' call debug debug_flag calling_code msg_level msg_text /* parse the CLI params to pick up the BACKUP_TYPE, SOURCE and TARGET info */ call cli_parm_parse(cli_arg) /* put the BACKUP_TYPE paramter into UPPERCASE */ backup_type = translate(backup_type) /* notify of safe return to calling procedure */ msg_text='back to '||calling_code||' at MSG_LEVEL: '||msg_level call debug debug_flag calling_code msg_level msg_text /* check to see if a backup_type was specified */ if backup_type = '' then backup_type = 'UNKNOWN' msg_text ='Starting RSYNC for LOCAL to' backup_type 'backup!' call log debug_flag calling_code msg_level msg_text msg_text=crlf||'SOURCE_FOLDER => ' || source_folder call log debug_flag calling_code msg_level msg_text msg_text='TARGET_FOLDER => ' || target_folder call log debug_flag calling_code msg_level msg_text /* check to see if we have all the required input params */ if (backup_type = '') | (source_folder = '') | (target_folder = '') then do msg_text=crlf||"ERROR => Missing BACKUP_TYPE, SOURCE_FOLDER and/or TARGET_FOLDER locations!" call log debug_flag calling_code msg_level msg_text msg_text=crlf||"USAGE => RSYNC_BACKUP (LOCAL/NAS) SOURCE_FOLDER TARGET_FOLDER" call log debug_flag calling_code msg_level msg_text return end else do /* let's make the fully qualified RSYNC LOG filename */ rsync_log_file = log_file_path||'rsync_'||backup_type||'_backup.log ' /* OK, ready to run, so let's put together the RSYNC CLI */ if (backup_type = 'NAS') then /* depending on the NAS capability these may need to be adjusted to - support the handling of the OS/2 extended attributes */ CLI = '--dry-run --archive --delete --progress --stats --whole-file --no-xattrs --human-readable --quiet --exclude-from='||rsync_exclude_file||' --log-file='||rsync_log_file Enquote(source_folder) Enquote(target_folder) else if (backup_type = 'LOCAL') then /* WIP => need to put in LOCAL OS/2 specific RSYNC parameters to - preserve the extended attributes, etc. */ CLI = '--dry-run --archive --delete --progress --stats --whole-file --no-xattrs --human-readable --quiet --exclude-from='||rsync_exclude_file||' --log-file='||rsync_log_file Enquote(source_folder) Enquote(target_folder) /* show the RSYNC command line */ msg_text=crlf||"RSYNC CLI =>" CLI call debug debug_flag calling_code msg_level msg_text /* update the RSYNC LOG file with NEW run stamp */ msg_text=crlf||"===============================================================================" call lineout rsync_log_file,msg_text call log debug_flag calling_code msg_level msg_text /* get the START message built */ datetime_stamp = date('U')||" - "||time('N') msg_text = "RSYNC started: "||datetime_stamp||"..." call lineout rsync_log_file,msg_text call log debug_flag calling_code msg_level msg_text msg_text=crlf||"SOURCE_FOLDER => "||source_folder call lineout rsync_log_file,msg_text call log debug_flag calling_code msg_level msg_text msg_text="TARGET_FOLDER => "||target_folder call lineout rsync_log_file,msg_text call log debug_flag calling_code msg_level msg_text msg_text=crlf||"RSYNC CLI =>"||CLI call lineout rsync_log_file,msg_text call debug debug_flag calling_code msg_level msg_text msg_text=crlf||"-----------------------------------------" call lineout rsync_log_file,msg_text call debug debug_flag calling_code msg_level msg_text call lineout rsync_log_file /* reset the timer to 0, we will use later to get TOTAL duration */ call time('r') /* run the RSYNC command with command line input params */ '@g:\usr\bin\rsync' CLI /* update the RSYNC LOG file with NEW run stamp */ msg_text="-----------------------------------------" call lineout rsync_log_file,msg_text call debug debug_flag calling_code msg_level msg_text /* get the FINISH message built */ datetime_stamp = date('U')||" - "||time('N') msg_text = crlf||"RSYNC completed: "||datetime_stamp||"..." call lineout rsync_log_file,msg_text call log debug_flag calling_code msg_level msg_text msg_text=crlf||"RSYNC took "||time('e')||" seconds to complete the "||backup_type||" backup task!" call lineout rsync_log_file,msg_text call log debug_flag calling_code msg_level msg_text msg_text="===============================================================================" call lineout rsync_log_file,msg_text call log debug_flag calling_code msg_level msg_text call lineout rsync_log_file end exit 0 /* MAIN end */ /* subroutine to handle the command line parameter values */ cli_parm_parse: procedure expose debug_flag msg_level backup_type source_folder target_folder crlf /* Parse multiple args optionally enclosed in double quotes */ parse ARG Args Args = STRIP( Args) /* setup the variables */ calling_code='cli_parm_parse' msg_level=msg_level+1 msg_text='Initializing...' call debug debug_flag calling_code msg_level msg_text msg_text="CLI input params = " call debug debug_flag calling_code msg_level msg_text||Args /* Init vars */ Arg. = '' Arg.0 = 0 Rest = Args /* DEBUG data */ msg_text="CLI params length = " length(Args) call debug debug_flag calling_code msg_level msg_text /* Parse Rest */ DO WHILE Rest <> '' /* Advance arg counter */ NumArgs = Arg.0 + 1 msg_text=NumArgs': Rest = ['Rest']' call debug debug_flag calling_code msg_level msg_text /* Parse Next from Rest */ IF LEFT( Rest, 1) = '"' THEN PARSE VAR Rest '"'Next'"' Rest ELSE PARSE VAR Rest Next Rest msg_text=NumArgs': Next = ['Next']' call debug debug_flag calling_code msg_level msg_text /* Strip multiple spaces between args */ Rest = STRIP( Rest) /* Save Next to Arg. array */ Arg.NumArgs = Next Arg.0 = NumArgs END /* Test Arg. array */ DO i = 1 TO Arg.0 msg_text='Arg.'i' = 'Arg.i call debug debug_flag calling_code msg_level msg_text END /* assign the results to the MAIN program variables */ backup_type = Arg.1 source_folder = Arg.2 target_folder = Arg.3 /* reset DEBUG LEVEL tracker */ msg_level=msg_level-1 return 0 /* cli_parm_parse END */ /* subroutine to encapsulate the string with single quotes */ Enquote: rc = 0 PARSE ARG Filename IF VERIFY( Filename, ' &|<>', 'M') <> 0 THEN Filename = "'"Filename"'" RETURN( Filename) /* Enquote END */ /* subroutine to show DEBUG messages */ debug: procedure parse arg debug_flag calling_code msg_level msg_text /* get my own msg_level variable for indentation loop */ msg_level_cntr = msg_level /* check if DEBUG=ON */ if (debug_flag=1) then do /* reset variables */ msg_indent='DEBUG : ' /* for each msg_level unit indent accordingly */ do while msg_level_cntr <> 0 msg_indent = msg_indent||' ==> ' msg_level_cntr = msg_level_cntr-1 end say msg_indent||calling_code||' => '||msg_text end return 0 /* debug END */ /* subroutine to show LOG messages */ log: procedure parse arg debug_flag calling_code msg_level msg_text /* check to see if DEBUG=ON, if so , run through DEBUG routine */ if (debug_flag) then call debug debug_flag calling_code msg_level msg_text else say msg_text return 0 /* log END */