@beeboo That is what we do now. Gets old uploading a new package every week. Need to get an AutoPKG workflow set up at some point.
My brain is not working right tonight. We don’t use SSO on our campus for Zoom, I’m not figuring out how to make this script work to install Zoom and update Zoom without needing admin credentials. How should the script look?
@kwoodard
This is what I use. We don't manage zooms preferences or settings at all. Just want the people who are using it to have the newest version.
#!/bin/bash
#https://www.jamf.com/jamf-nation/third-party-products/files/1051/install-latest-zoom-client
# this is the full URL
url="https://zoom.us/client/latest/ZoomInstallerIT.pkg"
# change directory to /private/tmp to make this the working directory
cd /private/tmp/
# download the installer package and name it for the linkID
/usr/bin/curl -JL "$url" -o "ZoomInstallerIT.pkg"
# install the package
/usr/sbin/installer -pkg "ZoomInstallerIT.pkg" -target /
# remove the installer package when done
/bin/rm -f "ZoomInstallerIT.pkg"
exit 0
@strayer Thank you for this. This won't prompt for admin credentials?
@kwoodard They won't need admin credentials to run this. Zoom will still probably ask for admin credentials when it needs to update, but the lazy approach would be to put this into Self Service and say "When it prompts you, install it from Self service again."
The not lazy approach would be to set up patch management for Zoom, and scope a policy that runs this regularly on all computers and exclude those with the latest version of zoom installed.
I've done both for different applications so no judgement here.
@strayer You can set patch management to run a script, or are you saying to have the script setup in Self Service to run on demand?
I am running your script @strayer and it will grey out these options. Same with the first script posted in this post. I roll out zoom at enrollment and i dont have those keys set so they are not greyed out when first installing. Any ideas?

