Connected Backup, java, and some lousy version checking code.

bradtchapman
Valued Contributor

On some Macs that have Java 8 Update 45 (public release April 14, 2015), the Connected Backup utilities fail to run, ostensibly because of an issue with Java:

"Error: this Java instance does not support a 32-bit JVM.
Please install the desired version."

For those of you who didn't know, Connected Backup has several command line utilities:

/usr/bin/cbactivate
/usr/bin/cbbackup
/usr/bin/cbgetsettings
/usr/bin/cbretrieve
/usr/bin/cbuninstall
/usr/bin/cbupdateconfiguration
/usr/bin/cbcbupdateprofile

Most people will never use these unless for a specific purpose.

Aliases (soft links) to all the cb* utilities are placed at /usr/bin
The real utilities are found in /Library/AgentService/bin

The utility of interest here is getsettings (which is linked from /usr/bin/cbgetsettings). It produces the Java error under OS X 10.7.x, 10.8.x, and 10.9.x, but runs perfectly under 10.10.x .

In this particular environment, getsettings is being used for compliance by reporting the last backup date and status.

The following information is returned from the cbgetsettings -l -x command:

   <Date>6/5/15 5:53PM</date>
   <Status>Completed Successfully</Status>

This information is parsed into delicious chunks by TWO different extension attributes (one for date, one for status).

The Java error, therefore, is particularly unusual, because you would expect a higher version of the operating system to offer even less compatibility with older software.

That's when I started looking at the actual utilities, so I examined the contents of getsettings with the text editor vi:

#!/bin/sh
osversionlong=`sw_vers -productVersion`
osvers=${osversionlong:3:1}
# -d32 is not recognized by Tiger
if [ osvers -le 4 ]; then
#Tiger
javacmd='java'
else
#Leopard or Snow Leopard
javacmd='java -d32'
fi
$javacmd -Djava.library.path=/Library/ (etc...)

Here I found some version checking code that is used to run java as a 32-bit machine, or in some other way, whether it has Tiger, Leopard or Snow Leopard.

osversionlong=`sw_vers -productVersion`
osvers=${osversionlong:3:1}

Let's break down what each part does.

On any given Mac, the command "sw_vers -productVersion" would return something like this:

10.2.8
10.3.9
10.4.11
10.5.8
10.6.8
10.7.5
10.8.5
10.9.5
10.10.4

In the connected backup utilities, this value is stored in the variable osversionlong.

The next variable, osvers, (used later on in the script) is calculated by ${osversionlong:3:1} .

This means: "Take the string in the variable osversionlong, read the character in position 3, and only 1 character from that point." Since computers count from 0, we know that it's actually asking for the character in the 4th position, and ONLY that character.

So from the results above, osvers would be truncated to something like this:

10.2.8 -> 2
10.3.9 -> 3
10.4.11 -> 4
10.5.8 -> 5
10.6.8 -> 6
10.7.5 -> 7
10.8.5 -> 8
10.9.5 -> 9
10.10.3 -> 1

The next few lines are an if-then script to evaluate the version and perform an action:

if [ osvers -le 4 ]; then
#Tiger
javacmd='java'
else
#Leopard or Snow Leopard
javacmd='java -d32'
fi

"If the value of the variable osvers is less than or equal to 4, then assume this is Tiger and set the command to 'java' . Else, assume Leopard or Snow Leopard and set the command to 'java -d32' ."

Here's the thing: for quite some time now, running 'java' has defaulted to 64-bit mode. Java 8u45 must have dropped support for running 32-bit mode altogether, because computers running Java 8u40 return results without error. But these tools clearly did not take into account that a Mac could count to 10. Which explains why a Mac running Java 8u45 & Yosemite would work—the value of osvers would be "1", and 'java' , the 64-bit version, would be called—but a Mac running Mavericks & Java 8u45 would not work, because the value of osvers would be "9", and 'java -d32' would be invoked instead.

SOLUTIONS...

There are three ways to solve this:

One. Comment out or remove ALL the version checking bullcrap, change $javacmd to java, leaving only two lines behind. Make backups of your utilities, because you'll be making permanent changes that may void any service agreements with HP.

#!/bin/sh
java -Djava.library.path=/Library/ (etc...)

