Posted on 08-29-2012 07:04 AM
Hello, all.
I'm trying to deploy an older version of Wacom tablet driver to several workstations with tablets not supported by the version that was included in our image. The first part of this process is removing the current driver so that I can install the older one. I've extracted the Wacom-developed uninstall script from the Wacom Tablet Utility and setup a policy that runs it and nothing else. Here is the log from the JSS. You can see that the script exit code is zero, yet it is still showing that the policy failed:
/usr/sbin/jamf is version 8.52
Executing Policy Wacom Separate Uninstall Script...
Mounting smb://casper.acad.ccad.edu/JSS_Repository to /Volumes/JSS_Repository...
Running Script wacomTablet_uninstall.pl...
Script Exit Code:0
Script Result: Deleting StartupItems - Driver:
Deleting Driver.kext:
Can't exec "/private/tmp/SystemLoginItemTool": No such file or directory at /private/tmp/wacomTablet_uninstall.pl line 262.
Tablet Driver not running.:
Unloading KEXTs:
(kernel) Kext com.Wacom.iokit.TabletDriver not found for unload request.
Failed to unload com.Wacom.iokit.TabletDriver - (libkern/kext) not found.
(kernel) Kext com.wacom.driver.HIDTablet not found for unload request.
Failed to unload com.wacom.driver.HIDTablet - (libkern/kext) not found.
Deleting Preferences:
readdir() attempted on invalid dirhandle TABLETDIR at /private/tmp/wacomTablet_uninstall.pl line 413.
closedir() attempted on invalid dirhandle TABLETDIR at /private/tmp/wacomTablet_uninstall.pl line 422.
Removing /Users/student/Library/Preferences/com.wacom.wacomtablet.prefs
Removing /Users/student/Library/Preferences/com.wacom.wacomtouch.prefs
Deleting Control Panels:
No receipt for 'com.wacom.installwacomtablet' found at '/'.
Deleting Frameworks
Deleting Internet Plugins:
Done.:
Unmounting file server...
The script itself is below. I don't really do perl, but I see the main routine ends with exit 0, and as previously mentioned, the JSS is picking up on that exit code. Can anyone help me figure out how I can get a successful result with the policy so that I have an accurate listing of where this script has run successfully?
Thanks,
Eric
#! /usr/bin/perl -w
#-----------------------------------------------------------------------------
#
# FILE NAME
#
# uninstall_base.pl
#
# PURPOSE
#
# Remove Tablet Driver From System. Also allows removing preferences for the
# current user or all users.
#
# COPYRIGHT
#
# Copyright WACOM Technology, Inc. 2003 - 2009
# All rights reserved.
#
#-----------------------------------------------------------------------------
use strict;
use Env;
use utf8;
use File::Basename;
use File::Path "rmtree";
use Getopt::Long;
use Data::Dumper;
# Make %ENV safer; this script runs as root
# removes search paths, so all commands must be issued with fully-qualified paths
$ENV{PATH} = "";
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
##############################################################################
# Prototypes
sub killRunning;
sub deleteReciepts;
sub deleteProLanguageFiles;
sub deleteSystemFiles;
sub deleteWacomApplications;
sub deleteCurrentUserPreferenceFiles;
sub deleteAllPreferenceFiles;
sub deleteWacomInternetPlugins;
sub removeDirIfEmpty;
sub removeFileIfExists;
sub deleteUserDefaultsFile;
sub createRestorePrefsFile;
sub quitPreferences;
sub quitAllPreferences;
##############################################################################
# Globals
my $gDriverExecutable = "WacomTabletDriver";
my $gDriverApp = "$gDriverExecutable.app";
my $gDriverSpringboard = "WacomTabletSpringboard";
my $gPrefPane = "WacomTablet.prefpane";
my $gKext = "Wacom Tablet.kext";
my $gLaunchAgent = "com.wacom.wacomtablet.plist";
my $gPrefFile = "com.wacom.wacomtablet.prefs";
my $gCFPlugin = "TabletDriverCFPlugin.bundle";
my $gAppFolder = "/Applications/Wacom Tablet.localized";
my $gUninstaller = "Wacom Tablet Utility.app";
my $gUninstaller_Old = "Removed Wacom Tablet.app";
my $gDocReceipt = "Wacom Tablet Docs.txt";
my $gInstallerPkg = "Install Wacom Tablet.pkg";
my $gDriverAppPath = "/Library/Application Support/Tablet";
my $gOtherDriverKext = "Pen Tablet.kext";
my $gSafariPlugin = "WacomSafari.plugin";
my $gNetscapePlugin = "WacomNetscape.plugin";
my $gWacomTabletPlugin = "WacomTabletPlugin.plugin";
my $gTouchPrefFile = "com.wacom.wacomtouch.prefs";
my $gTouchUserDefaults = "com.wacomtouchtablet.userdefaults.xml";
my $gDriverUserDefaults = "com.wacomtablet.userdefaults.xml";
my $gTouchRestorePrefFile = "com.wacom.wacomtouch.restore.prefs";
my $gPenRestorePrefFile = "com.wacom.wacomtablet.restore.prefs";
# Bundle identifiers
my $gInstallerBundleIdentifier = "com.wacom.installwacomtablet";
my $gKextIdentifier = "com.wacom.kext.wacomtablet";
# Xtras
my $gXtrasFolder = "";
my $gWacomXtraFile = "";
my $gWacomDataXtraFile = "";
#------------------
# This script is customized based on whether it removes Consumer or Professional
# drivers. All the variables declaring the filenames are spliced into this
# script at build time. We can't just include them because this script runs
# under root privileges, and inclusion is consequently disabled as a security
# risk.
my $gCoordinatorExecutable = "TabletDriver";
my $gOldPrefFile = "com.wacom.tabletpreferences";
my $gSysPrefsExecutable = "System Preferences";
my $wacomLog = "wacomlog.txt";
#command line options & hash table
my $prefsOnly = 0;
my $currentPrefsOnly = "";
my $restartDrivers = 0;
my %commandOpts = ("prefsonly" => $prefsOnly, "currentprefsonly=s" => $currentPrefsOnly, "restartdrivers" => $restartDrivers);
my @processList = `/bin/ps -axcopid,command`;
my @currentUserProcessList = `/bin/ps -xcopid,command`;
##############################################################################
# main
##############################################################################
sub main
{
GetOptions(%commandOpts);
if ($prefsOnly) { quitAllPreferences(); deleteAllPreferenceFiles(); hupDriver(); } elsif($currentPrefsOnly) #Remove current user's prefs only { quitPreferences(); deleteCurrentUserPreferenceFiles($currentPrefsOnly); hupDriver(); } elsif($restartDrivers) #restart drivers (called for resetting preferences) { quitPreferences(); #if the preference pane is running, quit hupDriver(); } else #Remove everything (uninstall) { quitAllPreferences();
# Delete running programs, *then* kill them so launchd won't relaunch them # even if KeepAlive is enabled. deleteSystemFiles(); killRunning();
deleteAllPreferenceFiles(); deleteWacomApplications(); deleteReceipts(); deleteFrameworks(); deleteWacomInternetPlugins(); deleteUserDefaultsFile(); }
print "Done.: ";
exit 0;
}
##############################################################################
# The Sub Routines
##############################################################################
##############################################################################
sub hupDriver
{
# defect 5670 It's problematic to restart driver for inactive user sessions.
# All driver processes would be competing for resources such as connection
# to the tablet and the current driver process may lose.
# So we only restart the driver in the current session.
# The inactive sessions will pick up the change after logout and back in.
foreach my $process (@currentUserProcessList)
{
if($process =~ m/^s*(d+)s+$gDriverExecutable$/)
{
print "Restarting Driver $1
";
kill "HUP", $1;
return;
}
}
}
##############################################################################
sub quitPreferences
{
my @processUserListPre = `/bin/ps -xcopid,command`;
my @processUserListPost = ();
my $script = qq| tell application "System Preferences" to quit|;
# Defect 6001 removal of prefs while System Preferences is running # was causing System Preferences to crash. Problem fixed by # quitting System Preferences before prefs file is removed.
foreach my $process (@processUserListPre) { if($process =~ m/^s*(d+)s+$gSysPrefsExecutable$/) { system(qq|/usr/bin/osascript -e '$script'|); return; } }
@processUserListPost = `/bin/ps -xcopid,command`;
foreach my $process (@processUserListPost)
{
if($process =~ m/^s*(d+)s+$gSysPrefsExecutable$/)
{
kill "TERM", $1;
}
}
}
##############################################################################
sub quitAllPreferences
{
my @allProcessList = ();
quitPreferences();
# Defect 6001 removal of prefs while System Preferences is running # was causing System Preferences to crash. Problem fixed by # quitting System Preferences before prefs file is removed.
@allProcessList = `/bin/ps -axcopid,command`;
foreach my $process (@allProcessList)
{
if($process =~ m/^s*(d+)s+$gSysPrefsExecutable$/)
{
kill "TERM", $1;
}
}
}
##############################################################################
# killRunning
#
# Purpose: Terminating running executables or loaded code.
#
sub killRunning
{
my @killPIDs;
#delete System login item entry my $sysLogItemTool = dirname($0)."/SystemLoginItemTool"; $sysLogItemTool =~ m/^(.*)$/; $sysLogItemTool = $1; #get around perl security
# SystemLoginItem tool can not run link on 10.1.5 # so ignore any errors from it. That's ok because it's not needed on 10.1.5 anyway. eval { system($sysLogItemTool, "-d", "$gDriverAppPath/$gDriverApp"); };
# Find PIDs of processes to kill foreach my $process (@processList) { # Driver if( $process =~ m/^s*(d+)s+$gDriverExecutable$/ ) { push @killPIDs, $1; }
# Coordinator (only if the other driver isn't running) if( isOtherDriverInstalled() == 0 && $process =~ m/^s*(d+)s+$gCoordinatorExecutable$/ ) { push @killPIDs, $1; } }
# Kill 'em if ( scalar @killPIDs ) { print "Killing Tablet Driver: @killPIDs "; kill "QUIT", @killPIDs; } else { print "Tablet Driver not running.: "; }
print "Unloading KEXTs: "; `/sbin/kextunload -m com.Wacom.iokit.TabletDriver`; `/sbin/kextunload -m com.wacom.driver.HIDTablet`;
}#end killRunning
##############################################################################
# deleteReceipts
#
# Purpose: Delete the evidence that this install ever existed. Now when
# running the installer again, it won't complain about
# pre-existing versions.
#
sub deleteReceipts
{
my $delFile;
# Receipt tracking has been an evolving field: # 10.4: Installed packages, stripped of contents, are put in /Library/Receipts # 10.5: Some (newer?) packages are registered in a database format which can # be manipulated with the new pkgutil command-line tool. Traditional # receipts are still written too, and are the exclusive means of # tracking older package formats such as Wacom's installer. # 10.6: Now everything goes to the database. You must use pkgutil.
# Snow Leopard: try pkgutil. system("/usr/sbin/pkgutil", "--forget", $gInstallerBundleIdentifier);
# Earlier: delete the files rmtree( "/Library/Receipts/$gInstallerPkg" ); rmtree( "/Library/Receipts/$gDocReceipt" );
}#end deleteReceipts
##############################################################################
sub deleteSystemFiles
{
my $extensionsDir = "/System/Library/Extensions";
my $launchAgents = "/Library/LaunchAgents";
my $xtrasFolderLength = length($gXtrasFolder);
print "Deleting StartupItems - Driver: ";
# Tablet Driver rmtree("$gDriverAppPath/$gDriverApp"); rmtree("$gDriverAppPath/$gDriverSpringboard");
# if installer happened to have failed make sure the Xtras temp folder gets deleted. if($xtrasFolderLength > 0) { rmtree(["$gDriverAppPath/$gXtrasFolder/$gWacomXtraFile"], 0, 0); rmtree(["$gDriverAppPath/$gXtrasFolder/$gWacomDataXtraFile"], 0, 0);
removeDirIfEmpty("$gDriverAppPath/$gXtrasFolder"); } removeDirIfEmpty("$gDriverAppPath");
# launchd agents rmtree(["$launchAgents/$gLaunchAgent"], 0, 0);
# Kexts print "Deleting Driver.kext: "; rmtree(["$extensionsDir/$gKext"], 0, 0);
# The TabletDriverCFPlugin is shared between the two drivers, so only remove
# it if we are removing the last driver.
if( isOtherDriverInstalled() == 0 )
{
rmtree(["$extensionsDir/$gCFPlugin"], 0, 0);
}
}
##############################################################################
sub deleteWacomApplications
{
my $prefpanesDir = "/Library/PreferencePanes";
my $tutorialLog = "$gAppFolder/$wacomLog";
print "Deleting Control Panels: ";
# Get the path to the RemoveTablet.app's folder my $manifestFile;
my @applications = ( "$prefpanesDir/$gPrefPane", "$gAppFolder/$gUninstaller_Old", "$gAppFolder/$gUninstaller" );
map { removeFileIfExists($_); } @applications;
removeFileIfExists($tutorialLog);
# Delete installed docs listed in manifest file if (open MANIFEST, "<", "/Library/Receipts/$gDocReceipt") { while(<MANIFEST>) { chomp $; $manifestFile = $; $manifestFile =~ m/^(.*)$/; $manifestFile = $1; #get around perl security
removeFileIfExists($manifestFile) } close MANIFEST; } else { # no manifest file }
# Delete tablet folder if it's empty my $isEmpty = 1; opendir TABLETDIR, $gAppFolder; my @dirlist = readdir TABLETDIR; my $dirEntry; foreach $dirEntry (@dirlist) { if ( $dirEntry !~ m/^./) { $isEmpty = 0; } } closedir TABLETDIR;
# We used to check the empty status, but when we switched to installing
# manuals through the control panel, that method wouldn't leave a receipt
# that could be used to remove it, so now we're removing the Wacom Tablet
# folder and any files contained therein without checking.
#if ($isEmpty == 1)
#{
rmtree(["$gAppFolder"], 0, 0);
#}
}
##############################################################################
sub deleteCurrentUserPreferenceFiles
{
print "Deleting Preferences:
";
my $userName = shift; my $prefFile; my $nameLength = length($gTouchPrefFile); my $prefsFolder = "/Users/$userName/Library/Preferences";
$prefFile = "$prefsFolder/$gOldPrefFile"; removeFileIfExists($prefFile);
$prefFile = "$prefsFolder/$gPrefFile"; removeFileIfExists($prefFile);
if ($nameLength > 0) { $prefFile = "$prefsFolder/$gTouchPrefFile"; removeFileIfExists($prefFile); }
# creating restore files to signal the pen and touch driver to restore to defaults
createRestorePrefsFile($prefsFolder, $gPenRestorePrefFile);
createRestorePrefsFile($prefsFolder, $gTouchRestorePrefFile);
}
##############################################################################
# deleteAllPreferenceFiles
#
# Purpose: Deletes preferences files for all users.
#
# Note that this routine will leave a set of "restore.pref" files in other
# user accounts. This is done because the driver can't be restarted in other
# user accounts without causing problems (see comments under hupDriver())
#
sub deleteAllPreferenceFiles
{
print "Deleting Preferences:
";
my @homeList; my $homeRegEx; my $homeLine; my $prefFile;
my $nameLength = length($gTouchPrefFile);
if(-e "/usr/bin/niutil") { # MacOS X Server @homeList = `/usr/bin/niutil -list . /users home`; } else { # MacOS X @homeList = `/usr/bin/dscl localhost -list /Search/Users home`; }
$homeRegEx = 's(/Users/.*)';
#delete each user's preference file foreach $homeLine (@homeList) { next if not $homeLine =~ /$homeRegEx/;
my $homePath = $1; my $prefsFolder = "$homePath/Library/Preferences";
#delete legacy pref file $prefFile = "$prefsFolder/$gOldPrefFile"; removeFileIfExists($prefFile);
#delete pen pref file $prefFile = "$prefsFolder/$gPrefFile"; removeFileIfExists($prefFile);
#delete touch pref file if ($nameLength > 0) { $prefFile = "$prefsFolder/$gTouchPrefFile"; removeFileIfExists($prefFile); }
if ($prefsOnly) { # we're just removing prefs; not uninstalling. # create empty restore file so driver will pick up the changes upon restart createRestorePrefsFile($prefsFolder, $gPenRestorePrefFile); createRestorePrefsFile($prefsFolder, $gTouchRestorePrefFile); } else { # this is uninstall # remove the restore files if(length($gPenRestorePrefFile) > 0) { removeFileIfExists("$prefsFolder/$gPenRestorePrefFile"); }
if(length($gTouchRestorePrefFile) > 0) { removeFileIfExists("$prefsFolder/$gTouchRestorePrefFile"); } } }
#delete global preference file my $globalPrefsFolder = "/Library/Preferences/Tablet"; removeFileIfExists("$globalPrefsFolder/$gOldPrefFile"); removeFileIfExists("$globalPrefsFolder/$gPrefFile");
if ($nameLength > 0) { removeFileIfExists("$globalPrefsFolder/$gTouchPrefFile"); }
#delete global Tablet preference folder if empty
removeDirIfEmpty($globalPrefsFolder);
}
##############################################################################
sub deleteFrameworks
{
print "Deleting Frameworks
";
rmtree("/Library/Frameworks/WacomMultiTouch.framework");
}
##############################################################################
sub deleteWacomInternetPlugins
{
print "Deleting Internet Plugins:
";
# The web plugins are shared between the two drivers, so only remove them if
# we are removing the last driver.
if( isOtherDriverInstalled() == 0 )
{
deleteInternetPlugin($gSafariPlugin);
deleteInternetPlugin($gNetscapePlugin);
deleteInternetPlugin($gWacomTabletPlugin);
}
}
##############################################################################
# deleteInternetPlugin
#
# Purpose: Deletes an Internet plugin of the given name from the standard
# Internet Plugins folder.
#
# Parameters: $[0] = the plugin file name
#
sub deleteInternetPlugin
{
my $pluginName = $[0]; #first argument.
my $nameLength = length($pluginName);
if ($nameLength > 0) { my $pluginPath = "/Library/Internet Plug-Ins/$pluginName"; removeFileIfExists($pluginPath); }
}#end deleteInternetPlugin
##############################################################################
# deleteUserDefaultsFile
#
# Purpose: Delete the user defaults files for both touch and pen if they
# exist.
#
sub deleteUserDefaultsFile
{
my $userDriverLength = length($gDriverUserDefaults);
my $userTouchLength = length($gTouchUserDefaults);
if($userDriverLength > 0) { my $userDriverDefaultsPath = "/Library/Preferences/$gDriverUserDefaults"; removeFileIfExists($userDriverDefaultsPath); }
if($userTouchLength > 0)
{
my $usersTouchDefaultsPath = "/Library/Preferences/$gTouchUserDefaults";
removeFileIfExists($usersTouchDefaultsPath);
}
}
##############################################################################
# isOtherDriverInstalled
#
# Purpose: Returns true if the other Wacom driver is installed, such as if
# this is a pro uninstaller and the consumer driver is installed.
#
sub isOtherDriverInstalled
{
my $otherDriverIsPresent = 0;
# check for the presence of an indicative file. if(-e "/System/Library/Extensions/$gOtherDriverKext") { $otherDriverIsPresent = 1; }
return $otherDriverIsPresent;
}#end isOtherDriverInstalled
##############################################################################
sub removeDirIfEmpty
{
my $dirToRemove = shift;
my $isEmpty = 1;
opendir SOMEDIR, $dirToRemove or return;
my @dirlist = readdir SOMEDIR;
my $dirEntry;
foreach $dirEntry (@dirlist)
{
if ( $dirEntry !~ m/^./)
{
$isEmpty = 0;
}
}
closedir SOMEDIR;
if ($isEmpty == 1)
{
rmtree([$dirToRemove], 0, 0);
}
}
##############################################################################
sub removeFileIfExists
{
my $full_path = shift;
if(-e $full_path)
{
print "Removing $full_path
";
rmtree([$full_path], 0, 0);
}
}
##############################################################################
# createRestorePrefsFile
#
# Purpose: Create an empty file with the given file name under user's
# Preferences folder.
#
# Parameters: $[0] = prefs folder path, file name
#
sub createRestorePrefsFile
{
my ($prefsFolder, $fileName) = @;
if (length($fileName) > 0) { my $filePath = "$prefsFolder/$fileName";
# remove the existing one if exists removeFileIfExists($filePath);
# create the file open(RESTOREFILE, ">$filePath") or warn "Could not create $filePath .";
# done; close the file close RESTOREFILE;
# set file permission to -rw-rw-r--
system("/bin/chmod", "664", $filePath);
}
}#end createRestorePrefsFile
##############################################################################
main();
Posted on 08-29-2012 07:09 AM
Eric,
I can see from the policy result you have some text that returns "FAILED"
Unloading KEXTs: (kernel) Kext com.Wacom.iokit.TabletDriver not found for unload request. Failed to unload com.Wacom.iokit.TabletDriver - (libkern/kext) not found. (kernel) Kext com.wacom.driver.HIDTablet not found for unload request. Failed to unload com.wacom.driver.HIDTablet - (libkern/kext) not found.
The JSS will see this @ report it as an error. The words error or fail will trigger this response (might be more).
It's actually been this way since v6 I think, there may be a feature request to have this changed. Pretty sure I made one pre-JAMF Nation.
Posted on 08-29-2012 07:50 AM
Ben,
So even though the exit code of the script itself is a 0, the JSS parses the output of the script to see the word "failed" or somehow sees the failure of individual commands/subroutines within the script? Wow, would not have guessed that. That's very frustrating. Can I simply redirect script output to /dev/null to fix this?
Thanks,
Eric
Posted on 08-29-2012 07:55 AM
yeah the JSS looks at output, i had an LD_LANG environment variable in my .cshrc and when the admin user was trying to ssh in Recon or Remote, there was a line of output from sudo about LD environment variables, which in all reality did not cause a problem but JSS saw it as an error, and stopped all processing. So any output could be the cause I am unsure if they are looking for warning, failure or specific words or not.
Posted on 08-29-2012 08:00 AM
i've seen where any output at all, regardless of the script's exit code, can cause a failure report. it may have more to do with other commands used within a script sending output to STDERR by default, though it's still something that should be accommodated in policy run reporting.
Posted on 08-29-2012 09:59 AM
OK, so initial testing shows that directing all output and error to /dev/null yields a successful policy run in JSS. Annoying. Time to hunt down that feature request and complain to support.
Posted on 01-31-2014 02:51 PM
I stumbled upon this thread while dealing with false-negatives for script policies, so I'm necro'ing it for the sake of anyone else who may...
This general construct has worked for us to preserve the exit status and stdout/stderr from adobe_prtk and a few other command line tools, but hid them from Casper. The key bits to hiding but preserving output are underlined. —Cheers, JReid
#!/bin/bash
echo -n "<br>• running that tool with unreliable output... ";
**+toolOut=$(+** /path/to/flaky/tool --thenItsFlags **+2>&1 )+**;
**+toolExit=$?+** ;
**+if [ $toolExit -eq 0 ]; then+**
echo "probable success. Output was:";
echo "<br>${toolOut}";
# more success code
**+else+**
echo "probably failed. Output was:";
echo "<br>${toolOut}";
# more failure code
# maybe we'll match script exit code to the tool's:
exit $toolExit
**+fi;+**
Posted on 03-26-2014 07:28 AM
Found this in the release notes for 9.3 as a deprecation:
?
Policy status determined by checking script output for “error” and “fail”—Historically, one of the ways the JSS has determined the status of a policy is by checking script output for the words “error” and “fail”. As of v9.0, the JSS also uses exit codes to determine the status of a policy. This method is more reliable and accurate.
Although the JSS v9.3 still checks script output for the words “error” or “fail”, this will be removed in a future version. If you have written scripts that utilize this feature, consider implementing an alternative solution using exit codes as soon as possible.
Looks like this will no longer be an issue in the future.
Posted on 03-26-2014 07:36 AM
That paragraph has been in the release notes for I think every version of Casper Suite 9, since 9.0, I think version 9 is mature enough at this point for them to remove that legacy feature altogether. It doesn't really serve a good purpose. Its better to check the actual exit status than to look for specific words in stdout.
Posted on 01-12-2016 12:40 AM
Let me bump this thread… I have a similar issue:
I try to install Sophos Cloud Endpoint. I created an Autopkg with a post install:
#!/bin/bash
# Following https://www.sophos.com/en-us/support/knowledgebase/120570.aspx
# test_command
# Found on http://stackoverflow.com/questions/5195607/checking-bash-exit-status-of-several-commands-efficiently
function test_command {
"$@"
local status=$?
echo -n "Executing '$@'… "
if [ $status -ne 0 ]; then
echo "ERROR: $@" >&2
exit $status
fi
echo "OK"
}
BASEPATH="/Library/MyFiles/SophosInstall"
test_command $BASEPATH/Sophos Installer.app/Contents/MacOS/Sophos Installer --install &> $BASEPATH/sophosinstall.log
# Should have exited with $status before if something failed
exit 0
The logs on JSS. This one is marked as Completed:
Mac mini de François levaufr1 About a minute ago Completed Executing Policy ASAP: Push SophosCloudEndpoint Downloading SophosCloudEndpoint-1.2.pkg... Downloading https://d1b21.cloudfront.net/SophosCloudEndpoint-1.2.pkg... Verifying package integrity... Installing SophosCloudEndpoint-1.2.pkg... Installation failed. The installer reported: installer: Package name is SophosCloudEndpoint-1.2 installer: Upgrading at base path / installer: The upgrade failed (Le programme d’installation a rencontré une erreur qui a provoqué l’échec de l’installation. Contactez l’éditeur du logiciel pour obtenir de l’aide.) Running Recon... Retrieving inventory preferences from https://jss.ftiff.com/... Locating accounts... Locating package receipts... Searching path: /Applications Locating printers... Gathering application usage information...
Install.log on client:
Jan 12 09:23:56 minidefrancois installd[14420]: PackageKit: Executing script "./postinstall" in /private/tmp/PKInstallSandbox.xtjcl9/Scripts/com.github.FTIFFGITS.mac-autopkg.pkg.SophosCloudEndpoint.bMTA7f Jan 12 09:23:58 minidefrancois Sophos Bootstrap[14520]: [SMESophosBootstrapAppDelegate.m:1329] System verified Jan 12 09:26:24 minidefrancois Sophos Installer[14530]: [SMEInstallController.m:212] Installing saas version 9.3.4 Jan 12 09:26:24 minidefrancois Sophos Installer[14530]: [SMEInstallController.m:817] Fresh install of the "saas" product. Jan 12 09:26:24 minidefrancois Sophos Installer[14530]: [SMEAggregateInstallStrategy.m:71] "installer.prepare.stopProcesses" success: YES Jan 12 09:26:24 minidefrancois Sophos Installer[14530]: [SMEAggregateInstallStrategy.m:71] "installer.prepare.removeComponents" success: YES Jan 12 09:26:24 minidefrancois Sophos Installer[14530]: [SMEAggregateInstallStrategy.m:71] "installer.prepare.removeKeychains" success: YES Jan 12 09:26:24 minidefrancois Sophos Installer[14530]: [SMEAggregateInstallStrategy.m:71] "installer.localPayload.buildPlan" success: YES Jan 12 09:26:31 minidefrancois Sophos Installer[14530]: [SMEAggregateInstallStrategy.m:71] "installer.localPayload.cacheManifestComponents" success: YES Jan 12 09:26:31 minidefrancois Sophos Installer[14530]: [SMEAggregateInstallStrategy.m:71] "installer.localPayload.remoteRemove" success: YES Jan 12 09:26:34 minidefrancois Sophos Bootstrap Downloader[14523]: [SMEDownloadController.m:478] Failed to launch /Library/Caches/com.sophos.sau/CID/Sophos Installer.app/Contents/MacOS/tools/InstallationDeployer with returncode: 11, stderr: Jan 12 09:26:35 minidefrancois Sophos Bootstrap[14520]: [SMESophosBootstrapAppDelegate.m:980] Received failure notification: (1) Jan 12 09:26:36 minidefrancois Sophos Bootstrap[14520]: [SophosDistantObject.m:208] An exception was encountered while messaging the server: SophosNilProxyException. Retrying: 1 attempt(s) Jan 12 09:26:36 minidefrancois Sophos Bootstrap[14520]: [SMESophosBootstrapAppDelegate.m:222] Installation failed. Jan 12 09:26:37 minidefrancois install_monitor[14517]: Re-included: /Applications, /Library, /System, /bin, /private, /sbin, /usr Jan 12 09:26:37 minidefrancois installd[14420]: PackageKit: releasing backupd Jan 12 09:26:37 minidefrancois installd[14420]: PackageKit: allow user idle system sleep Jan 12 09:26:37 minidefrancois installd[14420]: PackageKit: Install Failed: Error Domain=PKInstallErrorDomain Code=112 "Une erreur s’est produite pendant l’exécution des scripts du paquet « SophosCloudEndpoint-1.2.pkg »." UserInfo={NSFilePath=./postinstall, NSURL=file://localhost/Library/Application%20Support/JAMF/Downloads/SophosCloudEndpoint-1.2.pkg, PKInstallPackageIdentifier=com.github.FTIFFGITS.mac-autopkg.pkg.SophosCloudEndpoint, NSLocalizedDescription=Une erreur s’est produite pendant l’exécution des scripts du paquet « SophosCloudEndpoint-1.2.pkg ».} { NSFilePath = "./postinstall"; NSLocalizedDescription = "Une erreur sU2019est produite pendant lU2019exU00e9cution des scripts du paquet U00abU00a0SophosCloudEndpoint-1.2.pkgU00a0U00bb."; NSURL = "file://localhost/Library/Application%20Support/JAMF/Downloads/SophosCloudEndpoint-1.2.pkg"; PKInstallPackageIdentifier = "com.github.FTIFFGITS.mac-autopkg.pkg.SophosCloudEndpoint"; } Jan 12 09:26:37 minidefrancois installd[14420]: PackageKit: Running idle tasks Jan 12 09:26:37 minidefrancois installer[14514]: install:didFailWithError:Error Domain=PKInstallErrorDomain Code=112 "Une erreur s’est produite pendant l’exécution des scripts du paquet « SophosCloudEndpoint-1.2.pkg »." UserInfo={NSFilePath=./postinstall, NSURL=file://localhost/Library/Application%20Support/JAMF/Downloads/SophosCloudEndpoint-1.2.pkg, PKInstallPackageIdentifier=com.github.FTIFFGITS.mac-autopkg.pkg.SophosCloudEndpoint, NSLocalizedDescription=Une erreur s’est produite pendant l’exécution des scripts du paquet « SophosCloudEndpoint-1.2.pkg ».} Jan 12 09:26:37 minidefrancois installd[14420]: PackageKit: Removing client PKInstallDaemonClient pid=14514, uid=0 (/usr/sbin/installer) Jan 12 09:26:37 minidefrancois installd[14420]: PackageKit: Done with sandbox removals Jan 12 09:26:38 minidefrancois installer[14514]: Install failed: Le programme d’installation a rencontré une erreur qui a provoqué l’échec de l’installation. Contactez l’éditeur du logiciel pour obtenir de l’aide.
my sophosinstall.log:
2016-01-12 09:23:57.247 Sophos Installer[14520:549229] Starting Sophos Bootstrap Installer. 2016-01-12 09:26:36.827 Sophos Installer[14520:549229] Installation failed. See install.log for detailed information. Executing '/Library/ftiff/SophosInstall/Sophos Installer.app/Contents/MacOS/Sophos Installer --install'… ERROR: /Library/ftiff/SophosInstall/Sophos Installer.app/Contents/MacOS/Sophos Installer --install
If I understand correctly, I should get a status code != 0 in post install, then policy should fail!
Posted on 01-12-2016 01:49 AM
@ftiff I presume this is 9.8.2 you're on?
Well:
Policy status determined by checking script output for "error" and "fail"—The JSS no longer determines the status of a policy by checking script output for the words "error" and "fail". As of v9. 82, the JSS now only uses error codes to determine the status of a policy. If you have written scripts that utilize this functionality, it is recommended that you consider implementing an alternative solution using error codes as soon as possible. If you need assistance or have questions, contact your Technical Account Manager.
Can you remove the exit 0 statement from the end of the script?
Posted on 01-12-2016 03:00 AM
Thanks a lot @bentoms !
However this is not working. I worked with @owen. It seems the policy is marked as "Completed", whatever the script output / installer return status is.
Here's how to reproduce:
1. download https://www.dropbox.com/s/wy7n4mrdz12t8ds/DummyExitFail-1.7.pkg?dl=0
2. create a policy, attach DummyExitFail-1.7.pkg to it
When executed on client computer, you should get an error.
If I use sudo installer -pkg DummyExitFail-1.7.pkg -target /
it also fails.
You can get the return code with echo $?
which is set to 1 (=Failed)