snap shotting和pictbridge是什么 ...

Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.
I'm migrating our jsf project to Spring Webflow + JSF. We use ehcache to store information about chat and users data. Dpwb class(serialized) pulls data from the ehcache. As long the Dpwb class is serialized it should work, why it is looking for serializing ehcache which I can't do anything about it.
&flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd"&
&var name="wbIdentifiers" class="com.emyed.whiteboard.controller.WhiteboardIdentifiers" /&
&view-state id="createWb" view="createdialog.xhtml"&
&transition on="create" to="wboard"&
&evaluate expression="generalCreateWhiteboard.create()"
result="wbIdentifiers" /&
&/transition&
&/view-state&
&view-state id="wboard" view="/WEB-INF/views/D/whiteboard.xhtml"&
&on-render&
&evaluate expression="generalCreateWhiteboard.setDisplayWhiteboard(wbIdentifiers)"
result="viewScope.dpwb "&&/evaluate&
&/on-render&
&/view-state&
org.springframework.web.util.NestedServletException: Reque nested exception is org.springframework.webflow.execution.repository.snapshot.SnapshotCreationException: Could not seri make sure all objects stored in flow or flash scope are serializable
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:948)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
root cause
org.springframework.webflow.execution.repository.snapshot.SnapshotCreationException: Could not seri make sure all objects stored in flow or flash scope are serializable
org.springframework.webflow.execution.repository.snapshot.SerializedFlowExecutionSnapshot.&init&(SerializedFlowExecutionSnapshot.java:75)
org.springframework.webflow.execution.repository.snapshot.SerializedFlowExecutionSnapshotFactory.createSnapshot(SerializedFlowExecutionSnapshotFactory.java:70)
org.springframework.webflow.execution.repository.snapshot.AbstractSnapshottingFlowExecutionRepository.snapshot(AbstractSnapshottingFlowExecutionRepository.java:75)
org.springframework.webflow.execution.repository.impl.DefaultFlowExecutionRepository.putFlowExecution(DefaultFlowExecutionRepository.java:126)
org.springframework.webflow.executor.FlowExecutorImpl.resumeExecution(FlowExecutorImpl.java:171)
org.springframework.webflow.mvc.servlet.FlowHandlerAdapter.handle(FlowHandlerAdapter.java:183)
org.springframework.faces.webflow.JsfFlowHandlerAdapter.handle(JsfFlowHandlerAdapter.java:48)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
root cause
java.io.NotSerializableException: net.sf.ehcache.Cache
java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1164)
java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)
java.util.HashMap.writeObject(HashMap.java:1001)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:945)
java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1469)
java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:422)
org.springframework.webflow.core.collection.LocalAttributeMap.writeObject(LocalAttributeMap.java:327)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:945)
java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1469)
java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)
java.util.HashMap.writeObject(HashMap.java:1001)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:945)
java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1469)
java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:422)
org.springframework.webflow.core.collection.LocalAttributeMap.writeObject(LocalAttributeMap.java:327)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:945)
java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1469)
java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)
org.springframework.webflow.engine.impl.FlowSessionImpl.writeExternal(FlowSessionImpl.java:160)
java.io.ObjectOutputStream.writeExternalData(ObjectOutputStream.java:1429)
java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1398)
java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)
java.util.LinkedList.writeObject(LinkedList.java:943)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:945)
java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1469)
java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)
org.springframework.webflow.engine.impl.FlowExecutionImpl.writeExternal(FlowExecutionImpl.java:309)
java.io.ObjectOutputStream.writeExternalData(ObjectOutputStream.java:1429)
java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1398)
java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)
org.springframework.webflow.execution.repository.snapshot.SerializedFlowExecutionSnapshot.serialize(SerializedFlowExecutionSnapshot.java:173)
org.springframework.webflow.execution.repository.snapshot.SerializedFlowExecutionSnapshot.&init&(SerializedFlowExecutionSnapshot.java:70)
org.springframework.webflow.execution.repository.snapshot.SerializedFlowExecutionSnapshotFactory.createSnapshot(SerializedFlowExecutionSnapshotFactory.java:70)
org.springframework.webflow.execution.repository.snapshot.AbstractSnapshottingFlowExecutionRepository.snapshot(AbstractSnapshottingFlowExecutionRepository.java:75)
org.springframework.webflow.execution.repository.impl.DefaultFlowExecutionRepository.putFlowExecution(DefaultFlowExecutionRepository.java:126)
org.springframework.webflow.executor.FlowExecutorImpl.resumeExecution(FlowExecutorImpl.java:171)
org.springframework.webflow.mvc.servlet.FlowHandlerAdapter.handle(FlowHandlerAdapter.java:183)
org.springframework.faces.webflow.JsfFlowHandlerAdapter.handle(JsfFlowHandlerAdapter.java:48)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
The exception indicates that one of the objects that WebFlow is trying to serialize has an instance variable (or contains another object with instance variable) of type net.sf.ehcache.Cache, which is not serializable. Note that it is not enough just to mark an object as java.io.Serializable, all of its serialized members must also be serializable.
This question describes a test that you can use to check whether something is really serializable (the instance variables must be populated for the test to be meaningful):
From your flow definition, it looks like com.emyed.whiteboard.controller.WhiteboardIdentifiers must be serializable because it is stored in the flow scope.
From what I can see, it doesn't look like the "Dpwb" class needs to be serializable because it is only stored in the view scope, which doesn't require serializability.
1,47411019
Your Answer
Sign up or
Sign up using Google
Sign up using Facebook
Sign up using Stack Exchange
Post as a guest
Post as a guest
By posting your answer, you agree to the
Not the answer you're looking for?
Browse other questions tagged
Stack Overflow works best with JavaScript enabled&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&
&&网站联系: qq: email:&
软件世界网# Author: William Lam
# Created Date: 11/17/2008
# /docs/DOC-8760
##################################################################
# directory that all VM backups should go (e.g. /vmfs/volumes/SAN_LUN1/mybackupdir)
# 砞﹚称???纗??竚???︽?э纗??竚?
VM_BACKUP_VOLUME=/vmfs/volumes/dlgCore-NFS-bigboi.VM-Backups/WILLIAM_BACKUPS
# Format output of VMDK backup
# zeroedthick
# 2gbsparse
# eagerzeroedthick
# ﹚竡称??祑盒?Α?稱?秆祑盒?Α弧?叫把σ?VMware vSphere(ESXi) 店览祑盒?Αざ残?
DISK_BACKUP_FORMAT=thin
# Number of backups for a given VM before deleting
# ﹚竡称?玂痙?计秖
VM_BACKUP_ROTATION_COUNT=3
# Shutdown guestOS prior to running backups and power them back on afterwards
# This feature assumes VMware Tools are installed, else they will not power down and loop forever
# 1=on, 0 =off
# 店览诀POWER OFF?ぃ穦璶―snapshotting
(enable=1,disable=0)
POWER_VM_DOWN_BEFORE_BACKUP=0
# enable shutdown code 1=on, 0 = off
# ﹚竡⊿Τ?杆VMware Tools?店览诀琌????祑盒POWER OFF?币ノ"POWER_VM_DOWN_BEFORE_BACKUP"
ENABLE_HARD_POWER_OFF=0
# if the above flag "ENABLE_HARD_POWER_OFF "is set to 1, then will look at this flag which is the # of iterations
# the script will wait before executing a hard power off, this will be a multiple of 60seconds
# (e.g) = 3, which means this will wait up to 180seconds (3min) before it just powers off the VM
# ?狦币ノ"ENABLE_HARD_POWER_OFF"?﹚竡磅︽眏?闽超?穦?计笲衡?虫?3?3だ牧180?
ITER_TO_WAIT_SHUTDOWN=3
# Number of iterations the script will wait before giving up on powering down the VM and ignoring it for backup
# this will be a multiple of 60 (e.g) = 5, which means this will wait up to 300secs (5min) before it gives up
# 砞﹚POWER DOWN??丁?单?闽超?VM穦?斌┪┛菠疭﹚?VM称??虫?5?5だ牧300?
POWER_DOWN_TIMEOUT=5
# enable compression with gzip+tar 1=on, 0=off
# 称?琌?币ノ溃罽 (enable=1,disable=0)
ENABLE_COMPRESSION=0
############################
####### NEW PARAMS #########
############################
# Include VMs memory when taking snapshot
# 琌?币ノ VM 店览诀?е酚癘拘砰 (enable=1,disable=0)
VM_SNAPSHOT_MEMORY=0
# Quiesce VM when taking snapshot (requires VMware Tools to be installed)
# 琌?币ノ癸氨ゎ? VM 店览诀ㄏノе酚 (惠Τ?杆 VMware Tools)
VM_SNAPSHOT_QUIESCE=0
##########################################################
# NON-PERSISTENT NFS-BACKUP ONLY
# ENABLE NON PERSISTENT NFS BACKUP 1=on, 0=off
# 钡?ㄓ?NFS??闽砞﹚
# ??琌倒ぃ稱琵NFS籔╰参?戳硈钡?砞﹚?す砛??称??筁祘い硈钡?NFS?
?ㄏノ???6?跑计?
#﹚竡獶??┦?NFS称?
ENABLE_NON_PERSISTENT_NFS=0
# umount NFS datastore after backup is complete 1=yes, 0=no
# 琌?璶?更NFS(yes=1,no=0)
UNMOUNT_NFS=0
# IP Address of NFS Server
# NFS Server ???(ip┪?诀?)
NFS_SERVER=172.51.0.192
# Path of exported folder residing on NFS Server (e.g. /some/mount/point )
# NFS ??郎??隔畖
NFS_MOUNT=/upload
# Non-persistent NFS datastore display name of choice
# NFS 戈????よ??嘿
NFS_LOCAL_NAME=backup
# Name of backup directory for VMs residing on the NFS volume
# 店览诀?NFS称??ヘ魁
NFS_VM_BACKUP_DIR=mybackups
############################
######### EMAIL ############
############################
# ??琌MAIL 祇癳LOG?砞﹚
# Email debug 1=yes, 0=no
# 琌?祇癳debug?LOG?硂琌暗?代刚ㄏノ
EMAIL_DEBUG=0
# Email log 1=yes, 0=no
# 琌?璶硓筁筿?秎ンㄓ祇癳称?LOG (yes=1,no=0)
EMAIL_LOG=0
# Email Delay Interval from NC (netcat) - default 1
# 砞﹚–?mailぇ丁祇癳?┑筐?丁?
EMAIL_DELAY_INTERVAL=1
# Email SMTP server
# Email ?SMTP server?ip┪呼?
EMAIL_SERVER=auroa.
# Email SMTP server port
# 砞﹚mail ┮ㄏノ?port
EMAIL_SERVER_PORT=25
# Email FROM
# 盚ン??mail
EMAIL_FROM=root@ghettoVCB
# Email RCPT
# Μン??mail
EMAIL_TO=auroa@
########################## DO NOT MODIFY PAST THIS LINE ##########################
# RSYNC LINK 1=yes, 0 = no
RSYNC_LINK=0
LOG_LEVEL="info"
VMDK_FILES_TO_BACKUP="all"
# default 15min timeout
# 砞﹚单?VMе酚??丁??单?闽超?穦?斌㎝┛菠疭﹚称??VM
SNAPSHOT_TIMEOUT=15
LAST_MODIFIED_DATE=
VERSION_STRING=${LAST_MODIFIED_DATE}_${VERSION}
# Directory naming convention for backup rotations (please ensure there are no spaces!)
VM_BACKUP_DIR_NAMING_CONVENTION="$(date +%F_%H-%M-%S)"
printUsage() {
echo "###############################################################################"
echo "# ghettoVCB for ESX/ESXi 3.5, 4.x+ and 5.0"
echo "# Author: William Lam"
echo "# /"
echo "# Documentation: /docs/DOC-8760"
echo "# Created: 11/17/2008"
echo "# Last modified: ${LAST_MODIFIED_DATE} Version ${VERSION}"
echo "###############################################################################"
echo "Usage: $0 -f [VM_BACKUP_UP_LIST] -c [VM_CONFIG_DIR] -l [LOG_FILE] -d [DEBUG_LEVEL] -g [GLOBAL_CONF] -e [VM_EXCLUSION_LIST]"
echo "OPTIONS:"
Backup all VMs on host"
List of VMs to backup"
VM configuration directory for VM backups"
Path to global ghettoVCB configuration file"
File to output logging"
Debug level [info|debug|dryrun] (default: info)"
echo "(e.g.)"
echo -e "\nBackup VMs stored in a list"
echo -e "\t$0 -f vms_to_backup"
echo -e "\nBackup all VMs residing on this host"
echo -e "\t$0 -a"
echo -e "\nBackup all VMs residing on this host except for the VMs in the exclusion list"
echo -e "\t$0 -a -e vm_exclusion_list"
echo -e "\nBackup VMs based on specific configuration located in directory"
echo -e "\t$0 -f vms_to_backup -c vm_backup_configs"
echo -e "\nBackup VMs using global ghettoVCB configuration file"
echo -e "\t$0 -f vms_to_backup -g /global/ghettoVCB.conf"
echo -e "\nOutput will log to /tmp/ghettoVCB.log (consider logging to local or remote datastore to persist logs)"
echo -e "\t$0 -f vms_to_backup -l /vmfs/volume/local-storage/ghettoVCB.log"
echo -e "\nDry run (no backup will take place)"
echo -e "\t$0 -f vms_to_backup -d dryrun"
logger() {
LOG_TYPE=$1
if [[ "${LOG_LEVEL}" == "debug" ]] && [[ "${LOG_TYPE}" == "debug" ]] || [[ "${LOG_TYPE}" == "info" ]] || [[ "${LOG_TYPE}" == "dryrun" ]]; then
TIME=$(date +%F" "%H:%M:%S)
if [ "${LOG_TO_STDOUT}" -eq 1 ]; then
echo -e "${TIME} -- ${LOG_TYPE}: ${MSG}"
if [ -n "${LOG_OUTPUT}" ]; then
echo -e "${TIME} -- ${LOG_TYPE}: ${MSG}" >> "${LOG_OUTPUT}"
if [ "${EMAIL_LOG}" -eq 1 ]; then
echo -ne "${TIME} -- ${LOG_TYPE}: ${MSG}\r\n" >> "${EMAIL_LOG_OUTPUT}"
sanityCheck() {
NUM_OF_ARGS=$1
if [ "${USE_GLOBAL_CONF}" -eq 1 ]; then
reConfigureGhettoVCBConfiguration "${GLOBAL_CONF}"
#always log to STDOUT, use "> /dev/null" to ignore output
LOG_TO_STDOUT=1
#if no logfile then provide default logfile in /tmp
if [ -z "${LOG_OUTPUT}" ]; then
LOG_OUTPUT="/tmp/ghettoVCB-$(date +%F_%H-%M-%S).log"
echo "Logging output to \"${LOG_OUTPUT}\" ..."
touch "${LOG_OUTPUT}"
# REDIRECT is used by the "tail" trick, use REDIRECT=/dev/null to redirect vmkfstool to STDOUT only
REDIRECT=${LOG_OUTPUT}
if [[ ${NUM_OF_ARGS} -lt 1 ]] || [[ ${NUM_OF_ARGS} -gt 12 ]]; then
logger "info" "ERROR: Incorrect number of arguments!"
printUsage
if [[ ! -f "${VM_FILE}" ]] && [[ "${USE_VM_CONF}" -eq 0 ]] && [[ "${BACKUP_ALL_VMS}" -eq 0 ]]; then
logger "info" "ERROR: \"${VM_FILE}\" is not valid VM input file!"
printUsage
if [[ ! -f "${VM_EXCLUSION_FILE}" ]] && [[ "${EXCLUDE_SOME_VMS}" -eq 1 ]]; then
logger "info" "ERROR: \"${VM_EXCLUSION_FILE}\" is not valid VM exclusion input file!"
printUsage
if [[ ! -d "${CONFIG_DIR}" ]] && [[ "${USE_VM_CONF}" -eq 1 ]]; then
logger "info" "ERROR: \"${CONFIG_DIR}\" is not valid directory!"
printUsage
if [[ ! -f "${GLOBAL_CONF}" ]] && [[ "${USE_GLOBAL_CONF}" -eq 1 ]]; then
logger "info" "ERROR: \"${GLOBAL_CONF}\" is not valid global configuration file!"
printUsage
if [ -f /usr/bin/vmware-vim-cmd ]; then
VMWARE_CMD=/usr/bin/vmware-vim-cmd
VMKFSTOOLS_CMD=/usr/sbin/vmkfstools
elif [ -f /bin/vim-cmd ]; then
VMWARE_CMD=/bin/vim-cmd
VMKFSTOOLS_CMD=/sbin/vmkfstools
logger "info" "ERROR: Unable to locate *vimsh*! You're not running ESX(i) 3.5+, 4.x+ or 5.0!"
echo "ERROR: Unable to locate *vimsh*! You're not running ESX(i) 3.5+, 4.x+ or 5.0!"
ESX_VERSION=$(vmware -v | awk '{print $3}')
if [[ "${ESX_VERSION}" == "5.0.0" ]] || [[ "${ESX_VERSION}" == "5.1.0" ]]; then
elif [[ "${ESX_VERSION}" == "4.0.0" ]] || [[ "${ESX_VERSION}" == "4.1.0" ]]; then
ESX_VERSION=$(vmware -v | awk '{print $4}')
if [[ "${ESX_VERSION}" == "3.5.0" ]] || [[ "${ESX_VERSION}" == "3i" ]]; then
echo "You're not running ESX(i) 3.5, 4.x, 5.x!"
NEW_VIMCMD_SNAPSHOT="no"
${VMWARE_CMD} vmsvc/snapshot.remove | grep "snapshotId" > /dev/null 2>&1
if [ $? -eq 0 ]; then
NEW_VIMCMD_SNAPSHOT="yes"
if [[ "${EMAIL_LOG}" -eq 1 ]] && [[ -f /usr/bin/nc ]] || [[ -f /bin/nc ]]; then
if [ -f /usr/bin/nc ]; then
NC_BIN=/usr/bin/nc
elif [ -f /bin/nc ]; then
NC_BIN=/bin/nc
EMAIL_LOG=0
if [ ! $(whoami) == "root" ]; then
logger "info" "This script needs to be executed by \"root\"!"
echo "ERROR: This script needs to be executed by \"root\"!"
startTimer() {
START_TIME=$(date)
S_TIME=$(date +%s)
endTimer() {
END_TIME=$(date)
E_TIME=$(date +%s)
DURATION=$(echo $((E_TIME - S_TIME)))
#calculate overall completion time
if [ ${DURATION} -le 60 ]; then
logger "info" "Backup Duration: ${DURATION} Seconds"
logger "info" "Backup Duration: $(awk 'BEGIN{ printf "%.2f\n", '${DURATION}'/60}') Minutes"
captureDefaultConfigurations() {
DEFAULT_VM_BACKUP_VOLUME="${VM_BACKUP_VOLUME}"
DEFAULT_DISK_BACKUP_FORMAT="${DISK_BACKUP_FORMAT}"
DEFAULT_VM_BACKUP_ROTATION_COUNT="${VM_BACKUP_ROTATION_COUNT}"
DEFAULT_POWER_VM_DOWN_BEFORE_BACKUP="${POWER_VM_DOWN_BEFORE_BACKUP}"
DEFAULT_ENABLE_HARD_POWER_OFF="${ENABLE_HARD_POWER_OFF}"
DEFAULT_ITER_TO_WAIT_SHUTDOWN="${ITER_TO_WAIT_SHUTDOWN}"
DEFAULT_POWER_DOWN_TIMEOUT="${POWER_DOWN_TIMEOUT}"
DEFAULT_SNAPSHOT_TIMEOUT="${SNAPSHOT_TIMEOUT}"
DEFAULT_ENABLE_COMPRESSION="${ENABLE_COMPRESSION}"
DEFAULT_VM_SNAPSHOT_MEMORY="${VM_SNAPSHOT_MEMORY}"
DEFAULT_VM_SNAPSHOT_QUIESCE="${VM_SNAPSHOT_QUIESCE}"
DEFAULT_VMDK_FILES_TO_BACKUP="${VMDK_FILES_TO_BACKUP}"
DEFAULT_EMAIL_LOG="${EMAIL_LOG}"
DEFAULT_EMAIL_DEBUG="${EMAIL_DEBUG}"
useDefaultConfigurations() {
VM_BACKUP_VOLUME="${DEFAULT_VM_BACKUP_VOLUME}"
DISK_BACKUP_FORMAT="${DEFAULT_DISK_BACKUP_FORMAT}"
VM_BACKUP_ROTATION_COUNT="${DEFAULT_VM_BACKUP_ROTATION_COUNT}"
POWER_VM_DOWN_BEFORE_BACKUP="${DEFAULT_POWER_VM_DOWN_BEFORE_BACKUP}"
ENABLE_HARD_POWER_OFF="${DEFAULT_ENABLE_HARD_POWER_OFF}"
ITER_TO_WAIT_SHUTDOWN="${DEFAULT_ITER_TO_WAIT_SHUTDOWN}"
POWER_DOWN_TIMEOUT="${DEFAULT_POWER_DOWN_TIMEOUT}"
SNAPSHOT_TIMEOUT="${DEFAULT_SNAPSHOT_TIMEOUT}"
ENABLE_COMPRESSION="${DEFAULT_ENABLE_COMPRESSION}"
VM_SNAPSHOT_MEMORY="${DEFAULT_VM_SNAPSHOT_MEMORY}"
VM_SNAPSHOT_QUIESCE="${DEFAULT_VM_SNAPSHOT_QUIESCE}"
VMDK_FILES_TO_BACKUP="all"
EMAIL_LOG=0
EMAIL_DEBUG=0
reConfigureGhettoVCBConfiguration() {
GLOBAL_CONF=$1
if [ -f "${GLOBAL_CONF}" ]; then
. "${GLOBAL_CONF}"
useDefaultConfigurations
reConfigureBackupParam() {
if [ -e "${CONFIG_DIR}/${VM}" ]; then
logger "info" "CONFIG - USING CONFIGURATION FILE = ${CONFIG_DIR}/${VM}"
. "${CONFIG_DIR}/${VM}"
useDefaultConfigurations
dumpHostInfo() {
VERSION=$(vmware -v)
logger "debug" "HOST VERSION: ${VERSION}"
echo ${VERSION} | grep "Server 3i" > /dev/null 2>&1
if [ $? -eq 1 ]; then
logger "debug" "HOST LEVEL: $(vmware -l)"
logger "debug" "HOSTNAME: $(hostname)\n"
findVMDK() {
VMDK_TO_SEARCH_FOR=$1
#if [ "${USE_VM_CONF}" -eq 1 ]; then
logger "debug" "findVMDK() - Searching for VMDK: \"${VMDK_TO_SEARCH_FOR}\" to backup"
OLD_IFS2="${IFS}"
for k in ${VMDK_FILES_TO_BACKUP}
VMDK_FILE=$(echo $k | sed -e 's/^[[:blank:]]*//;s/[[:blank:]]*$//')
if [ "${VMDK_FILE}" == "${VMDK_TO_SEARCH_FOR}" ]; then
logger "debug" "findVMDK() - Found VMDK! - \"${VMDK_TO_SEARCH_FOR}\" to backup"
isVMDKFound=1
IFS="${OLD_IFS2}"
getVMDKs() {
#get all VMDKs listed in .vmx file
VMDKS_FOUND=$(grep -iE '(scsi|ide)' "${VMX_PATH}" | grep -i fileName | awk -F " " '{print $1}')
TMP_IFS=${IFS}
IFS=${ORIG_IFS}
#loop through each disk and verify that it's currently present and create array of valid VMDKS
for DISK in ${VMDKS_FOUND};
#extract the SCSI ID and use it to check for valid vmdk disk
SCSI_ID=$(echo ${DISK%%.*})
grep -i "${SCSI_ID}.present" "${VMX_PATH}" | grep -i "true" > /dev/null 2>&1
#if valid, then we use the vmdk file
if [ $? -eq 0 ]; then
#verify disk is not independent
grep -i "${SCSI_ID}.mode" "${VMX_PATH}" | grep -i "independent" > /dev/null 2>&1
if [ $? -eq 1 ]; then
grep -i "${SCSI_ID}.deviceType" "${VMX_PATH}" | grep -i "scsi-hardDisk" > /dev/null 2>&1
#if we find the device type is of scsi-disk, then proceed
if [ $? -eq 0 ]; then
DISK=$(grep -i ${SCSI_ID}.fileName "${VMX_PATH}" | awk -F "\"" '{print $2}')
echo "${DISK}" | grep "\/vmfs\/volumes" > /dev/null 2>&1
if [ $? -eq 0 ]; then
DISK_SIZE_IN_SECTORS=$(cat "${DISK}" | grep "VMFS" | grep ".vmdk" | awk '{print $2}')
DISK_SIZE_IN_SECTORS=$(cat "${VMX_DIR}/${DISK}" | grep "VMFS" | grep ".vmdk" | awk '{print $2}')
DISK_SIZE=$(echo "${DISK_SIZE_IN_SECTORS}" | awk '{printf "%.0f\n",$1*512/24}')
VMDKS="${DISK}###${DISK_SIZE}:${VMDKS}"
TOTAL_VM_SIZE=$((TOTAL_VM_SIZE+DISK_SIZE))
#if the deviceType is NULL for IDE which it is, thanks for the inconsistency VMware
#we'll do one more level of verification by checking to see if an ext. of .vmdk exists
#since we can not rely on the deviceType showing "ide-hardDisk"
grep -i ${SCSI_ID}.fileName "${VMX_PATH}" | grep -i ".vmdk" > /dev/null 2>&1
if [ $? -eq 0 ]; then
DISK=$(grep -i ${SCSI_ID}.fileName "${VMX_PATH}" | awk -F "\"" '{print $2}')
echo "${DISK}" | grep "\/vmfs\/volumes" > /dev/null 2>&1
if [ $? -eq 0 ]; then
DISK_SIZE_IN_SECTORS=$(cat "${DISK}" | grep "VMFS" | grep ".vmdk" | awk '{print $2}')
DISK_SIZE_IN_SECTORS=$(cat "${VMX_DIR}/${DISK}" | grep "VMFS" | grep ".vmdk" | awk '{print $2}')
DISK_SIZE=$(echo "${DISK_SIZE_IN_SECTORS}" | awk '{printf "%.0f\n",$1*512/24}')
VMDKS="${DISK}###${DISK_SIZE}:${VMDKS}"
TOTAL_VM_SIZE=$((TOTAL_VM_SIZE_IN+DISK_SIZE))
#independent disks are not affected by snapshots, hence they can not be backed up
DISK=$(grep -i ${SCSI_ID}.fileName "${VMX_PATH}" | awk -F "\"" '{print $2}')
echo "${DISK}" | grep "\/vmfs\/volumes" > /dev/null 2>&1
if [ $? -eq 0 ]; then
DISK_SIZE_IN_SECTORS=$(cat "${DISK}" | grep "VMFS" | grep ".vmdk" | awk '{print $2}')
DISK_SIZE_IN_SECTORS=$(cat "${VMX_DIR}/${DISK}" | grep "VMFS" | grep ".vmdk" | awk '{print $2}')
DISK_SIZE=$(echo "${DISK_SIZE_IN_SECTORS}" | awk '{printf "%.0f\n",$1*512/24}')
INDEP_VMDKS="${DISK}###${DISK_SIZE}:${INDEP_VMDKS}"
IFS=${TMP_IFS}
logger "debug" "getVMDKs() - ${VMDKS}"
dumpVMConfigurations() {
logger "info" "CONFIG - VERSION = ${VERSION_STRING}"
logger "info" "CONFIG - GHETTOVCB_PID = ${GHETTOVCB_PID}"
logger "info" "CONFIG - VM_BACKUP_VOLUME = ${VM_BACKUP_VOLUME}"
if [ "${ENABLE_NON_PERSISTENT_NFS}" -eq 1 ]; then
logger "info" "CONFIG - ENABLE_NON_PERSISTENT_NFS = ${ENABLE_NON_PERSISTENT_NFS}"
logger "info" "CONFIG - UNMOUNT_NFS = ${UNMOUNT_NFS}"
logger "info" "CONFIG - NFS_SERVER = ${NFS_SERVER}"
logger "info" "CONFIG - NFS_MOUNT = ${NFS_MOUNT}"
logger "info" "CONFIG - VM_BACKUP_ROTATION_COUNT = ${VM_BACKUP_ROTATION_COUNT}"
logger "info" "CONFIG - VM_BACKUP_DIR_NAMING_CONVENTION = ${VM_BACKUP_DIR_NAMING_CONVENTION}"
logger "info" "CONFIG - DISK_BACKUP_FORMAT = ${DISK_BACKUP_FORMAT}"
logger "info" "CONFIG - POWER_VM_DOWN_BEFORE_BACKUP = ${POWER_VM_DOWN_BEFORE_BACKUP}"
logger "info" "CONFIG - ENABLE_HARD_POWER_OFF = ${ENABLE_HARD_POWER_OFF}"
logger "info" "CONFIG - ITER_TO_WAIT_SHUTDOWN = ${ITER_TO_WAIT_SHUTDOWN}"
logger "info" "CONFIG - POWER_DOWN_TIMEOUT = ${POWER_DOWN_TIMEOUT}"
logger "info" "CONFIG - SNAPSHOT_TIMEOUT = ${SNAPSHOT_TIMEOUT}"
logger "info" "CONFIG - LOG_LEVEL = ${LOG_LEVEL}"
logger "info" "CONFIG - BACKUP_LOG_OUTPUT = ${LOG_OUTPUT}"
logger "info" "CONFIG - VM_SNAPSHOT_MEMORY = ${VM_SNAPSHOT_MEMORY}"
logger "info" "CONFIG - VM_SNAPSHOT_QUIESCE = ${VM_SNAPSHOT_QUIESCE}"
logger "info" "CONFIG - VMDK_FILES_TO_BACKUP = ${VMDK_FILES_TO_BACKUP}"
logger "info" "CONFIG - EMAIL_LOG = ${EMAIL_LOG}"
if [ "${EMAIL_LOG}" -eq 1 ]; then
logger "info" "CONFIG - EMAIL_DEBUG = ${EMAIL_DEBUG}"
logger "info" "CONFIG - EMAIL_SERVER = ${EMAIL_SERVER}"
logger "info" "CONFIG - EMAIL_SERVER_PORT = ${EMAIL_SERVER_PORT}"
logger "info" "CONFIG - EMAIL_DELAY_INTERVAL = ${EMAIL_DELAY_INTERVAL}"
logger "info" "CONFIG - EMAIL_FROM = ${EMAIL_FROM}"
logger "info" "CONFIG - EMAIL_TO = ${EMAIL_TO}"
logger "info" ""
checkVMBackupRotation() {
local BACKUP_DIR_PATH=$1
local VM_TO_SEARCH_FOR=$2
#default rotation if variable is not defined
if [ -z ${VM_BACKUP_ROTATION_COUNT} ]; then
VM_BACKUP_ROTATION_COUNT=1
LIST_BACKUPS=$(ls -t "${BACKUP_DIR_PATH}" | grep "${VM_TO_SEARCH_FOR}-[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}_[0-9]\{2\}-[0-9]\{2\}-[0-9]\{2\}")
BACKUPS_TO_KEEP=$(ls -t "${BACKUP_DIR_PATH}" | grep "${VM_TO_SEARCH_FOR}-[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}_[0-9]\{2\}-[0-9]\{2\}-[0-9]\{2\}" | head -"${VM_BACKUP_ROTATION_COUNT}")
ORIG_IFS=${IFS}
for i in ${LIST_BACKUPS};
for j in ${BACKUPS_TO_KEEP};
if [ $i == $j ]; then
if [ $FOUND -eq 0 ]; then
logger "debug" "Removing $BACKUP_DIR_PATH/$i"
rm -rf "$BACKUP_DIR_PATH/$i"
#NFS I/O error handling hack
if [ $? -ne 0 ]; then
NFS_IO_HACK_COUNTER=0
NFS_IO_HACK_STATUS=0
NFS_IO_HACK_FILECHECK="$BACKUP_DIR_PATH/nfs_io.check"
while [ "${NFS_IO_HACK_STATUS}" -eq 0 -a "${NFS_IO_HACK_COUNTER}" -lt 60 ];
NFS_IO_HACK_COUNTER=$((NFS_IO_HACK_COUNTER+1))
touch "${NFS_IO_HACK_FILECHECK}"
if [ $? -eq 0 ]; then
NFS_IO_HACK_STATUS=1
rm -rf "${NFS_IO_HACK_FILECHECK}"
if [ "${NFS_IO_HACK_STATUS}"
-eq 1 ]; then
logger "info" "Slept ${NFS_IO_HACK_COUNTER} seconds to work around NFS I/O error"
logger "info" "Slept ${NFS_IO_HACK_COUNTER} seconds but failed work around for NFS I/O error"
IFS=${ORIG_IFS}
storageInfo() {
SECTION=$1
#SOURCE DATASTORE
SRC_DATASTORE_CAPACITY=$($VMWARE_CMD hostsvc/datastore/info "${VMFS_VOLUME}" | grep -i "capacity" | awk '{print $3}' | sed 's/,//g')
SRC_DATASTORE_FREE=$($VMWARE_CMD hostsvc/datastore/info "${VMFS_VOLUME}" | grep -i "freespace" | awk '{print $3}' | sed 's/,//g')
SRC_DATASTORE_BLOCKSIZE=$($VMWARE_CMD hostsvc/datastore/info "${VMFS_VOLUME}" | grep -i blockSizeMb | awk '{print $3}' | sed 's/,//g')
if [ -z ${SRC_DATASTORE_BLOCKSIZE} ]; then
SRC_DATASTORE_BLOCKSIZE="NA"
SRC_DATASTORE_MAX_FILE_SIZE="NA"
case ${SRC_DATASTORE_BLOCKSIZE} in
1)SRC_DATASTORE_MAX_FILE_SIZE="256 GB";;
2)SRC_DATASTORE_MAX_FILE_SIZE="512 GB";;
4)SRC_DATASTORE_MAX_FILE_SIZE="1024 GB";;
8)SRC_DATASTORE_MAX_FILE_SIZE="2048 GB";;
SRC_DATASTORE_CAPACITY_GB=$(echo "${SRC_DATASTORE_CAPACITY}" | awk '{printf "%.1f\n",$1/24}')
SRC_DATASTORE_FREE_GB=$(echo "${SRC_DATASTORE_FREE}" | awk '{printf "%.1f\n",$1/24}')
#DESTINATION DATASTORE
DST_VOL_1=$(echo "${VM_BACKUP_VOLUME#/*/*/}")
DST_DATASTORE=$(echo "${DST_VOL_1%%/*}")
DST_DATASTORE_CAPACITY=$($VMWARE_CMD hostsvc/datastore/info "${DST_DATASTORE}" | grep -i "capacity" | awk '{print $3}' | sed 's/,//g')
DST_DATASTORE_FREE=$($VMWARE_CMD hostsvc/datastore/info "${DST_DATASTORE}" | grep -i "freespace" | awk '{print $3}' | sed 's/,//g')
DST_DATASTORE_BLOCKSIZE=$($VMWARE_CMD hostsvc/datastore/info "${DST_DATASTORE}" | grep -i blockSizeMb | awk '{print $3}' | sed 's/,//g')
if [ -z ${DST_DATASTORE_BLOCKSIZE} ]; then
DST_DATASTORE_BLOCKSIZE="NA"
DST_DATASTORE_MAX_FILE_SIZE="NA"
case ${DST_DATASTORE_BLOCKSIZE} in
1)DST_DATASTORE_MAX_FILE_SIZE="256 GB";;
2)DST_DATASTORE_MAX_FILE_SIZE="512 GB";;
4)DST_DATASTORE_MAX_FILE_SIZE="1024 GB";;
8)DST_DATASTORE_MAX_FILE_SIZE="2048 GB";;
DST_DATASTORE_CAPACITY_GB=$(echo "${DST_DATASTORE_CAPACITY}" | awk '{printf "%.1f\n",$1/24}')
DST_DATASTORE_FREE_GB=$(echo "${DST_DATASTORE_FREE}" | awk '{printf "%.1f\n",$1/24}')
logger "debug" "Storage Information ${SECTION} backup: "
logger "debug" "SRC_DATASTORE: ${VMFS_VOLUME}"
logger "debug" "SRC_DATASTORE_CAPACITY: ${SRC_DATASTORE_CAPACITY_GB} GB"
logger "debug" "SRC_DATASTORE_FREE: ${SRC_DATASTORE_FREE_GB} GB"
logger "debug" "SRC_DATASTORE_BLOCKSIZE: ${SRC_DATASTORE_BLOCKSIZE}"
logger "debug" "SRC_DATASTORE_MAX_FILE_SIZE: ${SRC_DATASTORE_MAX_FILE_SIZE}"
logger "debug" ""
logger "debug" "DST_DATASTORE: ${DST_DATASTORE}"
logger "debug" "DST_DATASTORE_CAPACITY: ${DST_DATASTORE_CAPACITY_GB} GB"
logger "debug" "DST_DATASTORE_FREE: ${DST_DATASTORE_FREE_GB} GB"
logger "debug" "DST_DATASTORE_BLOCKSIZE: ${DST_DATASTORE_BLOCKSIZE}"
logger "debug" "DST_DATASTORE_MAX_FILE_SIZE: ${DST_DATASTORE_MAX_FILE_SIZE}"
if [[ "${SRC_DATASTORE_BLOCKSIZE}" != "NA" ]] && [[ "${DST_DATASTORE_BLOCKSIZE}" != "NA" ]]; then
if [ "${SRC_DATASTORE_BLOCKSIZE}" -lt "${DST_DATASTORE_BLOCKSIZE}" ]; then
logger "debug" ""
logger "debug" "SRC VMFS blocksze of ${SRC_DATASTORE_BLOCKSIZE}MB is less than DST VMFS blocksize of ${DST_DATASTORE_BLOCKSIZE}MB which can be an issue for VM snapshots"
logger "debug" ""
ghettoVCB() {
VM_INPUT=$1
VM_FAILED=0
VMDK_FAILED=0
dumpHostInfo
if [ ${ENABLE_NON_PERSISTENT_NFS} -eq 1 ]; then
VM_BACKUP_VOLUME="/vmfs/volumes/${NFS_LOCAL_NAME}/${NFS_VM_BACKUP_DIR}"
if [ "${LOG_LEVEL}" !=
"dryrun" ]; then
#1 = readonly
#0 = readwrite
logger "debug" "Mounting NFS: ${NFS_SERVER}:${NFS_MOUNT} to /vmfs/volume/${NFS_LOCAL_NAME}"
${VMWARE_CMD} hostsvc/datastore/nas_create "${NFS_LOCAL_NAME}" "${NFS_SERVER}" "${NFS_MOUNT}" 0
captureDefaultConfigurations
if [ "${USE_GLOBAL_CONF}" -eq 1 ]; then
logger "info" "CONFIG - USING GLOBAL GHETTOVCB CONFIGURATION FILE = ${GLOBAL_CONF}"
if [ "${USE_VM_CONF}" -eq 0 ]; then
dumpVMConfigurations
#dump out all virtual machines allowing for spaces now
${VMWARE_CMD} vmsvc/getallvms | sed 's/[[:blank:]]\{3,\}/
/g' | awk -F'
' '{print "\""$1"\";\""$2"\";\""$3"\""}' |
sed 's/\] /\]\";\"/g' | sed '1,1d' > /tmp/vms_list
if [ "${BACKUP_ALL_VMS}" -eq 1 ]; then
${VMWARE_CMD} vmsvc/getallvms | sed 's/[[:blank:]]\{3,\}/
/g' | awk -F'
' '{print ""$2""}' | sed '1,1d' | sed '/^$/d' > "${VM_INPUT}"
ORIG_IFS=${IFS}
for VM_NAME in $(cat "${VM_INPUT}" | grep -v "#" | sed '/^$/d' | sed -e 's/^[[:blank:]]*//;s/[[:blank:]]*$//');
IGNORE_VM=0
if [ "${EXCLUDE_SOME_VMS}" -eq 1 ]; then
grep -E "${VM_NAME}" "${VM_EXCLUSION_FILE}" > /dev/null 2>&1
if [ $? -eq 0 ]; then
IGNORE_VM=1
VM_ID=$(grep -E "\"${VM_NAME}\"" /tmp/vms_list | awk -F ";" '{print $1}' | sed 's/"//g')
#ensure default value if one is not selected or variable is null
if [ -z ${VM_BACKUP_DIR_NAMING_CONVENTION} ]; then
VM_BACKUP_DIR_NAMING_CONVENTION="$(date +%F_%k-%M-%S)"
if [[ "${USE_VM_CONF}" -eq 1 ]] && [[ ! -z ${VM_ID} ]]; then
reConfigureBackupParam "${VM_NAME}"
dumpVMConfigurations
VMFS_VOLUME=$(grep -E "\"${VM_NAME}\"" /tmp/vms_list | awk -F ";" '{print $3}' | sed 's/\[//;s/\]//;s/"//g')
VMX_CONF=$(grep -E "\"${VM_NAME}\"" /tmp/vms_list | awk -F ";" '{print $4}' | sed 's/\[//;s/\]//;s/"//g')
VMX_PATH="/vmfs/volumes/${VMFS_VOLUME}/${VMX_CONF}"
VMX_DIR=$(dirname "${VMX_PATH}")
#storage info
if [[ ! -z ${VM_ID} ]] && [[ "${LOG_LEVEL}" != "dryrun" ]]; then
storageInfo "before"
#ignore VM as it's in the exclusion list
if [ "${IGNORE_VM}" -eq 1 ]; then
logger "debug" "Ignoring ${VM_NAME} for backup since its located in exclusion list\n"
#checks to see if we can pull out the VM_ID
elif [ -z ${VM_ID} ]; then
logger "info" "ERROR: failed to locate and extract VM_ID for ${VM_NAME}!\n"
VM_FAILED=1
elif [ "${LOG_LEVEL}" == "dryrun" ]; then
logger "dryrun" "###############################################"
logger "dryrun" "Virtual Machine: $VM_NAME"
logger "dryrun" "VM_ID: $VM_ID"
logger "dryrun" "VMX_PATH: $VMX_PATH"
logger "dryrun" "VMX_DIR: $VMX_DIR"
logger "dryrun" "VMX_CONF: $VMX_CONF"
logger "dryrun" "VMFS_VOLUME: $VMFS_VOLUME"
logger "dryrun" "VMDK(s): "
TOTAL_VM_SIZE=0
OLD_IFS="${IFS}"
for j in ${VMDKS};
J_VMDK=$(echo "${j}" | awk -F "###" '{print $1}')
J_VMDK_SIZE=$(echo "${j}" | awk -F "###" '{print $2}')
logger "dryrun" "\t${J_VMDK}\t${J_VMDK_SIZE} GB"
HAS_INDEPENDENT_DISKS=0
logger "dryrun" "INDEPENDENT VMDK(s): "
for k in ${INDEP_VMDKS};
HAS_INDEPENDENT_DISKS=1
K_VMDK=$(echo "${k}" | awk -F "###" '{print $1}')
K_VMDK_SIZE=$(echo "${k}" | awk -F "###" '{print $2}')
logger "dryrun" "\t${K_VMDK}\t${K_VMDK_SIZE} GB"
IFS="${OLD_IFS}"
INDEP_VMDKS=""
logger "dryrun" "TOTAL_VM_SIZE_TO_BACKUP: ${TOTAL_VM_SIZE} GB"
if [ ${HAS_INDEPENDENT_DISKS} -eq 1 ]; then
logger "dryrun" "Snapshots can not be taken for indepdenent disks!"
logger "dryrun" "THIS VIRTUAL MACHINE WILL NOT HAVE ALL ITS VMDKS BACKED UP!"
ls "${VMX_DIR}" | grep -q "\-delta\.vmdk" > /dev/null 2>&1;
if [ $? -eq 0 ]; then
logger "dryrun" "Snapshots found for this VM, please commit all snapshots before continuing!"
logger "dryrun" "THIS VIRTUAL MACHINE WILL NOT BE BACKED UP DUE TO EXISTING SNAPSHOTS!"
if [ ${TOTAL_VM_SIZE} -eq 0 ]; then
logger "dryrun" "THIS VIRTUAL MACHINE WILL NOT BE BACKED UP DUE TO EMPTY VMDK LIST!"
logger "dryrun" "###############################################\n"
#checks to see if the VM has any snapshots to start with
elif ls "${VMX_DIR}" | grep -q "\-delta\.vmdk" > /dev/null 2>&1; then
logger "info" "Snapshot found for ${VM_NAME}, backup will not take place\n"
VM_FAILED=1
elif [[ -f "${VMX_PATH}" ]] && [[ ! -z "${VMX_PATH}" ]]; then
#nfs case and backup to root path of your NFS mount
if [ ${ENABLE_NON_PERSISTENT_NFS} -eq 1 ] ; then
BACKUP_DIR="/vmfs/volumes/${NFS_LOCAL_NAME}/${NFS_VM_BACKUP_DIR}/${VM_NAME}"
if [[ -z ${VM_NAME} ]] || [[ -z ${NFS_LOCAL_NAME} ]] || [[ -z ${NFS_VM_BACKUP_DIR} ]]; then
logger "info" "ERROR: Variable BACKUP_DIR was not set properly, please ensure all required variables for non-persistent NFS backup option has been defined"
#non-nfs (SAN,LOCAL)
BACKUP_DIR="${VM_BACKUP_VOLUME}/${VM_NAME}"
if [[ -z ${VM_BACKUP_VOLUME} ]]; then
logger "info" "ERROR: Variable VM_BACKUP_VOLUME was not defined"
#initial root VM backup directory
if [ ! -d "${BACKUP_DIR}" ]; then
mkdir -p "${BACKUP_DIR}"
if [ ! -d "${BACKUP_DIR}" ]; then
logger "info" "Unable to create \"${BACKUP_DIR}\"! - Ensure VM_BACKUP_VOLUME was defined correctly"
# directory name of the individual Virtual Machine backup followed by naming convention followed by count
VM_BACKUP_DIR="${BACKUP_DIR}/${VM_NAME}-${VM_BACKUP_DIR_NAMING_CONVENTION}"
# Rsync relative path variable if needed
RSYNC_LINK_DIR="./${VM_NAME}-${VM_BACKUP_DIR_NAMING_CONVENTION}"
mkdir -p "${VM_BACKUP_DIR}"
cp "${VMX_PATH}" "${VM_BACKUP_DIR}"
#new variable to keep track on whether VM has independent disks
VM_HAS_INDEPENDENT_DISKS=0
#extract all valid VMDK(s) from VM
if [ ! -z ${INDEP_VMDKS} ]; then
VM_HAS_INDEPENDENT_DISKS=1
ORGINAL_VM_POWER_STATE=$(${VMWARE_CMD} vmsvc/power.getstate ${VM_ID} | tail -1)
CONTINUE_TO_BACKUP=1
#section that will power down a VM prior to taking a snapshot and backup and power it back on
if [ ${POWER_VM_DOWN_BEFORE_BACKUP} -eq 1 ]; then
START_ITERATION=0
logger "info" "Powering off initiated for ${VM_NAME}, backup will not begin until VM is off..."
${VMWARE_CMD} vmsvc/power.shutdown ${VM_ID} > /dev/null 2>&1
while ${VMWARE_CMD} vmsvc/power.getstate ${VM_ID} | grep -i "Powered on" > /dev/null 2>&1;
#enable hard power off code
if [ ${ENABLE_HARD_POWER_OFF} -eq 1 ]; then
if [ ${START_ITERATION} -ge ${ITER_TO_WAIT_SHUTDOWN} ]; then
logger "info" "Hard power off occured for ${VM_NAME}, waited for $((ITER_TO_WAIT_SHUTDOWN*60)) seconds"
${VMWARE_CMD} vmsvc/power.off ${VM_ID} > /dev/null 2>&1
#this is needed for ESXi, even the hard power off did not take affect right away
logger "info" "VM is still on - Iteration: ${START_ITERATION} - sleeping for 60secs (Duration: $((START_ITERATION*60)) seconds)"
#logic to not backup this VM if unable to shutdown
#after certain timeout period
if [ ${START_ITERATION} -ge ${POWER_DOWN_TIMEOUT} ]; then
logger "info" "Unable to power off ${VM_NAME}, waited for $((POWER_DOWN_TIMEOUT*60)) seconds! Ignoring ${VM_NAME} for backup!"
VM_FAILED=1
CONTINUE_TO_BACKUP=0
START_ITERATION=$((START_ITERATION + 1))
if [ ${CONTINUE_TO_BACKUP} -eq 1 ]; then
logger "info" "VM is powerdOff"
if [ ${CONTINUE_TO_BACKUP} -eq 1 ]; then
logger "info" "Initiate backup for ${VM_NAME}"
startTimer
SNAP_SUCCESS=1
VM_VMDK_FAILED=0
#powered on VMs only
if [[ ! ${POWER_VM_DOWN_BEFORE_BACKUP} -eq 1 ]] && [[ "${ORGINAL_VM_POWER_STATE}" != "Powered off" ]]; then
SNAPSHOT_NAME="ghettoVCB-snapshot-$(date +%F)"
logger "info" "Creating Snapshot \"${SNAPSHOT_NAME}\" for ${VM_NAME}"
${VMWARE_CMD} vmsvc/snapshot.create ${VM_ID} "${SNAPSHOT_NAME}" "${SNAPSHOT_NAME}" "${VM_SNAPSHOT_MEMORY}" "${VM_SNAPSHOT_QUIESCE}" > /dev/null 2>&1
logger "debug" "Waiting for snapshot \"${SNAPSHOT_NAME}\" to be created"
logger "debug" "Snapshot timeout set to: $((SNAPSHOT_TIMEOUT*60)) seconds"
START_ITERATION=0
while [ $(${VMWARE_CMD} vmsvc/snapshot.get ${VM_ID} | wc -l) -eq 1 ]
if [ ${START_ITERATION} -ge ${SNAPSHOT_TIMEOUT} ]; then
logger "info" "Snapshot timed out, failed to create snapshot: \"${SNAPSHOT_NAME}\" for ${VM_NAME}"
SNAP_SUCCESS=0
echo "ERROR: Unable to backup ${VM_NAME} due to snapshot creation" >> ${VM_BACKUP_DIR}/STATUS.error
logger "debug" "Waiting for snapshot creation to be completed - Iteration: ${START_ITERATION} - sleeping for 60secs (Duration: $((START_ITERATION*30)) seconds)"
START_ITERATION=$((START_ITERATION + 1))
if [ ${SNAP_SUCCESS} -eq 1 ]; then
OLD_IFS="${IFS}"
for j in ${VMDKS};
VMDK=$(echo "${j}" | awk -F "###" '{print $1}')
isVMDKFound=0
findVMDK "${VMDK}"
if [[ $isVMDKFound -eq 1 ]] || [[ "${VMDK_FILES_TO_BACKUP}" == "all" ]]; then
#added this section to handle VMDK(s) stored in different datastore than the VM
echo ${VMDK} | grep "^/vmfs/volumes" > /dev/null 2>&1
if [ $? -eq 0 ]; then
SOURCE_VMDK="${VMDK}"
DS_UUID="$(echo ${VMDK#/vmfs/volumes/*})"
DS_UUID="$(echo ${DS_UUID%/*/*})"
VMDK_DISK="$(echo ${VMDK##/*/})"
mkdir -p "${VM_BACKUP_DIR}/${DS_UUID}"
DESTINATION_VMDK="${VM_BACKUP_DIR}/${DS_UUID}/${VMDK_DISK}"
SOURCE_VMDK="${VMX_DIR}/${VMDK}"
DESTINATION_VMDK="${VM_BACKUP_DIR}/${VMDK}"
#support for vRDM and deny pRDM
grep "vmfsPassthroughRawDeviceMap" "${SOURCE_VMDK}" > /dev/null 2>&1
if [ $? -eq 1 ]; then
FORMAT_OPTION="UNKNOWN"
if [ "${DISK_BACKUP_FORMAT}" == "zeroedthick" ]; then
if [[ "${VER}" == "4" ]] || [[ "${VER}" == "5" ]] ; then
FORMAT_OPTION="zeroedthick"
FORMAT_OPTION=""
elif [ "${DISK_BACKUP_FORMAT}" == "2gbsparse" ]; then
FORMAT_OPTION="2gbsparse"
elif [ "${DISK_BACKUP_FORMAT}" == "thin" ]; then
FORMAT_OPTION="thin"
elif [ "${DISK_BACKUP_FORMAT}" == "eagerzeroedthick" ]; then
if [[ "${VER}" == "4" ]] || [[ "${VER}" == "5" ]] ; then
FORMAT_OPTION="eagerzeroedthick"
FORMAT_OPTION=""
[ "${FORMAT_OPTION}" == "UNKNOWN" ]; then
logger "info" "ERROR: wrong DISK_BACKUP_FORMAT \"${DISK_BACKUP_FORMAT}\ specified for ${VM_NAME}"
VM_VMDK_FAILED=1
VMDK_OUTPUT=$(mktemp /tmp/ghettovcb.XXXXXX)
tail -f "${VMDK_OUTPUT}" &
TAIL_PID=$!
ADAPTER_FORMAT=$(grep -i "ddb.adapterType" "${SOURCE_VMDK}" | awk -F "=" '{print $2}' | sed -e 's/^[[:blank:]]*//;s/[[:blank:]]*$//;s/"//g')
[ -z "${FORMAT_OPTION}" ] ; then
logger "debug" "${VMKFSTOOLS_CMD} -i \"${SOURCE_VMDK}\" -a \"${ADAPTER_FORMAT}\" \"${DESTINATION_VMDK}\""
${VMKFSTOOLS_CMD} -i "${SOURCE_VMDK}" -a "${ADAPTER_FORMAT}" "${DESTINATION_VMDK}" > "${VMDK_OUTPUT}" 2>&1
logger "debug" "${VMKFSTOOLS_CMD} -i \"${SOURCE_VMDK}\" -a \"${ADAPTER_FORMAT}\" -d \"${FORMAT_OPTION}\" \"${DESTINATION_VMDK}\""
${VMKFSTOOLS_CMD} -i "${SOURCE_VMDK}" -a "${ADAPTER_FORMAT}" -d "${FORMAT_OPTION}" "${DESTINATION_VMDK}" > "${VMDK_OUTPUT}" 2>&1
VMDK_EXIT_CODE=$?
kill "${TAIL_PID}"
cat "${VMDK_OUTPUT}" >> "${REDIRECT}"
echo >> "${REDIRECT}"
rm "${VMDK_OUTPUT}"
if [ "${VMDK_EXIT_CODE}" != 0 ] ; then
logger "info" "ERROR: error in backing up of \"${SOURCE_VMDK}\" for ${VM_NAME}"
VM_VMDK_FAILED=1
logger "info" "WARNING: A physical RDM \"${SOURCE_VMDK}\" was found for ${VM_NAME}, which will not be backed up"
VM_VMDK_FAILED=1
IFS="${OLD_IFS}"
#powered on VMs only w/snapshots
if [[ ${SNAP_SUCCESS} -eq 1 ]] && [[ ! ${POWER_VM_DOWN_BEFORE_BACKUP} -eq 1 ]] && [[ "${ORGINAL_VM_POWER_STATE}" == "Powered on" ]] || [[ "${ORGINAL_VM_POWER_STATE}" == "Suspended" ]]; then
if [ "${NEW_VIMCMD_SNAPSHOT}" == "yes" ]; then
SNAPSHOT_ID=$(${VMWARE_CMD} vmsvc/snapshot.get ${VM_ID} | grep -E '(Snapshot Name|Snapshot Id)' | grep -A1 ${SNAPSHOT_NAME} | grep "Snapshot Id" | awk -F ":" '{print $2}' | sed -e 's/^[[:blank:]]*//;s/[[:blank:]]*$//')
${VMWARE_CMD} vmsvc/snapshot.remove ${VM_ID} ${SNAPSHOT_ID} > /dev/null 2>&1
${VMWARE_CMD} vmsvc/snapshot.remove ${VM_ID} > /dev/null 2>&1
#do not continue until all snapshots have been committed
logger "info" "Removing snapshot from ${VM_NAME} ..."
while ls "${VMX_DIR}" | grep -q "\-delta\.vmdk";
if [[ ${POWER_VM_DOWN_BEFORE_BACKUP} -eq 1 ]] && [[ "${ORGINAL_VM_POWER_STATE}" == "Powered on" ]]; then
#power on vm that was powered off prior to backup
logger "info" "Powering back on ${VM_NAME}"
${VMWARE_CMD} vmsvc/power.on ${VM_ID} > /dev/null 2>&1
TMP_IFS=${IFS}
IFS=${ORIG_IFS}
if [ ${ENABLE_COMPRESSION} -eq 1 ]; then
COMPRESSED_ARCHIVE_FILE="${BACKUP_DIR}/${VM_NAME}-${VM_BACKUP_DIR_NAMING_CONVENTION}.gz"
logger "info" "Compressing VM backup \"${COMPRESSED_ARCHIVE_FILE}\"..."
if [ ${IS_4I} -eq 1 ]; then
busybox tar -cz -C "${BACKUP_DIR}" "${VM_NAME}-${VM_BACKUP_DIR_NAMING_CONVENTION}" -f "${COMPRESSED_ARCHIVE_FILE}"
tar -cz -C "${BACKUP_DIR}" "${VM_NAME}-${VM_BACKUP_DIR_NAMING_CONVENTION}" -f "${COMPRESSED_ARCHIVE_FILE}"
# verify compression
if [[ $? -eq 0 ]] && [[ -f "${COMPRESSED_ARCHIVE_FILE}" ]]; then
logger "info" "Successfully compressed backup for ${VM_NAME}!\n"
COMPRESSED_OK=1
logger "info" "Error in compressing ${VM_NAME}!\n"
COMPRESSED_OK=0
rm -rf "${VM_BACKUP_DIR}"
checkVMBackupRotation "${BACKUP_DIR}" "${VM_NAME}"
checkVMBackupRotation "${BACKUP_DIR}" "${VM_NAME}"
IFS=${TMP_IFS}
INDEP_VMDKS=""
if [ ${SNAP_SUCCESS} -ne 1 ]; then
logger "info" "ERROR: Unable to backup ${VM_NAME} due to snapshot creation!\n"
[[ ${ENABLE_COMPRESSION} -eq 1 ]] && [[ $COMPRESSED_OK -eq 1 ]] || echo "ERROR: Unable to backup ${VM_NAME} due to snapshot creation" >> ${VM_BACKUP_DIR}/STATUS.error
VM_FAILED=1
elif [ ${VM_VMDK_FAILED} -ne 0 ]; then
logger "info" "ERROR: Unable to backup ${VM_NAME} due to error in VMDK backup!\n"
[[ ${ENABLE_COMPRESSION} -eq 1 ]] && [[ $COMPRESSED_OK -eq 1 ]] || echo "ERROR: Unable to backup ${VM_NAME} due to error in VMDK backup" >> ${VM_BACKUP_DIR}/STATUS.error
VMDK_FAILED=1
elif [ ${VM_HAS_INDEPENDENT_DISKS} -eq 1 ]; then
logger "info" "WARN: ${VM_NAME} has some Independent VMDKs that can not be backed up!\n";
[[ ${ENABLE_COMPRESSION} -eq 1 ]] && [[ $COMPRESSED_OK -eq 1 ]] || echo "WARN: ${VM_NAME} has some Independent VMDKs that can not be backed up" > ${VM_BACKUP_DIR}/STATUS.warn
VMDK_FAILED=1
#experimental
#create symlink for the very last backup to support rsync functionality for additinal replication
if [ "${RSYNC_LINK}" -eq 1 ]; then
SYMLINK_DST=${VM_BACKUP_DIR}
if [ ${ENABLE_COMPRESSION} -eq 1 ]; then
SYMLINK_DST1="${RSYNC_LINK_DIR}.gz"
SYMLINK_DST1=${RSYNC_LINK_DIR}
SYMLINK_SRC="$(echo "${SYMLINK_DST%*-*-*-*_*-*-*}")-symlink"
logger "info" "Creating symlink \"${SYMLINK_SRC}\" to \"${SYMLINK_DST1}\""
ln -sf "${SYMLINK_DST1}" "${SYMLINK_SRC}"
#storage info after backup
storageInfo "after"
logger "info" "Successfully completed backup for ${VM_NAME}!\n"
[[ ${ENABLE_COMPRESSION} -eq 1 ]] && [[ $COMPRESSED_OK -eq 1 ]] || echo "Successfully completed backup" > ${VM_BACKUP_DIR}/STATUS.ok
#experimental
#create symlink for the very last backup to support rsync functionality for additinal replication
if [ "${RSYNC_LINK}" -eq 1 ]; then
SYMLINK_DST=${VM_BACKUP_DIR}
if [ ${ENABLE_COMPRESSION} -eq 1 ]; then
SYMLINK_DST1="${RSYNC_LINK_DIR}.gz"
SYMLINK_DST1=${RSYNC_LINK_DIR}
SYMLINK_SRC="$(echo "${SYMLINK_DST%*-*-*-*_*-*-*}")-symlink"
logger "info" "Creating symlink \"${SYMLINK_SRC}\" to \"${SYMLINK_DST1}\""
ln -sf "${SYMLINK_DST1}" "${SYMLINK_SRC}"
#storage info after backup
storageInfo "after"
if [ ${CONTINUE_TO_BACKUP} -eq 0 ]; then
logger "info" "ERROR: Failed to backup ${VM_NAME}!\n"
VM_FAILED=1
logger "info" "ERROR: Failed to lookup ${VM_NAME}!\n"
VM_FAILED=1
if [[ ${ENABLE_NON_PERSISTENT_NFS} -eq 1 ]] && [[ ${UNMOUNT_NFS} -eq 1 ]] && [[ "${LOG_LEVEL}" != "dryrun" ]]; then
logger "debug" "Sleeping for 30seconds before unmounting NFS volume"
${VMWARE_CMD} hostsvc/datastore/destroy ${NFS_LOCAL_NAME}
getFinalStatus() {
if [[ "${LOG_TYPE}" == "dryrun" ]]; then
FINAL_STATUS="###### Final status: OK, only a dryrun. ######"
LOG_STATUS="OK"
elif [[ $VM_OK == 1 ]] && [[ $VM_FAILED == 0 ]] && [[ $VMDK_FAILED == 0 ]]; then
FINAL_STATUS="###### Final status: All VMs backed up OK! ######"
LOG_STATUS="OK"
elif [[ $VM_OK == 1 ]] && [[ $VM_FAILED == 0 ]] && [[ $VMDK_FAILED == 1 ]]; then
FINAL_STATUS="###### Final status: WARNING: All VMs backed up, but some disk(s) failed! ######"
LOG_STATUS="WARNING"
elif [[ $VM_OK == 1 ]] && [[ $VM_FAILED == 1 ]] && [[ $VMDK_FAILED == 0 ]]; then
FINAL_STATUS="###### Final status: ERROR: Only some of the VMs backed up! ######"
LOG_STATUS="ERROR"
elif [[ $VM_OK == 1 ]] && [[ $VM_FAILED == 1 ]] && [[ $VMDK_FAILED == 1 ]]; then
FINAL_STATUS="###### Final status: ERROR: Only some of the VMs backed up, and some disk(s) failed! ######"
LOG_STATUS="ERROR"
elif [[ $VM_OK == 0 ]] && [[ $VM_FAILED == 1 ]]; then
FINAL_STATUS="###### Final status: ERROR: All VMs failed! ######"
LOG_STATUS="ERROR"
elif [[ $VM_OK == 0 ]]; then
FINAL_STATUS="###### Final status: ERROR: No VMs backed up! ######"
LOG_STATUS="ERROR"
logger "info" "$FINAL_STATUS\n"
buildHeaders() {
EMAIL_ADDRESS=$1
echo -ne "HELO $(hostname -s)\r\n" > "${EMAIL_LOG_HEADER}"
echo -ne "MAIL FROM: \r\n" >> "${EMAIL_LOG_HEADER}"
echo -ne "RCPT TO: \r\n" >> "${EMAIL_LOG_HEADER}"
echo -ne "DATA\r\n" >> "${EMAIL_LOG_HEADER}"
echo -ne "From: ${EMAIL_FROM}\r\n" >> "${EMAIL_LOG_HEADER}"
echo -ne "To: ${EMAIL_ADDRESS}\r\n" >> "${EMAIL_LOG_HEADER}"
echo -ne "Subject: ghettoVCB - ${FINAL_STATUS}\r\n" >> "${EMAIL_LOG_HEADER}"
echo -en ".\r\n" >> "${EMAIL_LOG_OUTPUT}"
echo -en "QUIT\r\n" >> "${EMAIL_LOG_OUTPUT}"
cat "${EMAIL_LOG_HEADER}" > "${EMAIL_LOG_CONTENT}"
cat "${EMAIL_LOG_OUTPUT}" >> "${EMAIL_LOG_CONTENT}"
sendMail() {
#close email message
if [ "${EMAIL_LOG}" -eq 1 ]; then
#validate firewall has email port open for ESXi 5
if [ "${VER}" == "5" ]; then
/sbin/esxcli network firewall ruleset rule list | grep "${EMAIL_SERVER_PORT}" > /dev/null 2>&1
if [ $? -eq 1 ]; then
logger "info" "ERROR: Please enable firewall rule for email traffic on port ${EMAIL_SERVER_PORT}\n"
logger "info" "Please refer to ghettoVCB documentation for ESXi 5 firewall configuration\n"
echo "${EMAIL_TO}" | grep "," > /dev/null 2>&1
if [ $? -eq 0 ]; then
ORIG_IFS=${IFS}
for i in ${EMAIL_TO};
buildHeaders ${i}
"${NC_BIN}" -i "${EMAIL_DELAY_INTERVAL}" "${EMAIL_SERVER}" "${EMAIL_SERVER_PORT}"
/dev/null 2>&1
if [ $? -eq 1 ]; then
logger "info" "ERROR: Failed to email log output to ${EMAIL_SERVER}:${EMAIL_SERVER_PORT} to ${EMAIL_TO}\n"
buildHeaders ${EMAIL_TO}
"${NC_BIN}" -i "${EMAIL_DELAY_INTERVAL}" "${EMAIL_SERVER}" "${EMAIL_SERVER_PORT}"
/dev/null 2>&1
if [ $? -eq 1 ]; then
logger "info" "ERROR: Failed to email log output to ${EMAIL_SERVER}:${EMAIL_SERVER_PORT} to ${EMAIL_TO}\n"
if [ "${EMAIL_DEBUG}" -eq 1 ]; then
logger "info" "Email log output will not be deleted and is stored in ${EMAIL_LOG_CONTENT}"
logger "info" "Removing ${EMAIL_LOG_OUTPUT} and ${EMAIL_LOG_HEADER} and ${EMAIL_LOG_CONTENT}"
rm -f "${EMAIL_LOG_OUTPUT}"
rm -f "${EMAIL_LOG_HEADER}"
rm -f "${EMAIL_LOG_CONTENT}"
####################
# Start of Script
####################
if [ ! -f /bin/bash ]; then
USE_VM_CONF=0
USE_GLOBAL_CONF=0
BACKUP_ALL_VMS=0
EXCLUDE_SOME_VMS=0
EMAIL_LOG_HEADER=/vmfs/volumes/datastore1/log/ghettoVCB-email-$$.header
EMAIL_LOG_OUTPUT=/vmfs/volumes/datastore1/log/ghettoVCB-email-$$.log
EMAIL_LOG_CONTENT=/vmfs/volumes/datastore1/log/ghettoVCB-email-$$.content
#read user input
while getopts ":af:c:g:l:d:e:" ARGS; do
case $ARGS in
BACKUP_ALL_VMS=1
VM_FILE="/tmp/backup_all_vms_on-$(hostname)"
touch "${VM_FILE}"
VM_FILE="${OPTARG}"
VM_EXCLUSION_FILE="${OPTARG}"
EXCLUDE_SOME_VMS=1
CONFIG_DIR="${OPTARG}"
USE_VM_CONF=1
GLOBAL_CONF="${OPTARG}"
USE_GLOBAL_CONF=1
LOG_OUTPUT="${OPTARG}"
LOG_LEVEL="${OPTARG}"
echo "Option -${OPTARG} requires an argument."
printUsage
#performs a check on the number of commandline arguments + verifies $2 is a valid file
sanityCheck $#
LOCKDIR=/tmp/ghettoVCB.lock
if mkdir "${LOCKDIR}"
GHETTOVCB_PID=$$
logger "info" "============================== ghettoVCB LOG START ==============================\n"
logger "debug" "Succesfully acquired lock directory - ${LOCKDIR}\n"
# Remove lockdir when the script finishes, or when it receives a signal
trap 'rm -rf "${LOCKDIR}"' 0
# remove directory when script finishes
trap "exit 2" 1 2 3 13 15
# terminate script when receiving signal
ghettoVCB ${VM_FILE}
getFinalStatus
logger "debug" "Succesfully removed lock directory - ${LOCKDIR}\n"
logger "info" "============================== ghettoVCB LOG END ================================\n"
rm -rf "${LOCKDIR}"
exit $EXIT
logger "info" "Failed to acquire lock, another instance of script may be running, giving up on ${LOCKDIR}\n"

我要回帖

更多关于 pictbridge是什么 的文章

 

随机推荐