Compare commits
9 Commits
1dce024cd8
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 04d946aa00 | |||
| bd7d5da70e | |||
| c2ef3e05e3 | |||
| 14b1d29384 | |||
| 024d06a827 | |||
| 09fd3b2c67 | |||
| 6c1f8c926e | |||
| 67050cf3a0 | |||
| ab2e15d717 |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -6,6 +6,7 @@ __pycache__/
|
|||||||
env/
|
env/
|
||||||
venv/
|
venv/
|
||||||
ENV/
|
ENV/
|
||||||
|
SCRATCH
|
||||||
|
|
||||||
# macOS system files
|
# macOS system files
|
||||||
.DS_Store
|
.DS_Store
|
||||||
@@ -16,7 +17,11 @@ ENV/
|
|||||||
|
|
||||||
# Exclude Rubrik API config files
|
# Exclude Rubrik API config files
|
||||||
rbk_api.conf
|
rbk_api.conf
|
||||||
|
rubrik.conf
|
||||||
|
*.json
|
||||||
|
|
||||||
# Other common ignores
|
# Other common ignores
|
||||||
*.swp
|
*.swp
|
||||||
*.swo
|
*.swo
|
||||||
|
|
||||||
|
releases/
|
||||||
|
|||||||
172
README.md
Normal file
172
README.md
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
# Rubrik Oracle Backup Scripts for HP-UX
|
||||||
|
|
||||||
|
This collection of Korn shell (ksh) scripts provides automated backup solutions for Oracle databases using Rubrik Managed Volumes (MVs) on HP-UX systems. The scripts are designed to be HP-UX compatible and handle RMAN backups with incremental merge functionality.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- **Operating System**: HP-UX 11i or later (also works on Linux/Solaris/AIX)
|
||||||
|
- **Shell**: Korn shell (ksh) - standard on HP-UX
|
||||||
|
- **Tools**: curl, awk, egrep, date, expr, mkdir, hostname, ps, find, chmod
|
||||||
|
- **Oracle**: Oracle Database with RMAN configured
|
||||||
|
- **Rubrik**: Access to Rubrik CDM with Managed Volumes configured
|
||||||
|
- **Permissions**: Scripts should be run as the Oracle user
|
||||||
|
|
||||||
|
## RMAN Configuration
|
||||||
|
|
||||||
|
The script will
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
1. Copy `rbk_api.conf.example` to `rbk_api.conf`
|
||||||
|
2. Edit `rbk_api.conf` with your Rubrik settings:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Rubrik API Configuration
|
||||||
|
ID="your-service-account-id"
|
||||||
|
SECRET="your-service-account-secret"
|
||||||
|
RUBRIK_IP="your-rubrik-cluster-ip"
|
||||||
|
|
||||||
|
# Mount point prefix for Managed Volumes
|
||||||
|
MOUNTPOINT_PREFIX="/rubrik_"
|
||||||
|
|
||||||
|
# Log retention settings
|
||||||
|
HOSTLOGRET=2
|
||||||
|
MV_SPACE_WARN=75
|
||||||
|
|
||||||
|
# Number of RMAN channels to allocate per NFS mount
|
||||||
|
RMAN_CHANNELS_PER_MOUNT=1
|
||||||
|
|
||||||
|
# Logging directories
|
||||||
|
API_LOG_DIR=/tmp/rubrik
|
||||||
|
RMAN_LOG_DIR=/tmp/rubrik/rman
|
||||||
|
|
||||||
|
# Alert settings
|
||||||
|
ALERT_EMAILS="admin@example.com"
|
||||||
|
EMAIL_SUCCESS=1
|
||||||
|
```
|
||||||
|
|
||||||
|
## Scripts Overview
|
||||||
|
|
||||||
|
### oracle_funcs.ksh
|
||||||
|
Shared functions library containing:
|
||||||
|
- API authentication and REST calls
|
||||||
|
- Managed Volume operations (open/close)
|
||||||
|
- Error handling and logging
|
||||||
|
- OS detection and date handling
|
||||||
|
|
||||||
|
### list_mv.ksh
|
||||||
|
Lists all Managed Volumes visible to the configured service account, showing each MV's name and `isWritable` status.
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
```bash
|
||||||
|
./list_mv.ksh
|
||||||
|
```
|
||||||
|
|
||||||
|
**Output:**
|
||||||
|
```
|
||||||
|
Service account in use is client|...
|
||||||
|
Managed Volumes visible to this account:
|
||||||
|
mv_name_1: isWritable=true
|
||||||
|
mv_name_2: isWritable=false
|
||||||
|
```
|
||||||
|
|
||||||
|
### rubrik_mv_op.ksh
|
||||||
|
Opens or closes a Managed Volume for backup operations.
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
```bash
|
||||||
|
./rubrik_mv_op.ksh -d <DBNAME> -v <logs|data> -o <open|close>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Examples:**
|
||||||
|
```bash
|
||||||
|
# Open data volume for ORCL database
|
||||||
|
./rubrik_mv_op.ksh -d ORCL -v data -o open
|
||||||
|
|
||||||
|
# Close logs volume for ORCL database
|
||||||
|
./rubrik_mv_op.ksh -d ORCL -v logs -o close
|
||||||
|
```
|
||||||
|
|
||||||
|
### rman_db.ksh
|
||||||
|
Performs RMAN database backup with incremental merge to Rubrik Managed Volume.
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
```bash
|
||||||
|
./rman_db.ksh <ORACLE_SID>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Features:**
|
||||||
|
- Incremental level 1 backup with merge
|
||||||
|
- Automatic MV open/close
|
||||||
|
- Configurable RMAN channels per NFS mount (RMAN_CHANNELS_PER_MOUNT)
|
||||||
|
- Disk space monitoring
|
||||||
|
- Email alerts on failure/success
|
||||||
|
- Archive log backup
|
||||||
|
|
||||||
|
### rman_logs.ksh
|
||||||
|
Performs RMAN archive log backup to Rubrik Managed Volume.
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
```bash
|
||||||
|
./rman_logs.ksh <ORACLE_SID>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Features:**
|
||||||
|
- Backs up all not-backed-up archive logs
|
||||||
|
- Configurable RMAN channels per NFS mount (RMAN_CHANNELS_PER_MOUNT)
|
||||||
|
- Automatic MV open/close
|
||||||
|
- Disk space monitoring
|
||||||
|
- Optional host-side log purging
|
||||||
|
- Email alerts
|
||||||
|
|
||||||
|
## HP-UX Compatibility Notes
|
||||||
|
|
||||||
|
These scripts are specifically designed for HP-UX compatibility:
|
||||||
|
|
||||||
|
- Uses `ksh` instead of `bash`
|
||||||
|
- Avoids GNU-specific commands (`grep -o`, `readlink`)
|
||||||
|
- Portable `awk` for JSON parsing
|
||||||
|
- HP-UX date handling with fallback to GNU date
|
||||||
|
- No reliance on symlinks for script location detection
|
||||||
|
|
||||||
|
## Logging
|
||||||
|
|
||||||
|
- API calls are logged to `$API_LOG_DIR/api_calls.log`
|
||||||
|
- RMAN operations are logged to `$RMAN_LOG_DIR/$ORACLE_SID/`
|
||||||
|
- Use `tail -f` on log files for monitoring
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Common Issues
|
||||||
|
|
||||||
|
1. **"readlink not found"**: Scripts use portable directory detection
|
||||||
|
2. **JSON parsing errors**: Ensure Rubrik API returns expected format
|
||||||
|
3. **MV not found**: Check MV naming convention: `${HOST}_${ORACLE_SID}_data/logs`
|
||||||
|
4. **Permission denied**: Run as Oracle user, ensure MV mount points are accessible
|
||||||
|
5. **Curl errors**: Check network connectivity to Rubrik cluster
|
||||||
|
|
||||||
|
### Debug Mode
|
||||||
|
|
||||||
|
Add debug output by modifying scripts to show raw API responses.
|
||||||
|
|
||||||
|
### Testing Compatibility
|
||||||
|
|
||||||
|
Run the included `test.ksh` script to verify HP-UX compatibility of required tools.
|
||||||
|
|
||||||
|
## Security Notes
|
||||||
|
|
||||||
|
- Store `rbk_api.conf` securely with appropriate permissions
|
||||||
|
- Service account should have minimal required permissions
|
||||||
|
- Avoid logging secrets in log files
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
For issues specific to Rubrik CDM or Oracle integration, consult:
|
||||||
|
- Rubrik documentation
|
||||||
|
- Oracle RMAN documentation
|
||||||
|
- HP-UX system administration guides
|
||||||
|
|
||||||
|
## Version History
|
||||||
|
|
||||||
|
- v1.1: Enhanced list_mv.ksh with isWritable status, HP-UX compatibility improvements
|
||||||
|
- v1.0: Initial release with basic RMAN backup functionality
|
||||||
82
check_date.ksh
Executable file
82
check_date.ksh
Executable file
@@ -0,0 +1,82 @@
|
|||||||
|
#!/usr/bin/ksh
|
||||||
|
echo "Checking date command availability and date arithmetic support..."
|
||||||
|
|
||||||
|
# Check for date commands
|
||||||
|
echo "Available date commands:"
|
||||||
|
if command -v date >/dev/null 2>&1; then
|
||||||
|
echo " date: $(which date)"
|
||||||
|
DATE_CMD="date"
|
||||||
|
else
|
||||||
|
echo " date: NOT FOUND"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v gdate >/dev/null 2>&1; then
|
||||||
|
echo " gdate: $(which gdate)"
|
||||||
|
if [ -z "$DATE_CMD" ]; then
|
||||||
|
DATE_CMD="gdate"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " gdate: NOT FOUND in PATH"
|
||||||
|
# Check common HP-UX locations for gdate
|
||||||
|
echo " Checking common HP-UX locations for gdate..."
|
||||||
|
for gdate_path in /usr/local/bin/gdate /opt/gnu/bin/gdate /usr/contrib/bin/gdate /opt/coreutils/bin/gdate; do
|
||||||
|
if [ -x "$gdate_path" ]; then
|
||||||
|
echo " gdate: FOUND at $gdate_path"
|
||||||
|
if [ -z "$DATE_CMD" ]; then
|
||||||
|
DATE_CMD="$gdate_path"
|
||||||
|
fi
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ -z "$DATE_CMD" ] || [ "$DATE_CMD" = "date" ]; then
|
||||||
|
echo " gdate: NOT FOUND in common locations"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v perl >/dev/null 2>&1; then
|
||||||
|
echo " perl: $(which perl)"
|
||||||
|
PERL_AVAILABLE=1
|
||||||
|
else
|
||||||
|
echo " perl: NOT FOUND"
|
||||||
|
PERL_AVAILABLE=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$DATE_CMD" ]; then
|
||||||
|
echo "ERROR: No date command found!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Testing date arithmetic with: $DATE_CMD"
|
||||||
|
|
||||||
|
# Test basic date
|
||||||
|
echo "Basic date output:"
|
||||||
|
$DATE_CMD +"%Y-%m-%d %H:%M:%S"
|
||||||
|
|
||||||
|
# Test date arithmetic like used in rman_db.ksh
|
||||||
|
echo ""
|
||||||
|
echo "Testing date arithmetic: '$DATE_CMD +%m-%d-%Y\ %H:%M:%S -d \"-1 hour\"'"
|
||||||
|
if $DATE_CMD -d "-1 hour" >/dev/null 2>&1; then
|
||||||
|
RESULT=$($DATE_CMD +%m-%d-%Y\ %H:%M:%S -d '-1 hour')
|
||||||
|
echo "SUCCESS: Date arithmetic works"
|
||||||
|
echo "Result: $RESULT"
|
||||||
|
else
|
||||||
|
echo "ERROR: Date arithmetic (-d option) not supported"
|
||||||
|
echo "This system may need GNU date (gdate) installed"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Test perl-based date arithmetic as fallback
|
||||||
|
if [ $PERL_AVAILABLE -eq 1 ]; then
|
||||||
|
echo ""
|
||||||
|
echo "Testing perl-based date arithmetic fallback:"
|
||||||
|
echo "Command: perl -e 'use POSIX qw(strftime); \$time = time() - 3600; print strftime(\"%m-%d-%Y %H:%M:%S\", localtime(\$time))'"
|
||||||
|
PERL_RESULT=$(perl -e 'use POSIX qw(strftime); $time = time() - 3600; print strftime("%m-%d-%Y %H:%M:%S", localtime($time))')
|
||||||
|
echo "SUCCESS: Perl date arithmetic works"
|
||||||
|
echo "Result: $PERL_RESULT"
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
echo "WARNING: Perl not available - no fallback for date arithmetic"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Test complete."
|
||||||
61
list_mv.ksh
Executable file
61
list_mv.ksh
Executable file
@@ -0,0 +1,61 @@
|
|||||||
|
#!/usr/bin/ksh
|
||||||
|
#
|
||||||
|
# List MVs using API call to RSC, for diagnostic purposes
|
||||||
|
# Written for HCL / Nokia
|
||||||
|
# v1.1 - James Pattinson - October 2025
|
||||||
|
#
|
||||||
|
# usage: list_mv.ksh
|
||||||
|
_SCRIPT_="$0"
|
||||||
|
|
||||||
|
get_script_dir() {
|
||||||
|
script="$1"
|
||||||
|
case "$script" in
|
||||||
|
/*) abs_path="$script" ;;
|
||||||
|
*) abs_path="$PWD/$script" ;;
|
||||||
|
esac
|
||||||
|
while [ -L "$abs_path" ]; do
|
||||||
|
link=$(readlink "$abs_path")
|
||||||
|
case "$link" in
|
||||||
|
/*) abs_path="$link" ;;
|
||||||
|
*) abs_path="$(dirname "$abs_path")/$link" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
script_dir=$(dirname "$abs_path")
|
||||||
|
cd "$script_dir" 2>/dev/null && pwd
|
||||||
|
}
|
||||||
|
|
||||||
|
MYDIR=$(get_script_dir "$_SCRIPT_")
|
||||||
|
. $MYDIR/rubrik.conf
|
||||||
|
. $MYDIR/oracle_funcs.ksh
|
||||||
|
|
||||||
|
# Script starts here
|
||||||
|
|
||||||
|
echo "Service account in use is $ID"
|
||||||
|
echo "Managed Volumes visible to this account:"
|
||||||
|
|
||||||
|
ENDPOINT="https://$RUBRIK_IP/api/internal/managed_volume"
|
||||||
|
rest_api_get
|
||||||
|
|
||||||
|
awk '
|
||||||
|
{
|
||||||
|
|
||||||
|
line = $0
|
||||||
|
pos = 1
|
||||||
|
while (match(substr(line, pos), /"name":"[^"]*"/)) {
|
||||||
|
start = pos + RSTART + 7
|
||||||
|
len = RLENGTH - 9
|
||||||
|
name = substr(line, start, len)
|
||||||
|
pos += RSTART + RLENGTH - 1
|
||||||
|
if (match(substr(line, pos), /"isWritable":[ ]*(true|false)/)) {
|
||||||
|
start_w = pos + RSTART + 12
|
||||||
|
len_w = RLENGTH - 13
|
||||||
|
writable = substr(line, start_w, len_w)
|
||||||
|
print name ": isWritable=" writable
|
||||||
|
pos += RSTART + RLENGTH - 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' /tmp/rbkresponse.$$
|
||||||
|
|
||||||
|
cleanup
|
||||||
|
|
||||||
32
list_mv.sh
32
list_mv.sh
@@ -1,32 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
#
|
|
||||||
# List MVs using API call to CDM, for diagnostic purposes
|
|
||||||
# Written for HCL / Nokia
|
|
||||||
# v1.1 - James Pattinson - October 2025
|
|
||||||
#
|
|
||||||
# usage: list_mv.sh
|
|
||||||
|
|
||||||
|
|
||||||
MYDIR="$(dirname "$(readlink -f "$0")")"
|
|
||||||
source $MYDIR/rbk_api.conf
|
|
||||||
source $MYDIR/oracle_funcs.sh
|
|
||||||
|
|
||||||
# Script starts here
|
|
||||||
|
|
||||||
echo Service account in use is $ID
|
|
||||||
|
|
||||||
echo ALL MVs
|
|
||||||
|
|
||||||
ENDPOINT="https://$RUBRIK_IP/api/internal/managed_volume"
|
|
||||||
rest_api_get
|
|
||||||
|
|
||||||
grep -Eo '"name"[^,]*' /tmp/rbkresponse.$$
|
|
||||||
|
|
||||||
echo NonRelic MVs
|
|
||||||
|
|
||||||
ENDPOINT="https://$RUBRIK_IP/api/internal/managed_volume?is_relic=false"
|
|
||||||
rest_api_get
|
|
||||||
|
|
||||||
grep -Eo '"name"[^,]*' /tmp/rbkresponse.$$
|
|
||||||
|
|
||||||
cleanup
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/ksh
|
||||||
#
|
#
|
||||||
# Oracle shell script support functions
|
# Oracle shell script support functions
|
||||||
# Written for HCL / Nokia
|
# Written for HCL / Nokia
|
||||||
# v1.0 - James Pattinson - October 2025
|
# v1.0 - James Pattinson - November 2025
|
||||||
|
|
||||||
nowait=0
|
nowait=0
|
||||||
|
|
||||||
@@ -10,73 +10,105 @@ LOGFILE=$API_LOG_DIR/api_calls.log
|
|||||||
mkdir -p $API_LOG_DIR
|
mkdir -p $API_LOG_DIR
|
||||||
tabwidth=25
|
tabwidth=25
|
||||||
|
|
||||||
HOST=$(hostname -s)
|
|
||||||
|
|
||||||
os=$(uname -o)
|
# Portable short hostname function
|
||||||
if [ $os == "Solaris" ]; then
|
get_short_hostname() {
|
||||||
# Use the GNU version of date binary
|
# Check OS type first - HP-UX hostname doesn't support -s
|
||||||
DATE=/usr/gnu/bin/date
|
os_type=$(uname -s)
|
||||||
else
|
if [ "$os_type" = "HP-UX" ]; then
|
||||||
DATE=$(which date)
|
hostname | awk -F. '{print $1}'
|
||||||
fi
|
else
|
||||||
|
# Try -s flag on other systems
|
||||||
|
if hostname -s >/dev/null 2>&1; then
|
||||||
|
hostname -s
|
||||||
|
else
|
||||||
|
hostname | awk -F. '{print $1}'
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
HOST=$(get_short_hostname)
|
||||||
|
|
||||||
|
# Detect OS and set DATE variable appropriately
|
||||||
|
os_name=$(uname -s)
|
||||||
|
case "$os_name" in
|
||||||
|
Linux)
|
||||||
|
DATE=$(which date)
|
||||||
|
;;
|
||||||
|
SunOS)
|
||||||
|
# Solaris
|
||||||
|
DATE=/usr/gnu/bin/date
|
||||||
|
;;
|
||||||
|
HP-UX)
|
||||||
|
# HP/UX: try gdate, fallback to date with warning
|
||||||
|
if command -v gdate >/dev/null 2>&1; then
|
||||||
|
DATE=$(command -v gdate)
|
||||||
|
else
|
||||||
|
DATE=$(command -v date)
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
DATE=$(which date)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
echo "`$DATE` -$$-: CALLED $0 $@" >> $LOGFILE
|
echo "`$DATE` -$$-: CALLED $0 $@" >> $LOGFILE
|
||||||
|
|
||||||
trap ctrl_c INT
|
trap ctrl_c INT
|
||||||
|
|
||||||
function ctrl_c () {
|
ctrl_c() {
|
||||||
echo "`$DATE` -$$-: TRAPPED CTRL-C - EXITING" >> $LOGFILE
|
echo "`$DATE` -$$-: TRAPPED CTRL-C - EXITING" >> $LOGFILE
|
||||||
exit_with_error
|
exit_with_error
|
||||||
}
|
}
|
||||||
|
|
||||||
function ctrl_c_inhibit () {
|
ctrl_c_inhibit() {
|
||||||
echo "`$DATE` -$$-: TRAPPED CTRL-C - CONTINUING" >> $LOGFILE
|
echo "`$DATE` -$$-: TRAPPED CTRL-C - CONTINUING" >> $LOGFILE
|
||||||
}
|
}
|
||||||
|
|
||||||
exit_with_error () {
|
exit_with_error() {
|
||||||
# if [ $usingsatoken ]; then
|
ENDPOINT="https://$RUBRIK_IP/api/v1/session/me"
|
||||||
# ENDPOINT="https://$RUBRIK_IP/api/v1/session/me"
|
rest_api_delete
|
||||||
# rest_api_delete
|
check_http_error
|
||||||
# check_http_error
|
|
||||||
# fi
|
|
||||||
|
|
||||||
cat /tmp/rbkresponse.$$ | mailx -s "Backup error on ${HOST} for ${ORACLE_SID}. Please investigate" $ALERT_EMAILS
|
cat /tmp/rbkresponse.$$ | mailx -s "Backup error on ${HOST} for ${ORACLE_SID}. Please investigate" $ALERT_EMAILS
|
||||||
rm -f /tmp/rbkresponse.$$
|
rm -f /tmp/rbkresponse.$$
|
||||||
rm -f /tmp/mountedDBs.$$
|
rm -f /tmp/mountedDBs.$$
|
||||||
rm -f $PIDFILE
|
rm -f $PIDFILE
|
||||||
echo Aborting Script!
|
echo Aborting Script!
|
||||||
echo "`$DATE` -$$-: EXITED WITH ERROR $0 $@" >> $LOGFILE
|
echo "`$DATE` -$$-: EXITED WITH ERROR $0 $@" >> $LOGFILE
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
check_http_error () {
|
check_http_error() {
|
||||||
# All good responses start with a 2
|
# All good responses start with a 2
|
||||||
if [ ${http_response:0:1} != "2" ]; then
|
first_char=$(echo "$http_response" | cut -c1)
|
||||||
echo FATAL: HTTP error from API call: $http_response. The server responded with:
|
if [ "$first_char" != "2" ]; then
|
||||||
cat /tmp/rbkresponse.$$ ; echo ; exit_with_error
|
echo FATAL: HTTP error from API call: $http_response. The server responded with:
|
||||||
fi
|
cat /tmp/rbkresponse.$$ ; echo ; exit_with_error
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
check_pid () {
|
check_pid() {
|
||||||
|
|
||||||
if [ -f $PIDFILE ]
|
if [ -f $PIDFILE ]
|
||||||
then
|
then
|
||||||
PID=$(cat $PIDFILE)
|
PID=$(cat $PIDFILE)
|
||||||
ps -p $PID > /dev/null 2>&1
|
if ps -p $PID > /dev/null 2>&1; then
|
||||||
if [ $? -eq 0 ]
|
echo "ERROR: MV already being used by process ID $PID"
|
||||||
then
|
if ps -fp $PID > /dev/null 2>&1; then
|
||||||
echo "ERROR: MV already being used by process ID $PID"
|
ps -fp $PID
|
||||||
ps -fp $PID
|
else
|
||||||
exit_with_error
|
ps -ef | awk -v pid=$PID '$2==pid'
|
||||||
else
|
fi
|
||||||
## Process not found assume not running
|
exit_with_error
|
||||||
echo $$ > $PIDFILE
|
else
|
||||||
if [ $? -ne 0 ]
|
## Process not found assume not running
|
||||||
then
|
echo $$ > $PIDFILE
|
||||||
echo "ERROR: Could not create mvLock file"
|
if [ $? -ne 0 ]
|
||||||
exit_with_error
|
then
|
||||||
fi
|
echo "ERROR: Could not create mvLock file"
|
||||||
fi
|
exit_with_error
|
||||||
|
fi
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo $$ > $PIDFILE
|
echo $$ > $PIDFILE
|
||||||
if [ $? -ne 0 ]
|
if [ $? -ne 0 ]
|
||||||
@@ -88,53 +120,31 @@ check_pid () {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
check_get_token () {
|
|
||||||
|
|
||||||
if [ -z "${AUTH_TOKEN}" ]; then
|
# Get a new token only if AUTH_TOKEN is not already set
|
||||||
|
check_get_token() {
|
||||||
# RSC
|
if [ -z "$AUTH_TOKEN" ]; then
|
||||||
id_string=$(echo $ID | cut -d\| -f 2)
|
get_token
|
||||||
# CDM
|
fi
|
||||||
id_string=$(echo $ID | cut -d: -f 4)
|
|
||||||
|
|
||||||
if [ -f ~/.rbksession.$id_string ]; then
|
|
||||||
echo "`$DATE` -$$-: AUTH SESSION FILE EXISTS" >> $LOGFILE
|
|
||||||
read expiration token < <(echo $(cat ~/.rbksession.$id_string))
|
|
||||||
if [ $($DATE +%s -u -d $expiration) -lt $(( $($DATE +%s) + 1800 )) ]; then
|
|
||||||
echo "`$DATE` -$$-: AUTH TOKEN EXPIRED" >> $LOGFILE
|
|
||||||
get_token
|
|
||||||
else
|
|
||||||
AUTH_TOKEN=$token
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
get_token
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get_token () {
|
get_token() {
|
||||||
|
|
||||||
trap '' INT
|
echo "`$DATE` -$$-: AUTH USER $ID" >> $LOGFILE
|
||||||
echo "`$DATE` -$$-: AUTH USER $ID" >> $LOGFILE
|
MYENDPOINT="https://$RUBRIK_IP/api/v1/service_account/session"
|
||||||
MYENDPOINT="https://$RUBRIK_IP/api/v1/service_account/session"
|
MYPAYLOAD='{"serviceAccountId":"'$ID'","secret":"'$SECRET'"}'
|
||||||
MYPAYLOAD="{\"serviceAccountId\":\"$ID\",\"secret\":\"$SECRET\"}"
|
|
||||||
|
|
||||||
http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X POST $MYENDPOINT -H "accept: application/json" -H "Content-Type: application/json" -d $MYPAYLOAD)
|
http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X POST $MYENDPOINT -H "accept: application/json" -H "Content-Type: application/json" -d "$MYPAYLOAD")
|
||||||
check_http_error
|
check_http_error
|
||||||
|
|
||||||
AUTH_TOKEN=$(grep -Eo '"token"[^,]*' /tmp/rbkresponse.$$ | grep -Eo '[^:]*$' | sed 's/\"//g')
|
AUTH_TOKEN=$(cat /tmp/rbkresponse.$$ | awk '{match($0, /"token":"[^"]*"/); if (RSTART > 0) {print substr($0, RSTART+9, RLENGTH-10);}}')
|
||||||
SESSION=$(grep -Eo '"sessionId"[^,]*' /tmp/rbkresponse.$$ | grep -Eo '[^:]*$' | sed 's/\"//g')
|
|
||||||
EXPIRATION=$(grep -Eo '"expirationTime"[^,]*' /tmp/rbkresponse.$$ | cut -d: -f 2-4 | sed 's/\"//g' | sed 's/.000Z//;s/T/Z/')
|
echo "`$DATE` -$$-: AUTH SESSION $SESSION" >> $LOGFILE
|
||||||
|
|
||||||
echo "`$DATE` -$$-: AUTH SESSION $SESSION" >> $LOGFILE
|
|
||||||
echo "`$DATE` -$$-: SAVING TOKEN TO FILE" >> $LOGFILE
|
|
||||||
echo "$EXPIRATION $AUTH_TOKEN" > ~/.rbksession.$id_string
|
|
||||||
usingsatoken=1
|
|
||||||
trap ctrl_c INT
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# HTTP GET: Given $ENDPOINT write output to file
|
# HTTP GET: Given $ENDPOINT write output to file
|
||||||
rest_api_get () {
|
rest_api_get() {
|
||||||
check_get_token
|
check_get_token
|
||||||
http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X GET $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $AUTH_TOKEN")
|
http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X GET $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $AUTH_TOKEN")
|
||||||
echo "`$DATE` -$$-: REST API GET: ENDPOINT $ENDPOINT" >> $LOGFILE
|
echo "`$DATE` -$$-: REST API GET: ENDPOINT $ENDPOINT" >> $LOGFILE
|
||||||
@@ -145,7 +155,7 @@ rest_api_get () {
|
|||||||
check_http_error
|
check_http_error
|
||||||
}
|
}
|
||||||
|
|
||||||
rest_api_get_2 () {
|
rest_api_get_2() {
|
||||||
check_get_token
|
check_get_token
|
||||||
http_response=$(curl -s -k -o /tmp/rbkresponse2.$$ -w "%{http_code}" -X GET $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $AUTH_TOKEN")
|
http_response=$(curl -s -k -o /tmp/rbkresponse2.$$ -w "%{http_code}" -X GET $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $AUTH_TOKEN")
|
||||||
echo "`$DATE` -$$-: REST API GET: ENDPOINT $ENDPOINT" >> $LOGFILE
|
echo "`$DATE` -$$-: REST API GET: ENDPOINT $ENDPOINT" >> $LOGFILE
|
||||||
@@ -157,7 +167,7 @@ rest_api_get_2 () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# HTTP POST: Given $ENDPOINT and $PAYLOAD write output to file
|
# HTTP POST: Given $ENDPOINT and $PAYLOAD write output to file
|
||||||
rest_api_post () {
|
rest_api_post() {
|
||||||
check_get_token
|
check_get_token
|
||||||
http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X POST $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $AUTH_TOKEN" -H "Content-Type: application/json" -d $PAYLOAD)
|
http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X POST $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $AUTH_TOKEN" -H "Content-Type: application/json" -d $PAYLOAD)
|
||||||
echo "`$DATE` -$$-: REST API POST: ENDPOINT $ENDPOINT" >> $LOGFILE
|
echo "`$DATE` -$$-: REST API POST: ENDPOINT $ENDPOINT" >> $LOGFILE
|
||||||
@@ -169,7 +179,7 @@ rest_api_post () {
|
|||||||
check_http_error
|
check_http_error
|
||||||
}
|
}
|
||||||
|
|
||||||
rest_api_post_empty () {
|
rest_api_post_empty() {
|
||||||
check_get_token
|
check_get_token
|
||||||
http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X POST $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $AUTH_TOKEN" -H "Content-Type: application/json")
|
http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X POST $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $AUTH_TOKEN" -H "Content-Type: application/json")
|
||||||
echo "`$DATE` -$$-: REST API POST: ENDPOINT $ENDPOINT" >> $LOGFILE
|
echo "`$DATE` -$$-: REST API POST: ENDPOINT $ENDPOINT" >> $LOGFILE
|
||||||
@@ -181,7 +191,7 @@ rest_api_post_empty () {
|
|||||||
check_http_error
|
check_http_error
|
||||||
}
|
}
|
||||||
|
|
||||||
rest_api_patch () {
|
rest_api_patch() {
|
||||||
check_get_token
|
check_get_token
|
||||||
http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X PATCH $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $AUTH_TOKEN" -H "Content-Type: application/json" -d "$PAYLOAD")
|
http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X PATCH $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $AUTH_TOKEN" -H "Content-Type: application/json" -d "$PAYLOAD")
|
||||||
echo "`$DATE` -$$-: REST API PATCH: ENDPOINT $ENDPOINT" >> $LOGFILE
|
echo "`$DATE` -$$-: REST API PATCH: ENDPOINT $ENDPOINT" >> $LOGFILE
|
||||||
@@ -193,80 +203,90 @@ rest_api_patch () {
|
|||||||
check_http_error
|
check_http_error
|
||||||
}
|
}
|
||||||
|
|
||||||
rest_api_delete () {
|
rest_api_delete() {
|
||||||
check_get_token
|
check_get_token
|
||||||
http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X DELETE $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $AUTH_TOKEN")
|
http_response=$(curl -s -k -o /tmp/rbkresponse.$$ -w "%{http_code}" -X DELETE $ENDPOINT -H "accept: application/json" -H "Authorization: Bearer $AUTH_TOKEN")
|
||||||
echo "`$DATE` -$$-: REST API DELETE: $http_response: ENDPOINT $ENDPOINT" >> $LOGFILE
|
echo "`$DATE` -$$-: REST API DELETE: $http_response: ENDPOINT $ENDPOINT" >> $LOGFILE
|
||||||
check_http_error
|
check_http_error
|
||||||
}
|
}
|
||||||
|
|
||||||
get_mv () {
|
get_mv() {
|
||||||
|
|
||||||
ENDPOINT="https://$RUBRIK_IP/api/internal/managed_volume?name=$mv_name&is_relic=false"
|
ENDPOINT="https://$RUBRIK_IP/api/internal/managed_volume?name=$mv_name&is_relic=false"
|
||||||
rest_api_get
|
rest_api_get
|
||||||
|
|
||||||
mvId=$(grep -Eo '"id"[^,]*' /tmp/rbkresponse.$$ | grep -Eo 'ManagedVolume:::[a-z0-9-]*')
|
mvId=$(awk '{match($0, /ManagedVolume:::[a-z0-9-]*/); if (RSTART > 0) {id=substr($0, RSTART, RLENGTH); sub(/"$/, "", id); print id}}' /tmp/rbkresponse.$$)
|
||||||
numChannels=$(grep -Eo '"numChannels"[^,]*' /tmp/rbkresponse.$$ | cut -d: -f2)
|
numChannels=$(awk '{match($0, /"numChannels":[ ]*[0-9]+/); if (RSTART > 0) {val=substr($0, RSTART, RLENGTH); sub(/.*:[ ]*/, "", val); print val}}' /tmp/rbkresponse.$$)
|
||||||
|
|
||||||
if [[ $mvId == "" ]]; then
|
if [ -z "$mvId" ]; then
|
||||||
echo ERROR: MV with name $mv_name was not found
|
echo ERROR: MV with name $mv_name was not found
|
||||||
exit_with_error
|
exit_with_error
|
||||||
fi
|
fi
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get_data_mv () {
|
get_data_mv() {
|
||||||
|
|
||||||
mv_name=${HOST}_${ORACLE_SID}_data
|
mv_name=${HOST}_${ORACLE_SID}_Data
|
||||||
|
|
||||||
ENDPOINT="https://$RUBRIK_IP/api/internal/managed_volume?name=$mv_name&is_relic=false"
|
ENDPOINT="https://$RUBRIK_IP/api/internal/managed_volume?name=$mv_name&is_relic=false"
|
||||||
rest_api_get
|
rest_api_get
|
||||||
|
|
||||||
mvId=$(grep -Eo '"id"[^,]*' /tmp/rbkresponse.$$ | grep -Eo 'ManagedVolume:::[a-z0-9-]*')
|
mvId=$(awk '{match($0, /ManagedVolume:::[a-z0-9-]*/); if (RSTART > 0) {id=substr($0, RSTART, RLENGTH); sub(/"$/, "", id); print id}}' /tmp/rbkresponse.$$)
|
||||||
numChannels=$(grep -Eo '"numChannels"[^,]*' /tmp/rbkresponse.$$ | cut -d: -f2)
|
numChannels=$(awk '{match($0, /"numChannels":[ ]*[0-9]+/); if (RSTART > 0) {val=substr($0, RSTART, RLENGTH); sub(/.*:[ ]*/, "", val); print val}}' /tmp/rbkresponse.$$)
|
||||||
|
|
||||||
if [[ $mvId == "" ]]; then
|
if [ -z "$mvId" ]; then
|
||||||
echo ERROR: MV with name $mv_name was not found
|
echo ERROR: MV with name $mv_name was not found
|
||||||
exit_with_error
|
exit_with_error
|
||||||
fi
|
fi
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get_log_mv () {
|
get_log_mv() {
|
||||||
|
|
||||||
# Look for a log volume. If not present, return the data volume
|
# Look for a log volume. If not present, return the data volume
|
||||||
|
|
||||||
mv_name=${HOST}_${ORACLE_SID}_log
|
mv_name=${HOST}_${ORACLE_SID}_Log
|
||||||
ENDPOINT="https://$RUBRIK_IP/api/internal/managed_volume?name=$mv_name&is_relic=false"
|
ENDPOINT="https://$RUBRIK_IP/api/internal/managed_volume?name=$mv_name&is_relic=false"
|
||||||
rest_api_get
|
rest_api_get
|
||||||
|
|
||||||
logMvId=$(grep -Eo '"id"[^,]*' /tmp/rbkresponse.$$ | grep -Eo 'ManagedVolume:::[a-z0-9-]*')
|
logMvId=$(awk '{match($0, /ManagedVolume:::[a-z0-9-]*/); if (RSTART > 0) {id=substr($0, RSTART, RLENGTH); sub(/"$/, "", id); print id}}' /tmp/rbkresponse.$$)
|
||||||
|
|
||||||
if [[ $logMvId == "" ]]; then
|
if [ -z "$logMvId" ]; then
|
||||||
echo "INFO: Log volume ($mv_name) not found. Logs will be written to DB volume"
|
echo "INFO: Log volume ($mv_name) not found. Logs will be written to DB volume"
|
||||||
logMvPresent=0
|
logMvPresent=0
|
||||||
mv_name=${HOST}_${ORACLE_SID}_data
|
mv_name=${HOST}_${ORACLE_SID}_Data
|
||||||
|
|
||||||
ENDPOINT="https://$RUBRIK_IP/api/internal/managed_volume?name=$mv_name&is_relic=false"
|
ENDPOINT="https://$RUBRIK_IP/api/internal/managed_volume?name=$mv_name&is_relic=false"
|
||||||
rest_api_get
|
rest_api_get
|
||||||
|
|
||||||
mvId=$(grep -Eo '"id"[^,]*' /tmp/rbkresponse.$$ | grep -Eo 'ManagedVolume:::[a-z0-9-]*')
|
mvId=$(awk '{match($0, /ManagedVolume:::[a-z0-9-]*/); if (RSTART > 0) {id=substr($0, RSTART, RLENGTH); sub(/"$/, "", id); print id}}' /tmp/rbkresponse.$$)
|
||||||
numChannels=$(grep -Eo '"numChannels"[^,]*' /tmp/rbkresponse.$$ | cut -d: -f2)
|
numChannels=$(awk '{match($0, /"numChannels":[ ]*[0-9]+/); if (RSTART > 0) {val=substr($0, RSTART, RLENGTH); sub(/.*:[ ]*/, "", val); print val}}' /tmp/rbkresponse.$$)
|
||||||
|
|
||||||
if [[ $mvId == "" ]]; then
|
if [ -z "$mvId" ]; then
|
||||||
echo ERROR: MV with name $mv_name was not found
|
echo ERROR: MV with name $mv_name was not found
|
||||||
exit_with_error
|
exit_with_error
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
mvId=$(grep -Eo '"id"[^,]*' /tmp/rbkresponse.$$ | grep -Eo 'ManagedVolume:::[a-z0-9-]*')
|
mvId=$(awk '{match($0, /ManagedVolume:::[a-z0-9-]*/); if (RSTART > 0) {id=substr($0, RSTART, RLENGTH); sub(/"$/, "", id); print id}}' /tmp/rbkresponse.$$)
|
||||||
numChannels=$(grep -Eo '"numChannels"[^,]*' /tmp/rbkresponse.$$ | cut -d: -f2)
|
numChannels=$(awk '{match($0, /"numChannels":[ ]*[0-9]+/); if (RSTART > 0) {val=substr($0, RSTART, RLENGTH); sub(/.*:[ ]*/, "", val); print val}}' /tmp/rbkresponse.$$)
|
||||||
logMvPresent=1
|
logMvPresent=1
|
||||||
echo "INFO: Log volume ($mv_name) exists with $numChannels channels"
|
echo "INFO: Log volume ($mv_name) exists with $numChannels channels"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
open_mv () {
|
set_oracle_env() {
|
||||||
|
ORACLE_HOME=$(awk -F: '$1 == "'$1'" {print $2}' /etc/oratab)
|
||||||
|
PATH=$PATH:$ORACLE_HOME/bin
|
||||||
|
ORACLE_SID=$1
|
||||||
|
if [ -z "$ORACLE_HOME" ]; then
|
||||||
|
echo "ERROR: SID $1 not found in /etc/oratab"
|
||||||
|
exit_with_error
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
open_mv() {
|
||||||
|
|
||||||
PIDFILE=/tmp/mvLock_${mv_name}.pid
|
PIDFILE=/tmp/mvLock_${mv_name}.pid
|
||||||
check_pid
|
check_pid
|
||||||
@@ -276,7 +296,7 @@ open_mv () {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
close_mv () {
|
close_mv() {
|
||||||
|
|
||||||
if [ -z "${SLANAME}" ]; then
|
if [ -z "${SLANAME}" ]; then
|
||||||
echo Closing MV $mv_name using default assigned SLA
|
echo Closing MV $mv_name using default assigned SLA
|
||||||
@@ -292,13 +312,10 @@ close_mv () {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup () {
|
cleanup() {
|
||||||
# if [ $usingsatoken ]; then
|
ENDPOINT="https://$RUBRIK_IP/api/v1/session/me"
|
||||||
# ENDPOINT="https://$RUBRIK_IP/api/v1/session/me"
|
rest_api_delete
|
||||||
# rest_api_delete
|
echo "`$DATE` -$$-: EXITED $0 $@" >> $LOGFILE
|
||||||
# fi
|
|
||||||
echo "`$DATE` -$$-: EXITED $0 $@" >> $LOGFILE
|
|
||||||
rm -f /tmp/mountedDBs.$$
|
|
||||||
rm -f /tmp/rbkresponse.$$
|
rm -f /tmp/rbkresponse.$$
|
||||||
rm -f $PIDFILE
|
rm -f $PIDFILE
|
||||||
}
|
}
|
||||||
@@ -1,48 +1,56 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/ksh
|
||||||
#
|
#
|
||||||
# RMAN DB backup with incremental Merge
|
# RMAN DB backup with incremental Merge
|
||||||
# Written for HCL / Nokia
|
# Written for HCL / Nokia
|
||||||
# v1.0 - James Pattinson - October 2025
|
# v1.0 - James Pattinson - November 2025
|
||||||
#
|
#
|
||||||
# usage: rman_db.sh <ORACLE_SID>
|
# usage: rman_db.ksh <ORACLE_SID>
|
||||||
|
|
||||||
MYDIR="$(dirname "$(readlink -f "$0")")"
|
_SCRIPT_="$0"
|
||||||
|
|
||||||
export ORACLE_SID=$1
|
get_script_dir() {
|
||||||
|
script="$1"
|
||||||
|
case "$script" in
|
||||||
|
/*) abs_path="$script" ;;
|
||||||
|
*) abs_path="$PWD/$script" ;;
|
||||||
|
esac
|
||||||
|
while [ -L "$abs_path" ]; do
|
||||||
|
link=$(readlink "$abs_path")
|
||||||
|
case "$link" in
|
||||||
|
/*) abs_path="$link" ;;
|
||||||
|
*) abs_path="$(dirname "$abs_path")/$link" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
script_dir=$(dirname "$abs_path")
|
||||||
|
cd "$script_dir" 2>/dev/null && pwd
|
||||||
|
}
|
||||||
|
|
||||||
. $HOME/.profile
|
MYDIR=$(get_script_dir "$_SCRIPT_")
|
||||||
|
|
||||||
export ORAENV_ASK=NO
|
. $MYDIR/rubrik.conf
|
||||||
export ORACLE_SID=$1
|
. $MYDIR/oracle_funcs.ksh
|
||||||
|
|
||||||
. oraenv
|
set_oracle_env $1
|
||||||
|
|
||||||
export ORAENV_ASK=YES
|
export NLS_DATE_FORMAT='mm-dd-yyyy hh24:mi:ss'
|
||||||
|
export NLS_LANG=AMERICAN_AMERICA.AL32UTF8
|
||||||
|
|
||||||
source $MYDIR/rbk_api.conf
|
usage() {
|
||||||
source $MYDIR/oracle_funcs.sh
|
echo "Usage: $0 <DBNAME>]" 1>&2
|
||||||
|
exit 1
|
||||||
#ORACLE_SID=$1
|
}
|
||||||
|
|
||||||
usage() { echo "Usage: $0 <DBNAME>]" 1>&2; exit 1; }
|
|
||||||
|
|
||||||
if [ -z "${ORACLE_SID}" ]; then
|
if [ -z "${ORACLE_SID}" ]; then
|
||||||
usage
|
usage
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#ORAENV_ASK=NO
|
MOUNTPOINT=$MOUNTPOINT_PREFIX/$ORACLE_SID/data
|
||||||
#. oraenv
|
|
||||||
|
|
||||||
export NLS_DATE_FORMAT='mm-dd-yyyy hh24:mi:ss'
|
|
||||||
export NLS_LANG=AMERICAN_AMERICA.AL32UTF8
|
|
||||||
|
|
||||||
MOUNTPOINT=$MOUNTPOINT_PREFIX$ORACLE_SID
|
|
||||||
|
|
||||||
mkdir -p $RMAN_LOG_DIR/$ORACLE_SID/
|
mkdir -p $RMAN_LOG_DIR/$ORACLE_SID/
|
||||||
RMAN_LOG=$RMAN_LOG_DIR/$ORACLE_SID/rman_${ORACLE_SID}_DB_$(date +%d%m%y).log
|
RMAN_LOG=$RMAN_LOG_DIR/$ORACLE_SID/rman_${ORACLE_SID}_DB_$(date +%d%m%y).log
|
||||||
|
|
||||||
# Disk space check
|
# Disk space check
|
||||||
dusage=$(df -Ph | grep -E "$MOUNTPOINT" | sed s/%//g | awk -v spaceWarn=$MV_SPACE_WARN '{ if($5 >= spaceWarn) print $0;}')
|
dusage=$(df -Pk | grep -E "$MOUNTPOINT" | sed s/%//g | awk -v spaceWarn=$MV_SPACE_WARN '{ if($5 >= spaceWarn) print $0;}')
|
||||||
if [ "$dusage" != "" ]; then
|
if [ "$dusage" != "" ]; then
|
||||||
echo "WARNING: Disk Space Alert - sending email"
|
echo "WARNING: Disk Space Alert - sending email"
|
||||||
echo "$dusage" | mailx -s "WARNING: Rubrik MV Disk Space Alert On $(hostname) at $(date)" $ALERT_EMAILS
|
echo "$dusage" | mailx -s "WARNING: Rubrik MV Disk Space Alert On $(hostname) at $(date)" $ALERT_EMAILS
|
||||||
@@ -53,6 +61,8 @@ fi
|
|||||||
get_data_mv
|
get_data_mv
|
||||||
open_mv
|
open_mv
|
||||||
|
|
||||||
|
echo "DEBUG: numChannels=$numChannels, MOUNTPOINT=$MOUNTPOINT"
|
||||||
|
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
echo ERROR: Unable to open MV, aborting
|
echo ERROR: Unable to open MV, aborting
|
||||||
exit_with_error
|
exit_with_error
|
||||||
@@ -61,22 +71,35 @@ fi
|
|||||||
|
|
||||||
echo Running RMAN with log to $RMAN_LOG
|
echo Running RMAN with log to $RMAN_LOG
|
||||||
|
|
||||||
if [[ $numChannels -eq 1 ]]; then
|
# Default RMAN channels per mount if not set
|
||||||
|
RMAN_CHANNELS_PER_MOUNT=${RMAN_CHANNELS_PER_MOUNT:-1}
|
||||||
|
|
||||||
|
total_channels=$(expr $numChannels \* $RMAN_CHANNELS_PER_MOUNT)
|
||||||
|
|
||||||
|
if [ $total_channels -eq 1 ]; then
|
||||||
allocate="allocate channel 'ch1' device type disk format '$MOUNTPOINT/%U';"
|
allocate="allocate channel 'ch1' device type disk format '$MOUNTPOINT/%U';"
|
||||||
release="release channel ch1;"
|
release="release channel ch1;"
|
||||||
channel0="$MOUNTPOINT"
|
channel0="$MOUNTPOINT"
|
||||||
else
|
else
|
||||||
|
allocate=""
|
||||||
for i in $(seq 0 $(($numChannels - 1))); do
|
release=""
|
||||||
allocate+="allocate channel 'c$i' device type disk format '$MOUNTPOINT/c$i/%U';"
|
i=0
|
||||||
release+="release channel c$i;"
|
while [ $i -lt $numChannels ]; do
|
||||||
|
j=0
|
||||||
|
while [ $j -lt $RMAN_CHANNELS_PER_MOUNT ]; do
|
||||||
|
suffix=$(echo $j | tr '0123456789' 'abcdefghijklmnopqrstuvwxyz')
|
||||||
|
allocate="$allocate allocate channel 'c${i}${suffix}' device type disk format '$MOUNTPOINT/c$i/%U';"
|
||||||
|
release="$release release channel c${i}${suffix};"
|
||||||
|
j=$(expr $j + 1)
|
||||||
|
done
|
||||||
|
i=$(expr $i + 1)
|
||||||
done
|
done
|
||||||
channel0="$MOUNTPOINT/c0"
|
channel0="$MOUNTPOINT/c0"
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
# Save the current time (minus one hour) to ensure we catch all archive logs
|
# Save the current time (minus one hour) to ensure we catch all archive logs
|
||||||
startTime=$(date +%m-%d-%Y\ %H:%M:%S -d '-1 hour')
|
startTime=$(perl -e 'use POSIX qw(strftime); $time = time() - 3600; print strftime("%m-%d-%Y %H:%M:%S", localtime($time))')
|
||||||
|
|
||||||
# RMAN Part Here
|
# RMAN Part Here
|
||||||
###############################################################################
|
###############################################################################
|
||||||
@@ -84,10 +107,12 @@ startTime=$(date +%m-%d-%Y\ %H:%M:%S -d '-1 hour')
|
|||||||
|
|
||||||
# Now perform the backup and merge
|
# Now perform the backup and merge
|
||||||
rman nocatalog log $RMAN_LOG append > /dev/null <<EOF
|
rman nocatalog log $RMAN_LOG append > /dev/null <<EOF
|
||||||
|
#cat <<EOF
|
||||||
connect target /
|
connect target /
|
||||||
set echo on;
|
set echo on;
|
||||||
configure retention policy to recovery window of 1 days;
|
configure retention policy to recovery window of 1 days;
|
||||||
run {
|
run {
|
||||||
|
CONFIGURE BACKUP OPTIMIZATION OFF;
|
||||||
set controlfile autobackup format for device type disk to '$channel0/cf_%F';
|
set controlfile autobackup format for device type disk to '$channel0/cf_%F';
|
||||||
$allocate
|
$allocate
|
||||||
backup incremental level 1 for recover of copy with tag 'rubrik_snap' database;
|
backup incremental level 1 for recover of copy with tag 'rubrik_snap' database;
|
||||||
@@ -100,7 +125,7 @@ allocate channel for maintenance device type disk;
|
|||||||
crosscheck backup;
|
crosscheck backup;
|
||||||
crosscheck copy;
|
crosscheck copy;
|
||||||
delete noprompt obsolete device type disk;
|
delete noprompt obsolete device type disk;
|
||||||
delete noprompt backup of archivelog all completed before 'sysdate-3' tag rubrik_snap_logs;
|
delete noprompt backup of archivelog all completed before 'sysdate-2' tag rubrik_snap_logs;
|
||||||
release channel;
|
release channel;
|
||||||
EOF
|
EOF
|
||||||
###############################################################################
|
###############################################################################
|
||||||
@@ -116,6 +141,6 @@ elif [ $EMAIL_SUCCESS -eq 1 ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Change permission of backup files to enable alternate host restore
|
# Change permission of backup files to enable alternate host restore
|
||||||
find $MOUNTPOINT -type f -exec chmod 644 -- {} + 2>/dev/null
|
find $MOUNTPOINT -type f -exec chmod 644 {} \; 2>/dev/null
|
||||||
|
|
||||||
close_mv
|
close_mv
|
||||||
@@ -1,59 +1,69 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/ksh
|
||||||
#
|
#
|
||||||
# RMAN Log backup
|
# RMAN Log backup
|
||||||
# Written for HCL / Nokia
|
# Written for HCL / Nokia
|
||||||
# v1.1 - James Pattinson - October 2025
|
# v1.1 - James Pattinson - November 2025
|
||||||
#
|
#
|
||||||
# usage: rman_logs.sh <ORACLE_SID>
|
# usage: rman_logs.ksh <ORACLE_SID>
|
||||||
|
|
||||||
MYDIR="$(dirname "$(readlink -f "$0")")"
|
_SCRIPT_="$0"
|
||||||
export ORACLE_SID=$1
|
|
||||||
|
|
||||||
. $HOME/.profile
|
get_script_dir() {
|
||||||
|
script="$1"
|
||||||
|
case "$script" in
|
||||||
|
/*) abs_path="$script" ;;
|
||||||
|
*) abs_path="$PWD/$script" ;;
|
||||||
|
esac
|
||||||
|
while [ -L "$abs_path" ]; do
|
||||||
|
link=$(readlink "$abs_path")
|
||||||
|
case "$link" in
|
||||||
|
/*) abs_path="$link" ;;
|
||||||
|
*) abs_path="$(dirname "$abs_path")/$link" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
script_dir=$(dirname "$abs_path")
|
||||||
|
cd "$script_dir" 2>/dev/null && pwd
|
||||||
|
}
|
||||||
|
|
||||||
export ORAENV_ASK=NO
|
MYDIR=$(get_script_dir "$_SCRIPT_")
|
||||||
export ORACLE_SID=$1
|
|
||||||
|
|
||||||
. oraenv
|
. $MYDIR/rubrik.conf
|
||||||
|
. $MYDIR/oracle_funcs.ksh
|
||||||
|
|
||||||
export ORAENV_ASK=YES
|
set_oracle_env $1
|
||||||
|
|
||||||
source $MYDIR/rbk_api.conf
|
export NLS_DATE_FORMAT='mm-dd-yyyy hh24:mi:ss'
|
||||||
source $MYDIR/oracle_funcs.sh
|
export NLS_LANG=AMERICAN_AMERICA.AL32UTF8
|
||||||
|
|
||||||
#ORACLE_SID=$1
|
usage() {
|
||||||
|
echo "Usage: $0 <DBNAME>]" 1>&2
|
||||||
usage() { echo "Usage: $0 <DBNAME>]" 1>&2; exit 1; }
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
if [ -z "${ORACLE_SID}" ]; then
|
if [ -z "${ORACLE_SID}" ]; then
|
||||||
usage
|
usage
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#ORAENV_ASK=NO
|
|
||||||
#. oraenv
|
|
||||||
|
|
||||||
export NLS_DATE_FORMAT='mm-dd-yyyy hh24:mi:ss'
|
|
||||||
export NLS_LANG=AMERICAN_AMERICA.AL32UTF8
|
|
||||||
|
|
||||||
mkdir -p $RMAN_LOG_DIR/$ORACLE_SID/
|
mkdir -p $RMAN_LOG_DIR/$ORACLE_SID/
|
||||||
RMAN_LOG=$RMAN_LOG_DIR/$ORACLE_SID/rman_${ORACLE_SID}_LOG_$(date +%d%m%y).log
|
RMAN_LOG=$RMAN_LOG_DIR/$ORACLE_SID/rman_${ORACLE_SID}_LOG_$(date +%d%m%y).log
|
||||||
|
|
||||||
get_log_mv
|
get_log_mv
|
||||||
open_mv
|
open_mv
|
||||||
|
|
||||||
|
if [ -z "$numChannels" ]; then
|
||||||
|
echo "WARNING: numChannels not found, setting to 1"
|
||||||
|
numChannels=1
|
||||||
|
fi
|
||||||
|
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
echo ERROR: Unable to open MV, aborting
|
echo ERROR: Unable to open MV, aborting
|
||||||
exit_with_error
|
exit_with_error
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ $logMvPresent -eq 1 ]] && [[ $numChannels -eq 1 ]] ; then
|
MOUNTPOINT=$MOUNTPOINT_PREFIX/$ORACLE_SID/log
|
||||||
MOUNTPOINT=$MOUNTPOINT_PREFIX${ORACLE_SID}_log
|
|
||||||
else
|
|
||||||
MOUNTPOINT=$MOUNTPOINT_PREFIX$ORACLE_SID
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Disk space check
|
# Disk space check
|
||||||
dusage=$(df -Ph | grep -E "$MOUNTPOINT" | sed s/%//g | awk -v spaceWarn=$MV_SPACE_WARN '{ if($5 >= spaceWarn) print $0;}')
|
dusage=$(df -Pk | grep -E "$MOUNTPOINT" | sed s/%//g | awk -v spaceWarn=$MV_SPACE_WARN '{ if($5 >= spaceWarn) print $0;}')
|
||||||
if [ "$dusage" != "" ]; then
|
if [ "$dusage" != "" ]; then
|
||||||
echo "WARNING: Disk Space Alert - sending email"
|
echo "WARNING: Disk Space Alert - sending email"
|
||||||
echo "$dusage" | mailx -s "WARNING: Rubrik MV Disk Space Alert On $(hostname) at $(date)" $ALERT_EMAILS
|
echo "$dusage" | mailx -s "WARNING: Rubrik MV Disk Space Alert On $(hostname) at $(date)" $ALERT_EMAILS
|
||||||
@@ -63,20 +73,33 @@ fi
|
|||||||
|
|
||||||
echo Running RMAN with log to $RMAN_LOG
|
echo Running RMAN with log to $RMAN_LOG
|
||||||
|
|
||||||
if [[ $numChannels -eq 1 ]]; then
|
# Default RMAN channels per mount if not set
|
||||||
|
RMAN_CHANNELS_PER_MOUNT=${RMAN_CHANNELS_PER_MOUNT:-1}
|
||||||
|
|
||||||
|
total_channels=$(expr $numChannels \* $RMAN_CHANNELS_PER_MOUNT)
|
||||||
|
|
||||||
|
if [ $total_channels -eq 1 ]; then
|
||||||
allocate="allocate channel 'ch1' device type disk format '$MOUNTPOINT/%U';"
|
allocate="allocate channel 'ch1' device type disk format '$MOUNTPOINT/%U';"
|
||||||
release="release channel ch1;"
|
release="release channel ch1;"
|
||||||
channel0="$MOUNTPOINT"
|
channel0="$MOUNTPOINT"
|
||||||
else
|
else
|
||||||
|
allocate=""
|
||||||
for i in $(seq 0 $(($numChannels - 1))); do
|
release=""
|
||||||
allocate+="allocate channel 'c$i' device type disk format '$MOUNTPOINT/log_c$i/%U';"
|
i=0
|
||||||
release+="release channel c$i;"
|
while [ $i -lt $numChannels ]; do
|
||||||
|
j=0
|
||||||
|
while [ $j -lt $RMAN_CHANNELS_PER_MOUNT ]; do
|
||||||
|
suffix=$(echo $j | tr '0123456789' 'abcdefghijklmnopqrstuvwxyz')
|
||||||
|
allocate="$allocate allocate channel 'c${i}${suffix}' device type disk format '$MOUNTPOINT/c$i/%U';"
|
||||||
|
release="$release release channel c${i}${suffix};"
|
||||||
|
j=$(expr $j + 1)
|
||||||
|
done
|
||||||
|
i=$(expr $i + 1)
|
||||||
done
|
done
|
||||||
channel0="$MOUNTPOINT/log_c0"
|
channel0="$MOUNTPOINT/c0"
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
# RMAN Part Here
|
# RMAN Part Here
|
||||||
###############################################################################
|
###############################################################################
|
||||||
rman nocatalog log $RMAN_LOG append > /dev/null <<EOF
|
rman nocatalog log $RMAN_LOG append > /dev/null <<EOF
|
||||||
@@ -85,13 +108,14 @@ set echo on;
|
|||||||
show all;
|
show all;
|
||||||
crosscheck backup;
|
crosscheck backup;
|
||||||
run {
|
run {
|
||||||
|
CONFIGURE BACKUP OPTIMIZATION OFF;
|
||||||
set controlfile autobackup format for device type disk to '$channel0/cf_%F';
|
set controlfile autobackup format for device type disk to '$channel0/cf_%F';
|
||||||
$allocate
|
$allocate
|
||||||
backup archivelog all not backed up 1 times tag 'RUBRIK_LOGS';
|
backup archivelog all not backed up 1 times tag 'rubrik_pit_logs';
|
||||||
$release
|
$release
|
||||||
}
|
}
|
||||||
allocate channel for maintenance device type disk;
|
allocate channel for maintenance device type disk;
|
||||||
delete noprompt backup of archivelog all completed before 'sysdate-3' tag RUBRIK_LOGS;
|
delete noprompt backup of archivelog all completed before 'sysdate-2' tag rubrik_pit_logs;
|
||||||
release channel;
|
release channel;
|
||||||
EOF
|
EOF
|
||||||
###############################################################################
|
###############################################################################
|
||||||
@@ -107,11 +131,12 @@ elif [ $EMAIL_SUCCESS -eq 1 ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Change permission of backup files to enable alternate host restore
|
# Change permission of backup files to enable alternate host restore
|
||||||
find $MOUNTPOINT -type f -exec chmod 644 -- {} + 2>/dev/null
|
find $MOUNTPOINT -type f -exec chmod 644 {} \; 2>/dev/null
|
||||||
|
|
||||||
close_mv
|
close_mv
|
||||||
|
|
||||||
if [[ $HOSTLOGRET -gt 0 ]]; then
|
|
||||||
|
if [ $HOSTLOGRET -gt 0 ]; then
|
||||||
|
|
||||||
echo "Starting post-backup RMAN log purge"
|
echo "Starting post-backup RMAN log purge"
|
||||||
|
|
||||||
@@ -13,6 +13,11 @@ HOSTLOGRET=2
|
|||||||
# Percentage threshold to warn if an MV filesystem is getting full
|
# Percentage threshold to warn if an MV filesystem is getting full
|
||||||
MV_SPACE_WARN=75
|
MV_SPACE_WARN=75
|
||||||
|
|
||||||
|
# Number of RMAN channels to allocate per MV channel
|
||||||
|
# NOTE: This is not a TOTAL. Total number of RMAN channels will be
|
||||||
|
# this multipled by the number of channels of the Managed Volume
|
||||||
|
RMAN_CHANNELS_PER_MOUNT=1
|
||||||
|
|
||||||
# Logging directories
|
# Logging directories
|
||||||
|
|
||||||
# API calls
|
# API calls
|
||||||
@@ -23,4 +28,4 @@ RMAN_LOG_DIR=/tmp/rubrik/rman
|
|||||||
# List of email addresses to send failure alerts to
|
# List of email addresses to send failure alerts to
|
||||||
ALERT_EMAILS=root,oracle
|
ALERT_EMAILS=root,oracle
|
||||||
# Set to 1 to enable email alert on success also
|
# Set to 1 to enable email alert on success also
|
||||||
EMAIL_SUCCESS=1
|
EMAIL_SUCCESS=0
|
||||||
110
rubrik_mv_op.ksh
Executable file
110
rubrik_mv_op.ksh
Executable file
@@ -0,0 +1,110 @@
|
|||||||
|
#!/usr/bin/ksh
|
||||||
|
#
|
||||||
|
# Open and Close MV using API call to CDM
|
||||||
|
# Written for AvonHCL / Nokia
|
||||||
|
# v1.0 - James Pattinson - October 2025
|
||||||
|
#
|
||||||
|
# usage: rubrik_mv_op.ksh -d <DBNAME> -v <logs|data> -o <open|close>
|
||||||
|
#
|
||||||
|
# -d Oracle DBNAME
|
||||||
|
# -v Volume to operate on, logs or data
|
||||||
|
# -o Operation to perform - open or close the MV
|
||||||
|
|
||||||
|
_SCRIPT_="$0"
|
||||||
|
|
||||||
|
get_script_dir() {
|
||||||
|
script="$1"
|
||||||
|
case "$script" in
|
||||||
|
/*) abs_path="$script" ;;
|
||||||
|
*) abs_path="$PWD/$script" ;;
|
||||||
|
esac
|
||||||
|
while [ -L "$abs_path" ]; do
|
||||||
|
link=$(readlink "$abs_path")
|
||||||
|
case "$link" in
|
||||||
|
/*) abs_path="$link" ;;
|
||||||
|
*) abs_path="$(dirname "$abs_path")/$link" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
script_dir=$(dirname "$abs_path")
|
||||||
|
cd "$script_dir" 2>/dev/null && pwd
|
||||||
|
}
|
||||||
|
|
||||||
|
MYDIR=$(get_script_dir "$_SCRIPT_")
|
||||||
|
. $MYDIR/rubrik.conf
|
||||||
|
. $MYDIR/oracle_funcs.ksh
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "Usage: $0 -d <DBNAME> -v <logs|data> -o <open|close>"
|
||||||
|
echo " $0 -n <MV_NAME> -o <open|close>"
|
||||||
|
echo " -d Oracle DBNAME"
|
||||||
|
echo " -v Volume to operate on, logs or data"
|
||||||
|
echo " -o Operation to perform - open or close the MV"
|
||||||
|
echo " -n Specify MV name directly (use only with -o)"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
force=0
|
||||||
|
MVNAME=""
|
||||||
|
|
||||||
|
while getopts "d:v:o:n:" o; do
|
||||||
|
case "${o}" in
|
||||||
|
d)
|
||||||
|
DBNAME=${OPTARG}
|
||||||
|
;;
|
||||||
|
v)
|
||||||
|
VOLUME=${OPTARG}
|
||||||
|
;;
|
||||||
|
o)
|
||||||
|
OPCODE=${OPTARG}
|
||||||
|
;;
|
||||||
|
n)
|
||||||
|
MVNAME=${OPTARG}
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
shift $((OPTIND-1))
|
||||||
|
|
||||||
|
# Validate options
|
||||||
|
if [ -n "$MVNAME" ]; then
|
||||||
|
# Direct MV name mode: require -n and -o only
|
||||||
|
if [ -z "$OPCODE" ]; then
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
mv_name="$MVNAME"
|
||||||
|
elif [ -n "$DBNAME" ] && [ -n "$VOLUME" ] && [ -n "$OPCODE" ]; then
|
||||||
|
# Standard mode: require -d, -v, -o
|
||||||
|
mv_name=$(get_short_hostname)_${DBNAME}_${VOLUME}
|
||||||
|
else
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
# Script starts here
|
||||||
|
|
||||||
|
get_short_hostname() {
|
||||||
|
# Check OS type first - HP-UX hostname doesn't support -s
|
||||||
|
os_type=$(uname -s)
|
||||||
|
if [ "$os_type" = "HP-UX" ]; then
|
||||||
|
hostname | awk -F. '{print $1}'
|
||||||
|
else
|
||||||
|
# Try -s flag on other systems
|
||||||
|
if hostname -s >/dev/null 2>&1; then
|
||||||
|
hostname -s
|
||||||
|
else
|
||||||
|
hostname | awk -F. '{print $1}'
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
get_mv
|
||||||
|
|
||||||
|
case $OPCODE in
|
||||||
|
open) open_mv ;;
|
||||||
|
close) close_mv ;;
|
||||||
|
*) echo "ERROR: Invalid opcode. Specify open or close" ; exit_with_error
|
||||||
|
esac
|
||||||
|
|
||||||
|
cleanup
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
#
|
|
||||||
# Open and Close MV using API call to CDM
|
|
||||||
# Written for AvonHCL / Nokia
|
|
||||||
# v1.0 - James Pattinson - October 2025
|
|
||||||
#
|
|
||||||
# usage: rubrik_mv_op.sh -d <DBNAME> -v <logs|data> -o <open|close>
|
|
||||||
#
|
|
||||||
# -d Oracle DBNAME
|
|
||||||
# -v Volume to operate on, logs or data
|
|
||||||
# -o Operation to perform - open or close the MV
|
|
||||||
|
|
||||||
MYDIR="$(dirname "$(readlink -f "$0")")"
|
|
||||||
source $MYDIR/rbk_api.conf
|
|
||||||
source $MYDIR/oracle_funcs.sh
|
|
||||||
|
|
||||||
usage() { echo "Usage: $0 -d <DBNAME> -v <logs|data> -o <open|close>" 1>&2; exit 1; }
|
|
||||||
|
|
||||||
force=0
|
|
||||||
|
|
||||||
while getopts "d:v:o:" o; do
|
|
||||||
case "${o}" in
|
|
||||||
d)
|
|
||||||
DBNAME=${OPTARG}
|
|
||||||
;;
|
|
||||||
v)
|
|
||||||
VOLUME=${OPTARG}
|
|
||||||
;;
|
|
||||||
o)
|
|
||||||
OPCODE=${OPTARG}
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
usage
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
shift $((OPTIND-1))
|
|
||||||
|
|
||||||
if [ -z "${DBNAME}" ] || [ -z "${VOLUME}" ] || [ -z "${OPCODE}" ]; then
|
|
||||||
usage
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Script starts here
|
|
||||||
|
|
||||||
mv_name=$(hostname -s)_${DBNAME}_${VOLUME}
|
|
||||||
get_mv
|
|
||||||
|
|
||||||
case $OPCODE in
|
|
||||||
open) open_mv ;;
|
|
||||||
close) close_mv ;;
|
|
||||||
*) echo "ERROR: Invalid opcode. Specify open or close" ; exit_with_error
|
|
||||||
esac
|
|
||||||
|
|
||||||
cleanup
|
|
||||||
50
test.ksh
Executable file
50
test.ksh
Executable file
@@ -0,0 +1,50 @@
|
|||||||
|
#!/usr/bin/ksh
|
||||||
|
echo "Testing HP-UX compatibility for Rubrik scripts..."
|
||||||
|
|
||||||
|
# Check for required commands
|
||||||
|
for cmd in ksh awk readlink egrep date dfsdf expr mkdir; do
|
||||||
|
if ! command -v $cmd >/dev/null 2>&1; then
|
||||||
|
echo "ERROR: $cmd not found in PATH"
|
||||||
|
else
|
||||||
|
echo "OK: $cmd found"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Test awk JSON extraction for numChannels
|
||||||
|
echo '{"numChannels": 4, "foo": "bar"}' > /tmp/testjson.$$
|
||||||
|
numChannels=$(awk '{match($0, /"numChannels":[ ]*[0-9]+/); if (RSTART > 0) {val=substr($0, RSTART, RLENGTH); sub(/.*:[ ]*/, "", val); print val}}' /tmp/testjson.$$)
|
||||||
|
if [ "$numChannels" = "4" ]; then
|
||||||
|
echo "OK: awk numChannels extraction works"
|
||||||
|
else
|
||||||
|
echo "ERROR: awk numChannels extraction failed (got '$numChannels')"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Test awk JSON extraction for ManagedVolume
|
||||||
|
echo '{"id":"ManagedVolume:::abc-123-xyz"}' > /tmp/testjson.$$
|
||||||
|
mvId=$(awk '{match($0, /ManagedVolume:::[a-z0-9-]*/); if (RSTART > 0) {id=substr($0, RSTART, RLENGTH); sub(/"$/, "", id); print id}}' /tmp/testjson.$$)
|
||||||
|
if [ "$mvId" = "ManagedVolume:::abc-123-xyz" ]; then
|
||||||
|
echo "OK: awk ManagedVolume extraction works"
|
||||||
|
else
|
||||||
|
echo "ERROR: awk ManagedVolume extraction failed (got '$mvId')"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Test readlink
|
||||||
|
ln -s /tmp/testjson.$$ /tmp/testlink.$$
|
||||||
|
linkres=$(readlink /tmp/testlink.$$ 2>/dev/null)
|
||||||
|
if [ "$linkres" = "/tmp/testjson.$$" ]; then
|
||||||
|
echo "OK: readlink works"
|
||||||
|
else
|
||||||
|
echo "WARNING: readlink did not return expected result (got '$linkres')"
|
||||||
|
fi
|
||||||
|
rm -f /tmp/testjson.$$ /tmp/testlink.$$
|
||||||
|
|
||||||
|
# Test expr arithmetic
|
||||||
|
i=0
|
||||||
|
i=$(expr $i + 1)
|
||||||
|
if [ "$i" = "1" ]; then
|
||||||
|
echo "OK: expr arithmetic works"
|
||||||
|
else
|
||||||
|
echo "ERROR: expr arithmetic failed"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Testing complete."
|
||||||
Reference in New Issue
Block a user