In-Place macOS Sierra Upgrade Script

New Contributor III


I am trying to follow this guide from JAMF:

I am using the script noted here:

I got everything else working so far (you do need another policy to place the .dmg in the applications folder that the article neglects to tell you). I would like the script to force the restart instead of being "soft". I tested it and found that any open application will stop the upgrade.

Just need it to forcibly and immediately preform the restart.


Here is the script:

/Applications/Install macOS --applicationpath "/Applications/Install macOS" --volume $1 --rebootdelay 30 --nointeraction
killall "Self Service"
126 REPLIES 126

Valued Contributor

With 10.12.4 Updater Apple changed some things with startosinstall:
--volume argument is not needed.

On OS X 10.11.6:
--volume is not a valid option if you run on a OS X 10.11 Mac and command will fail.
Upgrade tool works fine without --volume argument

On OS X 10.8.5:
--volume available on 10.8
Upgrade command doesn't work properly (error: Helper tool creashed)
To get it working you need to open the Installer app once via GUI and then run the command.
We have an active AppleCare Enterprise Services case about this.

To get 10.12.4 upgrade working via scripted method we have to do 2 things:
1. Let it open the installer app and close quickly.
2. Run the startosinstall command with no --volume argument.

# All Glory and Thanks to Jesus!

macOSinstallerAppPath="/Applications/Install macOS"