@kwoodard For Zoom I just use patch management to track it and create smart groups for scoping. So I have that policy scoped to all users with Zoom installed, and excluded from users with the latest version.
@lamador I really have no idea, sorry. that script just gets zoom bare bones and installs. It may need additional things enabled in system preferences>Security & Privacy? We don't really use zoom at all, we just want it up to date because everyone installed it anyway due to covid...
@GregE
Any idea why when I try and run any of the versions you posted I get this error?
line 61: [: too many arguments
@Tjernigan line 61 for me is # Get the version number of the currently-installed Zoom, if any.
Presuming you've removed a line somewhere and it's the if statement on line 62, check the space around the opening and closing [ ] (I've been caught out by that before).
Ugh, anyone seeing that Zoom is downgrading clients on certain versions of MacOS? I'm testing Zoom on a 10.15.5 machine right now, running the newest version of Zoom, and it comes up with a note across the top of the app saying you should "upgrade" to a compatible version, but if I try to do so it tries to downgrade Zoom. I'm not finding much in the way of details except for an obscure Reddit conversation from a couple weeks ago which mentions they're seeing this behaviour without knowing why.
Thanks to OP for the script — extremely helpful. I've modified a bit for my organization's use and figured I'd post my modified version here in case it's useful for anyone. In the management plist, I have locked the following settings:
- remember the last login type
- display the 'call room' button on app home screen, for use in video conferencing rooms
- allow user to update through app (Zoom menu > Check for update)
- set web domain (set to dummy domain in script below — set your org's custom Zoom domain or remove depending on how you use Zoom)
- pre-configure SSO url (set to dummy SSO URL below)
- default to login with SSO
And set the following are set as package recommends (app defaults that the user can change)
- enable meeting reminders
- disable auto-fullscreen when screensharing is started
Note that all of the settings above, plus all other available settings, are described in this Zoom kbase: https://support.zoom.us/hc/en-us/articles/115001799006-Mass-Deployment-with-Preconfigured-Settings-for-Mac
The only other substantial changes to the script are to make a it a bit more verbose. It now checks if Zoom is running, or if a meeting is running, prints that, and exits successfully if the install was successful, but not applied. Zoom prompts the user with the attached pop-up when an update has been installed but not applied, so I still exit successfully in those cases; only if the update fails do I exit with a failure, and in that case I print the Zoom install log to try to help diagnose the issue.

Here's the script
#!/bin/sh
#####################################################################################################
#
# ABOUT THIS PROGRAM
#
# NAME
# ZoomInstall.sh -- Installs or updates Zoom
#
# SYNOPSIS
# sudo ZoomInstall.sh
#
####################################################################################################
#
# HISTORY
#
# Version: 1.1sa
# Updated by mw for use at SA 10/12/20
# via https://www.jamf.com/jamf-nation/discussions/29561/script-to-install-update-zoom
#
# 1.1 - Shannon Johnson, 27.9.2019
# Updated for new zoom numbering scheme
# Fixed the repeated plist modifications
#
# 1.0 - Shannon Johnson, 28.9.2018
# (Adapted from the FirefoxInstall.sh script by Joe Farage, 18.03.2015)
#
####################################################################################################
# Script to download and install Zoom.
# Only works on Intel systems.
# choose language (en-US, fr, de)
lang=""
# CHECK TO SEE IF A VALUE WAS PASSED IN PARAMETER 1 AND, IF SO, ASSIGN TO "lang"
if
"$4" != "" ] && m "$lang" == "" ]; then
lang=$4
else
lang="en-US"
fi
#Variables
pkgfile="ZoomInstallerIT.pkg"
plistfile="us.zoom.config.plist"
ZoomLog="/Library/Logs/zoomusinstall.log"
zoom_test=`ps aux | grep zoom.us | grep -v grep`
#checks if the cpthost process is running; if so, a meeting is active on the device
meeting_test=`ps aux | grep cpthost | grep -v grep`
# Are we running on Intel?
if
'`/usr/bin/uname -p`'="i386" -o '`/usr/bin/uname -p`'="x86_64" ]; then
## Get OS version and adjust for use with the URL string
OSvers_URL=$( sw_vers -productVersion | sed 's/ .]/_/g' )
## Set the User Agent string for use with curl
userAgent="Mozilla/5.0 (Macintosh; Intel Mac OS X ${OSvers_URL}) AppleWebKit/535.6.2 (KHTML, like Gecko) Version/5.2 Safari/535.6.2"
# Get the latest version of Reader available from Zoom page.
latestver=`/usr/bin/curl -s -A "$userAgent" https://zoom.us/download | grep 'ZoomInstallerIT.pkg' | awk -F'/' '{print $3}'`
# Get the version number of the currently-installed Zoom, if any.
if -e "/Applications/zoom.us.app" ]; then
currentinstalledver=`/usr/bin/defaults read /Applications/zoom.us.app/Contents/Info CFBundleVersion | sed -e 's/0 //g' -e 's/(//g' -e 's/)//g'`
if ${latestver} = ${currentinstalledver} ]; then
echo "Zoom is up-to-date. Exiting."
exit 0
fi
else
currentinstalledver="none"
echo "Zoom is not installed..."
fi
url="https://zoom.us/client/${latestver}/ZoomInstallerIT.pkg"
# Compare the two versions, if they are different or Zoom is not present then download and install the new version.
if "${currentinstalledver}" != "${latestver}" ]; then
# Construct the plist file for preferences
echo "<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>LastLoginType</key>
<true/>
<key>appendcallernameforroomsystem</key>
<true/>
<key>enablestartmeetingwithroomsystem</key>
<true/>
<key>ZAutoUpdate</key>
<true/>
<key>setwebdomain</key>
<string>$CustomZoomDomain</string>
<key>enableembedbrowserforsso</key>
<true/>
<key>ZSSOHost</key>
<string>$SSODomain</string>
<key>ZAutoSSOLogin</key>
<true/>
<key>PackageRecommend</key>
<dict>
<key>EnableRemindMeetingTime</key>
<true/>
<key>ZAutoFullScreenWhenViewShare</key>
<false/>
</dict>
</dict>
</plist>" > /tmp/${plistfile}
# Download and install new version
/bin/echo "Installed Zoom version: ${currentinstalledver}"
/bin/echo "Current Zoom version: ${latestver}"
/bin/echo "Downloading current version..."
/usr/bin/curl -sLo /tmp/${pkgfile} ${url}
/bin/echo "Installing Zoom ${latestver}..."
/usr/sbin/installer -allowUntrusted -pkg /tmp/${pkgfile} -target /
/bin/sleep 20
/bin/echo "Deleting Zoom installer..."
/bin/rm /tmp/${pkgfile}
#double check to see if the new version got updated
newlyinstalledver=`/usr/bin/defaults read /Applications/zoom.us.app/Contents/Info CFBundleVersion`
if "${latestver}" = "${newlyinstalledver}" ]; then
/bin/echo "SUCCESS: Zoom has been updated to version ${newlyinstalledver}"
# /Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType hud -title "Zoom Installed" -description "Zoom has been updated." &
else
if i "$meeting_test" != "" ]] ; then
/bin/echo "Zoom update failed to apply because the user is currently in a meeting..."
/bin/echo "Zoom will prompt user to restart the app to apply update. Exiting..."
exit 0
elif li "$meeting_test" == "" ]] && mp "$zoom_test" != "" ]] ; then
/bin/echo "Zoom update failed to apply because Zoom is currently open..."
/bin/echo "Zoom will prompt user to restart the app to apply update. Exiting..."
exit 0
else
/bin/echo "ERROR: Zoom update unsuccessful, version remains at ${currentinstalledver}."
/bin/echo "Printing Zoom install log..."
/usr/bin/tail -n 30 "$ZoomLog"
exit 1
fi
fi
# If Zoom is up to date already, just log it and exit.
else
/bin/echo "Zoom is already up to date, running ${currentinstalledver}."
fi
else
/bin/echo "ERROR: This script is for Intel Macs only."
fi
exit 0
I found the check box for "User dual monitors" is greyed out. I've bene told using ZDualMonitorOn would do the trick. Unless I'm doing it wrong, I've had no luck at making it not greyed out. Any ideas?
Here's part of the code