(note how javacmd isn't actually needed anymore).

Two. As a workaround for reporting purposes, a la an extended attribute, run the java command DIRECTLY (kudos to @makingtortillas for this suggestion):

java -Djava.library.path=/Library/AgentService/bin/ -Xmx1024m -Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.Jdk14Logger -Djava.util.logging.config.file=AgentLogger.properties  -cp /Library/AgentService/bin/agent.jar:/System/Library/Java com.connected.agent.cmdline.GetRegistrationInfo "$@" -l -x

Note the -l -x switches at the end: the huge java message above is just a substitute for "getsettings" , and the reason this mess is encapsulated inside a .sh script is for convenience and ease of documentation.

Three. Pester HP to fix these horribly broken utilities. (LOL)

So, just to be clear: the utility runs FINE in 64-bit mode and returns the expected results.

This was tested on OS X Mavericks. Please for goodness' sake, test this in your environment before putting it into production.

9 REPLIES 9

bradtchapman
Valued Contributor

I apologize for the wall of text. I am presenting a solution here for those of you with Connected Backup in your environment.

nessts
Valued Contributor II

I have many 10.9 and 10.10 machines running connected backup without issue, are the servers upgraded and are you running the latest version of software? Lets face it Apple pre-installation software checks did not deal real well with 10.10 when it first came out either for similar reasons.

bradtchapman
Valued Contributor

@nessts, this is a client-side issue. The installed version of CB is 8.8.2.*, and it's throwing a Java error because the utilities specifically call java -d32, which won't work.

According to this thread on Oracle Community, which is admittedly kind of old, the -d32 and -d64 options existed on Solaris because there was support (and a need for) running Java in 32-bit or 64-bit mode.

jhbush
Valued Contributor II

@bradtchapman would you mind posting your EA for CB here or on GitHub?

Thanks

jacopo_pulici
Contributor

I'm interested as well.
@bradtchapman, do you mind sharing with us your EA for CB?
Thanks

bradtchapman
Valued Contributor

Hi folks! Sorry I took so long to respond to this. Here's the code for each part that I wrote 8 months ago. There's probably a more efficient way to deal with the <brackets> but I don't know awk well enough to fix it.

Please also understand that this will launch cause a Java applet to launch for about 5 seconds, which steals focus and causes an icon to appear in the dock for a few seconds. This data may be stored in the XML files accompanying the cb libraries, so you might try parsing them directly.

LAST BACKUP DATE

#!/bin/sh
## by Brad Chapman for JAMF Nation, 6-6-2015

if [ -d /Applications/Autonomy/Connected Backup/Connected Backup.app ]; then
RESULT=`/usr/bin/cbgetsettings -l -x | grep Date | sed 's/</ /g' | sed 's/>/ /g' | awk '{ print $2 }'`
    echo "<result>$RESULT</result>"
else
    echo "<result>Not Installed</result>"
fi

GET CONNECTED BACKUP STATUS

#!/bin/sh
## by Brad Chapman for JAMF Nation, 6-6-2015

if [ -d /Applications/Autonomy/Connected Backup/Connected Backup.app ]; then
RESULT=`/usr/bin/cbgetsettings -l -x | grep Status | sed 's/    <Status>//g' | sed 's/</Status>//g'`
    echo "<result>$RESULT</result>"
else
    echo "<result>Not Installed</result>"
fi

jhbush
Valued Contributor II

@bradtchapman thank you for posting those. It looks like for 8.8.5.0 and above the binary to use is

/Library/AgentService/bin/getsettings

rather than

/usr/bin/cbgetsettings

The binary doesn't steal focus or visibly launch the jar when run remotely.

donmontalvo
Esteemed Contributor II

@jhbush1973 interesting, 8.8.5.0 and it's new binary doesn't steal focus when run remotely, or when triggered by a script on the computer (ie JSS policy), but does when invoked via Terminal at the actual computer.

The commands take more time than we like, so we're running a policy that outputs Status and Date to separate files, then grabbing the file contents via EA.

#GimmeCrashPlanDammit

--
https://donmontalvo.com

BK
New Contributor III

Just an update for everyone. In version 8.9.0 the binaries are stored all in /Library/AgentService/bin as a few of folks mentioned above.

/Library/AgentService/bin/backup
/Library/AgentService/bin/recover
/Library/AgentService/bin/updateprofile
/Library/AgentService/bin/retrieve
/Library/AgentService/bin/activate
/Library/AgentService/bin/getsettings
/Library/AgentService/bin/uninstall
/Library/AgentService/bin/updateconfiguration (previously cbupdateconfiguration and still documented this way!)

The documentation for 8.9 is horrible. Not updated with these new binaries or where they even are and typos.