CurrentloggedInUser=$(/usr/bin/python -c 'from SystemConfiguration import SCDynamicStoreCopyConsoleUser; import sys; username = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0]; username = [username,""][username in [u"loginwindow", None, u""]]; sys.stdout.write(username + "

# There was an issue with startosinstall command that "Install" needs to be opened once by logged in user to get it working properly
effectiveUserID=$(/usr/bin/id -u "$CurrentloggedInUser")
/bin/launchctl asuser "$effectiveUserID" sudo -u "$CurrentloggedInUser" /usr/bin/osascript <<EOT
        tell application "${macOSinstallerAppPath}" to activate
# Wait for 5 seconds to settle down then quit the app
/bin/sleep 5
/bin/launchctl asuser "$effectiveUserID" sudo -u "$CurrentloggedInUser" /usr/bin/osascript <<EOT
        tell application "${macOSinstallerAppPath}" to quit

# Run upgrade command
"${macOSinstallerAppPath}/Contents/Resources/startosinstall" --applicationpath "${macOSinstallerAppPath}" --rebootdelay 30 --nointeraction

# Reboot immediately if it has not rebooted by 'startosinstall'
/usr/local/jamf/bin/jamf reboot -background -immediately

exit 0

Apple also changed the way how Internet Recovery works.
Initial Internet Recovery will recover to the macOS it came with and once you have upgraded to macOS 10.12.4 the next Internet Recovery attempt will recover to 10.12.4 instead of the OS it came with.

New Contributor III

@Rosko , Josh, I showed Leslie last week what we are trying to do with the installer. We noticed that when we use the script in a policy then as a executed command (Files and Processes) it will not complete because it can't not close open applications.

We have a policy that downloads the installer and the script into /Users/Shared/ then a second that Executes the bash script.

What would be your preferred method of sending a killall command to the machine? User script in the same policy?

Contributor II
Contributor II

@VladCabrera As it sounds like the workflow has been modified, I really can't speak entirely too it without seeing it. But you shouldn't have to do a killall since there should be a & at the end of the line that calls the startosinstall in the script like this /Users/Shared/Install macOS --applicationpath /Users/Shared/Install macOS --nointeraction --pidtosignal $jamfHelperPID &.

This ensure that the macOS Sierra Installer will run as a background process and not "hold up" the script.

Valued Contributor II

My policy and script script are working fine. However, when the 10.12.5 Install macOS starts (from /Applications folder) I get this error below.

Is it booting/installing from the wrong volume?


Has anyone seen this before?

Valued Contributor

I got the 10.12.4 installer to work using Rosko's vanilla workflow. Using the 10.12.5 installer I kept seeing the following errors in the policy log:

"/Users/Shared/Install macOS" --applicationpath "/Users/Shared/Install macOS" --nointeraction By using the agreetolicense option, you are agreeing that you have run this tool with the license only option and have read and agreed to the terms. If you do not agree, press CTRL-C and cancel this process immediately. Error: __28-[OSISClient targetForPath:]_block_invoke, Couldn’t communicate with a helper application. Error: could not find target... Helper tool creashed...

In the system's install.log I saw this:

osinstallersetupplaind[2321]: Multiple clients attempting to connect to osinstallersetupd

So I added this bit of code before the startosinstall command

/usr/bin/killall osinstallersetupplaind
/bin/sleep 2

This seems to resolve the issues I had

Valued Contributor II

This post by @jbourdon did the trick for me.

New Contributor

Let me start out by saying that we're not a jAMF shop yet, trying to convince my bosses to go this route.

What I ended up doing was creating a payload-free package, with the Sierra Installer App in the Scripts folder along with a few other bits.

The postinstall script looks like this:


WORKDIR=$(dirname $0)
APP="$WORKDIR/Install macOS"

if [[ -d "$APP" ]]; then
    logger -s "Starting  Sierra InPlace Upgrade..."

     "$APP/Contents/Resources/startosinstall" --applicationpath "$APP" --agreetolicense --rebootdelay 10 --nointeraction
     sleep 5

     logger -s "Shutting Down osinstallersetupd Process.."
     sudo killall "osinstallersetupd" 2>/dev/null

     logger -s "Beginning Authenticated Reboot..."
     /usr/bin/fdesetup authrestart -inputplist < "$WORKDIR/authrestart.plist"
    logger -s "$APP not found.  Aborting..."
    exit 1

exit 0

We have a full-screen Cocoa app I created, that prevents the user from interacting with the system while the initial steps are taking place (think jAMF helper). This effectively blocks any soft-reboot from startosinstall. Apparently, when it reaches the stage where the rebootdelay kicks in, startosinstall is already done and the postinstall moves on to the next item in the script.

At that point, we perform an authenticated reboot ourselves, which will sigkill all running applications.

Since the installer binary unpacks the package to a temp directory and then cleans up after it's done, we don't have to bother with removing the macOS Sierra Installer app, or the plist used to do the authreboot.

Just wanted to share this alternate approach, since I've learned a lot from the members of this forum!


New Contributor III

Has anyone experienced with the 10.12.5 installer that some machines will run the startosinstall prep the drive but when it restarts it will boot back to the old OS. In other words, the upgrade will not run during the reboot. I have tested with just the startosinstall command and switches.

Running command /Users/Shared/Install macOS --applicationpath "/Users/Shared/Install macOS" --nointeraction...
Result of command:
By using the agreetolicense option, you are agreeing that you have run this tool with the license only option and have read and agreed to the terms.
If you do not agree, press CTRL-C and cancel this process immediately.
Preparing to run macOS Installer...
Preparing 1.492537...
Preparing 1.492537...
Preparing 1.492537...
Preparing 1.492611...
Preparing 2.388166...
Preparing 3.283721...
Preparing 4.179275...
Preparing 5.074830...
Preparing 5.970384...
Preparing 6.865939...
Preparing 7.761493...
Preparing 8.657048...
Preparing 9.552602...
Preparing 10.448157...
Preparing 11.343711...
Preparing 12.239266...
Preparing 13.134821...
Preparing 14.030375...
Preparing 14.925930...
Preparing 15.821484...
Preparing 16.717039...
Preparing 17.612593...
Preparing 18.508148...
Preparing 19.403702...
Preparing 20.299257...
Preparing 21.194811...
Preparing 22.090366...
Preparing 22.985921...
Preparing 23.881475...
Preparing 24.777030...
Preparing 25.672584...
Preparing 26.568139...
Preparing 27.463693...
Preparing 28.359248...
Preparing 29.254802...
Preparing 30.150357...
Preparing 31.045911...
Preparing 31.941466...
Preparing 32.837020...
Preparing 33.732575...
Preparing 34.628130...
Preparing 35.523684...
Preparing 36.419239...
Preparing 37.314793...
Preparing 38.210348...
Preparing 39.105902...
Preparing 40.001457...
Preparing 40.897011...
Preparing 41.792566...
Preparing 42.688120...
Preparing 43.583675...
Preparing 44.479230...
Preparing 45.374784...
Preparing 46.270339...
Preparing 47.165893...
Preparing 48.061448...
Preparing 48.957002...
Preparing 49.852557...
Preparing 50.748111...
Preparing 51.643666...
Preparing 52.539220...
Preparing 53.434775...
Preparing 54.330329...
Preparing 55.225884...
Preparing 56.121439...
Preparing 57.016993...
Preparing 57.912548...
Preparing 58.808102...
Preparing 59.703657...
Preparing 60.599211...
Preparing 61.494766...
Preparing 62.390320...
Preparing 63.285875...
Preparing 64.181429...
Preparing 65.076984...
Preparing 65.972539...
Preparing 66.868093...
Preparing 67.763648...
Preparing 68.659202...
Preparing 69.554757...
Preparing 70.450311...
Preparing 71.345866...
Preparing 72.241420...
Preparing 73.136975...
Preparing 74.032529...
Preparing 74.928084...
Preparing 75.823638...
Preparing 76.719193...
Preparing 77.614748...
Preparing 78.510302...
Preparing 79.405857...
Preparing 80.301411...
Preparing 81.196966...
Preparing 82.092520...
Preparing 82.988075...
Preparing 83.883629...
Preparing 84.779184...
Preparing 85.674738...
Preparing 86.570293...
Preparing 87.465848...
Preparing 88.361402...
Preparing 89.256957...
Preparing 90.152511...
System going down for install...

The machine reported back in with having 10.10 installed.

Contributor II

@VladCabrera yes we are seeing this also. It seems to work. When you run the script a second time.

New Contributor III

@a.stonham Any thoughts as to why that happens. I'm reviewing the log from the time that the installation started and comparing it to one that I ran the installer manually. Thus far nothing is jumping out at me.

Valued Contributor II

Let me just say that it is COMPLETELY RIDICULOUS that Jamf has not updated their built-in reboot options to support macOS Sierra upgrades. Sierra has been out for almost a year, and ever since 10.12.4 this functionality is BROKEN. So much for zero day support, eh guys?

I'm sure they will blame Apple... Tell you what, you guys are the device management system which Apple pretty much suggests that customers go with, yet there are many many MANY open PIs which affect core functionality. Even Munki has a workflow which works for Sierra upgrades. We CANNOT wait for 10 for the multitude of things which are currently broken to be fixed. It looks bad for Jamf when we have to try to hack around what used to be standard and streamlined processes.


@dgreening In all fairness, Apple has changed the upgrade utility a few times. That being said, Jamf should be well aware of these changes in advance, considering their supposed partnership with Apple.

New Contributor

Second what @seann said!!! We should not have to use bubble gum and bailing wire to get this working.


Anyone got this working with the 10.12.6 installer?

Honored Contributor

@Kyuubi Gotten what working? There's a few methods/scripts that have been proposed that from what I can tell continue to work with 10.12.6 assuming they've been maintained for the changes that Apple made in 10.12.4.


Sorry @bpavlov I didn't read all the posts before i posted. I was thinking that people were still using the old way of stripping the installOSX from the instead of using the I'll go back to reading now.

Valued Contributor III

@Rosko I have a question. I am looking to have the machine immediately run a recon command after it reboots after the upgrade. Is there a way to trigger this by injecting a line in the post install script? Or in the launchDaemon?
Also it seems the version check is broken so I had to hash out all the lines of code performing the check and re download of the installer. Otherwise script is working great. I just need it to update inventory and run a few other policies on the 1st boot after it upgrades (or have them run on first login after that, but since it doesn't know it has 10.12.6 yet it makes it hard to find a good scope).
Gabe Shackney
Princeton Public Schools

Gabe Shackney
Princeton Public Schools

Valued Contributor II

Contributor II
Contributor II

@gshackney It would have to be a launchDaemon that gets deployed in order to do a post-reboot recon. And @dan.snelson 's script looks good. The only thing I might do is instead of waiting 300 seconds, use the jamf checkJSSConenection verb to check if the machine is able to establish a connection to the JSS or not. If not, have it wait another 3-5 seconds.

Also, @dgreening, @seann, @WUSLS, @Kyuubi, @bpavlov and anyone else interested in native (Jamf) in-place upgrades, check out the beta of Jamf Pro v9.101. Also, if you are using VPP, you can deploy the macOS Installer that way as well, however you are not able to pre-cache it using this method so a caching server is highly recommended for mass-deployments.

Valued Contributor III

@dan.snelson @Rosko Thanks!
I'll play with this piece. I didn't scan through it too much, does the daemon delete itself after running? Also does it skip running until after the os upgrade reboots into itself once? I basically want to trigger the recon then once the JSS sees that it has run the upgrade policy and now has the new os, then I will have some policies run based on that.
Gabe Shackney
Princeton Public Schools

Gabe Shackney
Princeton Public Schools

Valued Contributor II

@gshackney Yes, it self-destructs:

# Delete launchd plist
ScriptLog "* Delete $plistLabel.plist ..."
/bin/rm -fv /Library/LaunchDaemons/$plistLabel.plist

# Delete script
ScriptLog "* Delete script ..."
/bin/rm -fv /path/to/client-side/scripts/

Here's the way we're deploying the script:

Valued Contributor II

Initial results look good for macOS High Sierra 10.13 Beta (17A360a):

/Applications/Install macOS High Sierra --applicationpath "/Applications/Install macOS High Sierra" --converttoapfs YES --rebootdelay 30 --nointeraction

New Contributor II

I executed this script:

after confirming macbook is plugged in to power and has enough disk space, i'm getting this screen:

'please wait as we prepare your computer for macos sierra....

this process will take ~5-10mins. once completed your computer will reboot and begin the upgrade.'

it's been on the same screen > 30mins and has not rebooted. did something go wrong? am i missing something?

thanks for any assistance

Honored Contributor

@dan.snelson You don't need --converttoapfs YES as it will automatically convert if the hardware supports it. That's been my experience in VMs anyways. Has your testing had different results?

Contributor III

Hi All,
Does anybody have suggestions on modifying Josh's script ( to force a reboot? The soft reboot just isn't cutting it for us - seems there's always an app open and then the reboot just doesn't happen. Timing-wise I'm just not sure where to drop the reboot now command. Any ideas?


Honored Contributor

Try adding shutdown -r now in the line after it finishes running the startosinstall command.

New Contributor II

@Rosko I've been trying to get the script to run and keep getting this error:

Launching jamfHelper as FullScreen...
Launching startosinstall...
Error: __28-[OSISClient targetForPath:]_block_invoke, Couldn’t communicate with a helper application.
Error: could not find target...
By using the agreetolicense option, you are agreeing that you have run this tool with the license only option and have read and agreed to the terms.
If you do not agree, press CTRL-C and cancel this process immediately.

I'm trying to run it as a recurring check-in policy instead of a Self Service policy, but it gets the same error in Self Service, too. I'm trying this on 10.9.5. Any thoughts?

Contributor II
Contributor II

Hello @mrhollywoodgates -

I have not seen this error before...has the script been modified? Also, please be sure to right-click and download the .sh file and not copy paste from the browser as that can sometimes throw in some hidden characters. Otherwise if the script hasn't been modified, I would try running the script locally on the target system and see if you get the same issue. If you continue to get the same issue its usually best to run the script line-by-line to see exactly where the problem is. Based on the what you've provided I'm assuming the script is failing when calling the startosinstall binary.

Also, are you removing all the calls for jamfHelper? Are you able to provide a copy of the script?

New Contributor II

@Rosko I have not modified the script except for the user variables. I did a lot of testing and reading other posts, and what ended up working for me was a suggestion someone had about having to launch the Installer app as the logged-in user before running it via script. I added this to the script and now it works as expected. I also changed the installer app variables to hard paths as part of troubleshooting. I've now tested it on 10.9 and 10.10 and it works on both platforms.

##Begin Upgrade
    /bin/echo "Launching startosinstall..."
    consoleUser=`ls -l /dev/console | cut -d " " -f4`
    effectiveUserID=$(/usr/bin/id -u "$consoleUser")
    /bin/launchctl asuser "$effectiveUserID" sudo -u "$consoleUser" /usr/bin/open /Applications/Install macOS
    sleep 5
    /bin/launchctl asuser "$effectiveUserID" sudo -u "$consoleUser" osascript -e 'quit app "Install macOS Sierra"'
    /Applications/Install macOS --applicationpath "/Applications/Install macOS" --nointeraction --pidtosignal $jamfHelperPID &
    /bin/sleep 3

Contributor II
Contributor II

@mrhollywoodgates I am glad you were able to solve the problem. I have heard of some folks needing to do this, however I have not been able to duplicate the need to launch the app and then close it, nor do many of the customers we have using this workflow have had to do this, so I don't really know what is causing it. But thanks again for the feedback and the solution. I will keep it in mind in the future if someone else should have the issue.

Have a great day!

Contributor III

@Rosko Sir, can you be so kind to give me an example that you can add in the beginning of your script that can do a User Files Clean up, user keychain clean up, and flush policy history. And maybe a Prompt to change Computername before the Upgrade executes? I am thinking of just using the Self Service for summer machine refresh. Since Jamf Pro 10 can do 3rd Party Patch update, and the super useful MAU Caching Server and AUSTT, there is no need for us to reimage machines during summer roll outs. Plus we cannot image anymore anyways because of High Sierra.


I've been testing this for High Sierra upgrades, first two worked OK, then I had "could not find target" errors.

<br/>Error: could not find target...<br/>By using the agreetolicense option, you are agreeing that you have run this tool with the license only option and have read and agreed to the terms.<br/>If you do not agree, press CTRL-C and cancel this process immediately.<br/>

Turns out that you can't do this while FileVault is doing it's initial encryption.

"You may not install to this volume because it is currently converting to Core Storage."

Contributor III

I just tested the VPP --> self-service workflow for the 10.13.0 macOS High Sierra upgrade.

As predicted it asked for an administrator username and password before starting the installation.

Is there a solution that allows for this workflow without requiring the admin credentials?

Esteemed Contributor III

Really wish Apple would give a command similar to this, but for macOS upgrades:

sudo softwareupdate --background-critical

New Contributor III


Thanks for the upgrade script. It's working great. I do have one request, can you add a:

diskutil verifyVolume (bootdisk)

I had one upgrade that failed and showed errors upon running this. I'm pretty sure it was a pre-exisiting condition. It would be great if the script halted if the diskutil finds errors.

Thank you!

New Contributor II

Fixed My Issue:

New Contributor II


just want to share what I have found. I want to be as close as possible to the standard install process. Solution like mentioned above to launch the Install App once and quit it after some seconds feels not like a nice solution...
For those that still have the problem with FV2 enabled machines and the auth restart via startosinstall. I figured out, that on the first launch of the High Sierra Installer app, Apple launches a LaunchAgent with a mach service "". So why not launch this agent for our own in our workflow. I submitted the LaunchAgent to launchd and then started the installation via startosinstall. Auth restart process works as expected. Cool!

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "">
<plist version="1.0">
        <string>/Applications/Install macOS High</string>

Try it yourself ...

New Contributor II


I have stripped down everything but the startosinstall commands and still having an issue

I installed the app in Shared/ and called it from there with this:

sudo /Users/Shared/Install macOS --applicationpath "/Users/Shared/Install macOS" --nointeraction

I get a long 'Preparing 1.670' to a 'Preparing 89.093' and then the error System reboot failed.

I want to test it working from Terminal before moving to a policy... Any ideas? I am using 10.12.6 installer

Any help is much appreciated.


Valued Contributor

Wow, this is still a problem,time to start looking at jamJAR



Well spotted!

It turns out the Sierra v10.12.6 installer has the same file:

$ ls -l /Applications/Install macOS*
-rwxr-xr-x  1 root  wheel   76304 Jul 15 00:22 /Applications/Install macOS
-rwxr-xr-x  1 root  wheel  104272 Jul 15 00:22 /Applications/Install macOS

The interesting question: Will this work if no user is logged into the console?