# Construct the plist file for preferences
echo "<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>nogoogle</key>
<string>1</string>
<key>nofacebook</key>
<string>1</string>
<key>ZDisableVideo</key>
<true/>
<key>ZAutoJoinVoip</key>
<true/>
<key>ZAutoUpdate</key>
<key>PackageRecommend</key>
<dict>
<key>ZDualMonitorOn</key>
<true/>
</dict>
</plist>" > /tmp/${plistfile}
if [ "${ssohost}" != "" ]; then
echo "
<key>ZAutoSSOLogin</key>
<true/>
<key>ZSSOHost</key>
<string>$ssohost</string>" >> /tmp/${plistfile}
fi
echo "<key>ZAutoFullScreenWhenViewShare</key>
<true/>
<key>ZAutoFitWhenViewShare</key>
<true/>" >> /tmp/${plistfile}
if [ "${hdvideo}" == "true" ]; then
echo "<key>ZUse720PByDefault</key>
<true/>" >> /tmp/${plistfile}
else
echo "<key>ZUse720PByDefault</key>
<false/>" >> /tmp/${plistfile}
fi
echo "<key>ZRemoteControlAllApp</key>
<false/>
</dict>
</plist>" >> /tmp/${plistfile}
Get rid of the <dict> above and indents for that key.
@erichughes so like this, correct?
# Construct the plist file for preferences
echo "<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>nogoogle</key>
<string>1</string>
<key>nofacebook</key>
<string>1</string>
<key>ZDisableVideo</key>
<true/>
<key>ZAutoJoinVoip</key>
<true/>
<key>ZAutoUpdate</key>
<key>PackageRecommend</key>
<key>ZDualMonitorOn</key>
<true/>
</dict>
</plist>" > /tmp/${plistfile}
if [ "${ssohost}" != "" ]; then
echo "
<key>ZAutoSSOLogin</key>
<true/>
<key>ZSSOHost</key>
<string>$ssohost</string>" >> /tmp/${plistfile}
fi
echo "<key>ZAutoFullScreenWhenViewShare</key>
<true/>
<key>ZAutoFitWhenViewShare</key>
<true/>" >> /tmp/${plistfile}
if [ "${hdvideo}" == "true" ]; then
echo "<key>ZUse720PByDefault</key>
<true/>" >> /tmp/${plistfile}
else
echo "<key>ZUse720PByDefault</key>
<false/>" >> /tmp/${plistfile}
fi
echo "<key>ZRemoteControlAllApp</key>
<false/>
</dict>
</plist>" >> /tmp/${plistfile}
Answered my own question, maybe. Ran it that way and it did not un-grey itself
That looks more correct. But I don't know anything about that specific key. We don't manage Zoom, just make it available if needed. That item is not grayed out for me, but I'm not deploying a plist for Zoom. Do the other keys work as expected with your deployed plist?
@erichughes I believe so, I'll need to double check. I did see this post which I might try out. The thing I love about this script is it downloads the latest package for us. Which I guess we can still do, just take the the plist stuff?
We use the basics of this script to instal for users who request Zoom and the also to keep them up to date. Static group scoped to a policy for install and a smart group that compares versions via EA, scoped to policy to keep them updated. When / If they ever execute it in Self Service.
We don't manage Zoom at all, people can use it if they wish. I suck at scripting and have been trying to get a script that will merely run in the background (preferably at startup when nothing is launched), check the version to see if it needs to be updated, and updates it without the user needing to know or add in admin credentials (which they don't have) to get things to install.
Messing with patch management, AutoPKG, auto uploading to the JSS... All this is a foreign language. It also seems that AutoPKG is no longer being updated? Am I missing something there? Working from home, I have to remote into my on-site computer to get apps uploaded and do a lot of the Jamf management. I can do some things via the web interface, but being that we only have on-prem, its hard to get some stuff done. I'm trying to script as much as I can to do things.
Hi @kwoodard
I moved to JamfCloud today so feeling happy and thought I'd contribute to Jamfnation.
I can read some scripts and modify some and understand there is always more to learn.
I use the install script from this thread to deploy Zoom
The script is very slightly modified, and in the script I
#!/bin/sh
# out few lines
# and put some notes into the script
# and reference this thread
# and change the script very so slightly
I have few policies for Zoom.
Zoom: Main Install Policy Frequency: ongoing, Trigger: superdupernametriggerhere Scope: All computers
(this is the policy that does the legwork)
Zoom: Install (Auto Install) Frequency: ongoing, Trigger: login Scope: (computers that are supposed to have Zoom installed)
Zoom: Install (Force Update) Frequency: ongoing, Trigger, login, startup Scope: (smartgroup that has app install zoom but is not at version X)
I know this is not the best way to go about it but I understand I need to learn and there is a better way, the better way is to have application install but at version less than xyz as an example but I need to learn regex
Zoom: Install (UPdate) via Self Service) Frequency: Ongoing Trigger: Self Service Scope: (smart group of application installed zoom)
^^ This is a policy users may choose to run if they want to update to latest version on their own ^^
As a side note, another app I download from the internet is Google Chrome while the majority is packaged with a few sprinkled from the Mac App Store.
zoom_test=`ps aux | grep zoom.us | grep -v grep`
#checks if the cpthost process is running; if so, a meeting is active on the device
meeting_test=`ps aux | grep cpthost | grep -v grep`
@msw-sa That is a little beauty, have updated my Google Chrome script for updating the .plist to whitelist our domain using the above - cheers!
@KCouture not sure constructing your plist like that will work. The first section prints creates plist file, and closes the </dict> and </plist> tags. All the subsequent echo commands will add keys outside the dict and plist, which I expect would fail. You can check console in /Library/Logs/zoominstall.log to confirm. If you don't see "plutil result: /tmp/us.zoom.config.plist: OK" in the log, or see anything about there being a problem with the plist, it's not properly formatted and won't apply those settings. I'm not really sure the purpose of making conditionals for adding plist keys — I would recommend putting your whole plist in the first echo. If for some reason you need to do it with the conditionals, you could possibly do it with a defaults write command, but again not sure why you'd bother.
You've almost got the package recommends, just add 1 tab before the key, and the true, like so
<key>PackageRecommend</key>
<key>ZDualMonitorOn</key>
<true/>
</dict>
</plist>
@atomczynski Just a general recommendation, wouldn't lean so heavily on startup and login triggers, particularly startup, for installing software. There won't be an internet connection right away, if anything running requires a user there won't be one logged in, etc. As for using a login a trigger, that policy will run each new login, but also each screen unlock if you manage screensavers/require screens to lock after X amount of time, or if users enable those settings themselves; recurring check-in with an execution frequency of weekly might be cleaner.
@kwoodard I would read this post earlier in the thread, https://www.jamf.com/jamf-nation/discussions/29561/script-to-install-update-zoom#responseChild200720, and review the Zoom article I linked that explains the plist options, to achieve that functionality. Anything installed by jamf runs as root so the user won't need admin credentials. See my note above about using the startup trigger — again would recommend a recurring check-in with a weekly frequency for something more lightweight and reliable.
@msw-sa
Good catch!
Thanks.
I looked at the policy some more and I actually have an exclusion built into the policy so the Auto Installer does not run on computers with the app installed.
Here is what I came up with. Can you all look it over to see if I missed anything? All I am needing to do is install Zoom, update Zoom, and not need admin credentials to do it.
#!/bin/bash
#https://www.jamf.com/jamf-nation/third-party-products/files/1051/install-latest-zoom-client
# this is the full URL
url="https://zoom.us/client/latest/ZoomInstallerIT.pkg"
# change directory to /private/tmp to make this the working directory
cd /private/tmp/
# download the installer package and name it for the linkID
/usr/bin/curl -JL "$url" -o "ZoomInstallerIT.pkg"
# install the package
/usr/sbin/installer -pkg "ZoomInstallerIT.pkg" -target /
# remove the installer package when done
/bin/rm -f "ZoomInstallerIT.pkg"
exit 0