macOS 12.4 and iOS 15.5

The updates for macOS 12.4, iOS 15.5 and all the siblings dropped yesterday. Usually I would gather a list of links for these updates in the news summary on Friday, but since I will be on a vacation break and they will seem stale in two weeks, you will get them now. Enjoy!

Update 2022-05-19: added Apple Business and School Manager User Guides.

macOS Monterey 12.4

iOS 15.5 and iPadOS 15.5

watchOS 8.6

tvOS 15.5

Other Updates

User Guides

Community

Support

Update Installomator: v9.2

We have updated Installomator. This brings Installomator to 465(!) applications! Many thanks to everyone who contributed.

Note: Both Google and Mozilla recommend using the pkg installers instead of the dmg downloads for managed deployments. So far, Installomator has provided labels for both. (googlechrome and googlechromepkgor firefox and firefoxpkg, respectively) Since there are problems with the dmg downloads, a future release of Installomator will disable the firefox and googlechrome dmg labels. You should switch to using the firefoxpkg or googlechromepkg labels instead.

  • bug and documentation fixes
  • 40 new, and 26 updated labels

You can find more details in the release notes.

Weekly News Summary for Admins — 2022-05-13

Last week I mentioned that Apple often releases a few things before WWDC, because they don’t fit in the keynote. I should have been careful what I wished for: the iPod touch — the last remnant of the iPod line — is being discontinued.


(Sponsor: Mosyle)

The only Apple Unified Platform for Business

Mosyle is the only solution that fully integrates Enhanced MDM, Endpoint Security, Internet Privacy & Security, Single Sign-On, and Application Management on a single Apple-only platform.

Click here to learn why Mosyle is all you need to work with Apple.


Like the discontinuation of macOS Server, this doesn’t come as much of a surprise. The main iPod line was discontinued in 2017. I wrote an article then, and I think it still holds up well.

The functionality of the iPod has been assimilated by the iPhone, Apple Watch, HomePod, and AirPods, all of which can now play your Music nearly anywhere, anytime. The iPod may be gone, but the Music lives on.

The news summary will be taking a short vacation break. It will resume in three weeks, on “WWDC Eve”, June 3, with a summary of everything else that happens between now and then. Let’s hope Apple is done with canceling products.

Never miss a post and get the weekly newsletter by email, you can subscribe to the Scripting OS X Weekly News Summary here!! (Same content, delivered to your Inbox once a week.)

News and Opinion

Social Media

  • Jack Rhysider: “If you’re in IT, I highly encourage you to write a blog. Here are 17 reasons why you should be blogging.” (Thread, if you start a Mac IT blog, be sure to let me know!)
  • William Smith: “For Jamf admins, ensure your configuration profiles with the Exchange (macOS) and Exchange ActiveSync (iOS) payloads are set to ‘Use OAuth for authentication’ before the October 1st deadline.”

Security and Privacy

Support and HowTos

Scripting and Automation

Apple Support

Updates and Releases

To Listen

Support

If you are enjoying what you are reading here, please spread the word and recommend it to another Mac Admin!

If you want to support me and this website even further, then consider buying one (or all) of my books. It’s like a subscription fee, but you also get a useful book or two extra!

Weekly News Summary for Admins — 2022-05-06

The month of May is like “advent for Apple fans.” WWDC is looming in a few weeks. Most of the dust from previous system releases has settled. Things have been fixed, or we have gotten used to the workarounds. Anticipation and dread for the next round of releases is rising. Sometimes, Apple even opens a door or two and releases something which didn’t fit in the keynote.


(Sponsor: Mosyle)

The only Apple Unified Platform for Business

Mosyle is the only solution that fully integrates Enhanced MDM, Endpoint Security, Internet Privacy & Security, Single Sign-On, and Application Management on a single Apple-only platform.

Click here to learn why Mosyle is all you need to work with Apple.


MacDevOps YVR have announced their speaker line-up for their virtual conference in June, and I am very proud to be among all these amazing speakers. You can still register for the event from June 15–17. You can also order MacDevOpsYVR 2022 t-shirts and hoodies!

Also the dates and location for this year’s Objective by the Sea were announced: It will go from October 3–7, in Spain, near Barcelona.

As always, I keep a list of conferences, their dates and other important links, such as calls for presentation and session video archives from previous conferences on my conferences page.

If you would rather get the weekly newsletter by email, you can subscribe to the Scripting OS X Weekly Newsletter here!! (Same content, delivered to your Inbox once a week.)

News and Opinion

Social Media

  • tlark: “ATTN MDM vendors. Please take a long good look at Munki, it is what IT admin/eng want. We don’t want complex systems that require GUI clicking. We just reduced our level of effort by ripping out third party app deployment/patching from our MDM and deployed Munki in AWS” (Thread)

Security and Privacy

Support and HowTos

Scripting and Automation

Updates and Releases

To Watch

To Listen

Support

If you are enjoying what you are reading here, please spread the word and recommend it to another Mac Admin!

If you want to support me and this website even further, then consider buying one (or all) of my books. It’s like a subscription fee, but you also get a useful book or two extra!

Launching Scripts #4: AppleScript from Shell Script

In the last post, we discussed how to run shell commands and scripts from an Apple Script environment. In this post, we will look at how we can run AppleScript commands and scripts from the shell environment.

Open Scripting Architecture

The key to running AppleScript from the shell is the osascript command. OSA is short for ‘Open Scripting Architecture’ which is the framework that powers AppleScript. This framework allows AppleScript to have its native language, but also use JavaScript syntax.

The osascript command allows us to run AppleScript commands from Terminal and shell. The most common use is the user interaction commands from AppleScript, like display dialog:

osascript -e 'display dialog "Hello from shell"'

The -e option tells osascript that it will get one or more lines of statements as arguments. The following argument is AppleScript code. You can have multiple -e options which will work like multiple lines of a single AppleScript:

> osascript -e 'display dialog "Hello from shell"' -e 'button returned of result'
OK

osascript prints the value of the last command to stdout. In this case, it is the label of the button clicked in the dialog. (The ‘Cancel’ button actually causes the AppleScript to abort with an error, so no label will be returned for that.)

When you have multiple lines of script, using multiple -e statements will quickly become cumbersome and unreadable. It is easier to use a heredoc instead:

osascript <<EndOfScript
   display dialog "Hello from shell"
   return button returned of result
EndOfScript

This also avoids the problem of nested quotation marks and simplifies shell variable substitution.

Shell variables and osascript

There are a few ways to pass data into osascript from the shell.

Since the shell substitutes variables with their value before the command itself is actually executed, this works in a very straightforward manner:

computerName=$(scutil --get ComputerName)

newName=$(osascript -e "text returned of (display dialog \"Enter Computer Name\" default answer \"$computerName\")")

echo "New Name: $newName"

This works well, but because we want to use shell variable substitution for the $computerName, we have to use double quotes for the statement. That means we have to escape the internal AppleScript double quotes and everything starts to look really messy. Using a heredoc, cleans the syntax up:

computerName=$(scutil --get ComputerName)

newName=$(osascript <<EndOfScript
    display dialog "Enter Computer Name" default answer "$computerName"
    return text returned of result
EndOfScript
)

echo "New name: $newName"

I have a detailed post: Advanced Quoting in Shell Scripts.

Environment Variables

Generally, variable substitution works well, but there are some special characters where it might choke. A user can put double quotes in the computer name. In that case, the above code will choke on the substituted string, since AppleScript believes the double quotes in the name end the string.

If you have to expect to deal with text like this, you can pass data into osascript using environment variables, and using the AppleScript system attribute to retrieve it:

computerName=$(scutil --get ComputerName)

newName=$(COMPUTERNAME="$computerName" osascript <<EndOfScript
    set computerName to system attribute "COMPUTERNAME"
    display dialog "Enter Computer Name" default answer computerName
    return text returned of result
EndOfScript
)

echo "New name: $newName"

The shell syntax

VAR="value" command arg1 arg2...

sets the environment variable VAR for the process command and that command only. It is very useful.

Retrieving environment variables in AppleScript using system attribute is generally a good tool to know.

Interpret this!

osascript can also work as a shebang. That means you can write entire scripts in AppleScript and receive arguments from the shell. For example, this script prints the path to the front most Finder window:

#!/usr/bin/osascript

tell application "Finder"
    if (count of windows) is 0 then
        set dir to (desktop as alias)
    else
        set dir to ((target of Finder window 1) as alias)
    end if
    return POSIX path of dir
end tell

You can save this as a text file and set the executable bit. I usually use the .applescript extension.

> print_finder_path.applescript
/Users/armin/Documents

To access arguments passed into a script this way, you need to wrap the main code into a run handler:

#!/usr/bin/osascript

on run arguments
    if (count of arguments) is 0 then
        error 2
    end if
    return "Hello, " & (item 1 of arguments)
end

You can combine this into a longer script:

macOS Privacy and osascript

When you ran the above script, you may have gotten this dialog:

If you didn’t get this dialog, you must have gotten it at an earlier time and already approved the access.

AppleEvents between applications are controlled by the macOS Privacy architecture. Without this, any process could use AppleEvents to gather all kinds of data from any process. These dialogs are easy enough to deal with when running from Terminal. But if you put your AppleScript code (or shell scripts calling AppleScript) into other apps or solutions, it could get messy quite quickly.

Mac Admins generally want their automations to run without any user interactions. You can avoid these dialogs by creating PPPC (Privacy Preferences Policy Control) profiles that are distributed from an MDM server. In this case you have to pre-approve the application that launches the script, which can sometimes also be challenge. The other option is to find solutions that avoid sending AppleEvents altogether.

I have a longer post detailing this: Avoiding AppleScript Security and Privacy Requests

osascript and root

Management scripts often run as a privileged user or root. In this case, certain features of AppleScript may behave strangely, or not at all. I generally recommend to run osascript in the user context, as detailed in this post: Running a Command as another User

Conclusion

AppleScript’s bad reputation may be deserved, because its syntax is strange, and often very inconsistent. Nevertheless, it has features which are hard to match with other scripting languages. You can use the strategies from this and the previous posts to combine AppleScript with Shell Scripting and other languages to get the best of both worlds.

Weekly News Summary for Admins — 2022-04-29

It was a comparatively quiet week regarding Apple and macOS news. Aside from Apple making the first self repair options available, and reporting another blowout quarter.


(Sponsor: vast limits)

uberAgent: per-application network monitoring

uberAgent Logo

uberAgent is an innovative user experience monitoring product for macOS and Windows. uberAgent’s highlights include detailed information about application performance, network reliability drill-downs, application usage metering, browser performance, and web app metrics. Try for yourself and get your free 100 user community license at uberagent.com.


The news is that Elon Musk’s attempt to buy Twitter seems to be succeeding. This upsets many, and I cannot say I am excited about this myself. I don’t see much merit in the promises of the prospective new owner, and much potential to change Twitter for the worse.

That said, I have no plans to discontinue the @scriptingosx Twitter account, at least not yet. The advantage of having my website on my own domain, is that I am mostly independent of any specific social media. I cross-post from the blog to various social media and other platforms. Twitter and LinkedIn have the largest number of followers and generate the most traffic back to the site.

I have had a Mastodon (a free, open source, federated social media) account scriptingosx@mastodon.social since 2017 and seen an uptick of new followers in the last few days. (Welcome! You can join a Mastodon server here.) Traffic from Mastodon now exceeds traffic from Scripting OS X’s Facebook page, and is quickly catching up with Apple News traffic. All of these are very low numbers compared to Twitter and LinkedIn.

Scripting OS X also has an RSS feed, so you can add it to your very own curated list of news feeds in your favored RSS News reader. Start with NetNewsWire if you don’t have one yet.

Finally, you can subscribe to the Scripting OS X Weekly News Summary by email. If you are reading this, it is likely that you are already a subscriber, so thank you. But maybe you know a co-worker or other MacAdmin somewhere who isn’t yet and I would very much appreciate if you suggested this News Summary to them. Thank you!

macOS Server

News and Opinion

Social Media

  • Kat’s Mastodon Quickstart for Twitter Users – Kat Marchán
  • Steve Troughton-Smith: “From the start, we knew the App Store was a symbiotic environment designed to create value-add for Apple devices by giving devs great tools to make apps to entice customers to Apple, whilst also ensuring to deny devs any ability to ever remotely threaten Apple’s position of power” (Thread)
  • Mr. Macintosh: “Wondering why the Self Service store doesn’t look like an Apple website? The site is run by 3rd party partner ‘SPOT’ Service Parts Or Tools was incorporated on Dec 1, 2021 The original Apple announcement was on Nov 17, 2021 Total time = 5 months from announcement to live date”

Security and Privacy

Support and HowTos

Scripting and Automation

Apple Support

To Listen

Just for Fun

Support

If you are enjoying what you are reading here, please spread the word and recommend it to another Mac Admin!

If you want to support me and this website even further, then consider buying one (or all) of my books. It’s like a subscription fee, but you also get a useful book or two extra!

Launching Scripts #3: Shell scripts from AppleScript

In this series of posts, I am exploring the various different ways of launching scripts on macOS. In the first two posts, we explored what happens when you launch scripts from Terminal. We already explored some concepts such as the shell environment and how that affects scripts. In this post we are going to explore a different, but very common way to launch shell commands and scripts: AppleScript’s do shell script command.

do shell script

When AppleScript made the transition from Classic Mac OS 9 and earlier to Mac OS X, it gained one command that allowed AppleScripts to interact with Mac OS X’s Unix environment. The do shell script command executes a command or script in the shell and returns the output as a text to the AppleScript.

We have used this in an earlier post:

do shell script "echo $PATH"
    --> "/usr/bin:/bin:/usr/sbin:/sbin"

But you can use this to run any shell command:

do shell script "mdfind 'kMDItemCFBundleIdentifier == org.mozilla.firefox'"
    --> "/Applications/Firefox.app"

Note the use of single quotes inside the double quotes which delineate the AppleScript text. I have a post on the challenges of quoting in these mixed scripting environments.

You can assemble the command you pass into do shell script using AppleScript text operators:

set bundleID to "org.mozilla.firefox"
do shell script "mdfind 'kMDItemCFBundleIdentifier == " & bundleID & "'"
    --> "/Applications/Firefox.app"

Note that the PATH variable for AppleScripts that are run from Script Editor or as an AppleScript applet is different than the PATH in your interactive environment. Most notably, it does not include /usr/local/bin. When you want to use a command or script that is not stored in the four default directories, you will have to use the full path in the do shell script:

do shell script "/usr/local/bin/desktoppr"

(Desktoppr is a small tool I built to work with desktop pictures on macOS, you can get it here.)

When you are unsure what the full path to a command is, you can use the which command in Terminal:

> which desktoppr
/usr/local/bin/desktoppr

Errors

Keep in mind that which uses the same logic to lookup a command as the shell does when it looks up a command with no path. So, if you think you can trick AppleScript by using the which command to lookup a non-standard command, it will still fail:

do shell script "which desktoppr"
    --> error "The command exited with a non-zero status." number 1

When the command in do shell script returns a non-zero exit code, you will get an interactive dialog informing the user of the error. The AppleScript will not continue after the error. You can handle the error the same way you would handle any AppleScript error, with a try… on error block:

set filepath to "/unknown/file"

try
    do shell script "/usr/local/bin/desktoppr" & quoted form of filepath
on error
    display alert "Cannot set desktop picture to '" & filepath & "'"
end try

Files and Paths

AppleScript has its own methods of addressing files and folders. Actually, there are multiple ways, which is one of the confusing things about AppleScript. Neither of the native forms of addressing files and folder in AppleScript use the standard Unix notation with forward slashes separating folders. But there are built-in tools to convert from Unix notation to AppleScript and back.

Use the POSIX path attribute to get a Unix style file path from an AppleScript file or alias. Unix style paths used with commands need spaces and other special characters escaped. You can use the quoted form attribute to escape any AppleScript string. This is usually used directly with POSIX path:

set imagefile to choose file "Select a Desktop"
    --> alias "Macintosh HD:Library:Desktop Pictures:BoringBlueDesktop.png"
set imagepath to quoted form of POSIX path of imagefile
    --> '/Library/Desktop Pictures/BoringBlueDesktop.png'
do shell script "/usr/local/bin/desktoppr " & imagepath

You can convert a Unix style file path into an AppleScript file with the POSIX file type:

set bundleID to "org.mozilla.firefox"
set appPaths to do shell script "mdfind 'kMDItemCFBundleIdentifier == " & bundleID & "'"
    --> "/Applications/Firefox.app"

if (count of paragraphs of appPaths) = 0 then
    display alert "No app found"
else
    set appPath to first paragraph of appPaths
    -- convert the path to an AppleScript file
    set appFile to POSIX file appPath
        --> file "Macintosh HD:Applications:Firefox.app:"
    tell application "Finder" to reveal appFile
end if

Shell Scripts in AppleScript Bundles

Sometimes you are writing an AppleScript and want to use a script for some functionality which is difficult to achieve in AppleScript. When you have an AppleScript file and a shell script file that work together this way, you want to store them together and also have an easy way for one to get the location of the other.

For this, AppleScript provides the notion of script bundles and AppleScript applets (which are also bundles). A script bundle is not a flat file, but a folder which contains the script itself and other resources, such as script libraries, or shell scripts. The script can easily locate items in its bundle and call them.

For example, we want a script that needs to unzip a file. We can use the unzip command line tool to do that, but in my experience it is better to use ditto. The ditto expansion seems to be closer to how the expansion from Archive Utility works and do better with extended attributes and resource forks and other macOS specific things.

This is the shell script for our example:

#!/bin/sh

# target dir for expansion
targetdir="/Users/Shared/Script Bundle Demo"

# sanity checks for argument 1/filepath
if [ -z "$1" ]; then
    exit 2
fi

filepath=$1

# is it a file?
if [ ! -f "$filepath" ]; then
    exit 3
fi

# note: ditto seems to work better than unzip
ditto -x -k "$filepath" "$targetdir"

This is simple enough that you could just do it in a one-line do shell script, but I want to keep it simple. You could extend this shell script to use different tools to expand different types of archives, such as xar, tar, aa etc. If you want a more complex script, feel free to build one!

Now we can build the AppleScript/shell script combination. Open Script Editor, create a new script and save it right away. In the save dialog, change the ‘File Format’ to ‘Script bundle’ before saving.

After you have saved the Script as a bundle, you can see the Bundle Info in a pane on the right side of the script window. If you don’t see this pane, choose ‘Show Bundle Contents’ from the ‘View’ menu, or click the right most icon in the tool bar.

In this pane, you can set the name, identifier, version and some other data for the script bundle. You can also see a list of the ‘Resources’ which shows the contents of the Contents/Resources folder in the script’s bundle. When you find the script you save, you will see it has a scptd file extension and when you open the context menu on it in Finder, you can choose ‘Show Package Contents’ and dig into the bundle contents.

Note: AppleScript applications (or applets) work the same way. Their .app bundles have a few more sub folders, but the Resources work the same way. The difference is that AppleScript applets work on double-click, drag’n drop, and some other events that we will get to in later posts. Script bundles have to run from Script Editor.

Save the shell script from above into the script bundle’s Resources sub-directory with the name unarchive.sh. You should see it appear in the ‘Resources’ list in the script window.

This way, the AppleScript bundle can contain all the resources it might need, including shell (or other) scripts.

Now we still need to find a way to access the Resources from the script. To run our shell script, add the following code to the AppleScript in Script Editor:

-- Script Bundle Demo
set theArchive to choose file "Select a zip archive:" of type {"zip"}
set archivePath to quoted form of POSIX path of theArchive

-- assemble command
set scriptPath to quoted form of POSIX path of my (path to resource "unarchive.sh")
set commandString to scriptPath & space & archivePath

-- for debugging 
log (commandString)

do shell script commandString

First we prompt the user to choose a file with a zip extension, and the we convert the result into a quoted Unix path.

Then, we use the path to resource "unarchive.sh" to get the path to our shell script in the Resources folder in the bundle. Then we get the quoted Unix notation, and assemble the command for the do shell script. The log command there will print the commandString to the output in the script window and is useful for debugging. Then we run the command with do shell script.

Environment for do shell script

Our example script expands the archive into a subfolder of /Users/Shared. If you wanted to use a different location, you could use a second argument in the script.

There is a different way of passing data into scripts and that is environment variables.

First of all it is important to note that the shell environment for commands and scripts run with the do shell script command from an AppleScript in Script Editor or an AppleScript application is very different from the shell environment in an interactive shell in the Terminal. We have already seen that the PATH environment variable has a different value, which influences the command lookup behavior.

You can check the environment variable by running the env command. This will list all environment variables. (To be nitpicky, there is more to a shell environment than just the env variables, there are also shell options, but those will be different for each shell, sh, bash or zsh, anyway.)

do shell script "env"
    --> "SHELL=/bin/zsh
TMPDIR=/var/folders/2n/q0rgfx315273pb4ycsystwg80000gn/T/
USER=armin
COMMAND_MODE=unix2003
__CF_USER_TEXT_ENCODING=0x1F5:0x0:0x0
PATH=/usr/bin:/bin:/usr/sbin:/sbin
__CFBundleIdentifier=com.apple.ScriptEditor2
PWD=/
XPC_FLAGS=0x0
SHLVL=1
HOME=/Users/armin
LOGNAME=armin
_=/usr/bin/env"

Interestingly, we have USER and HOME to use in this environment.

We can also add environment variables to a do shell script command:

do shell script "TARGET_DIR='/Users/Shared/Script Bundle Demo' " & scriptPath & space & filePath

You can use this to set the value of the TARGET_DIR env variable for the next command, which is our script in the script bundle.

Administrator Privileges

No matter which way you use do shell script, it has one big benefit. You can prompt the user to get the command or script to run with administrative privileges:

do shell script "systemsetup -getRemoteLogin" with administrator privileges

This will prompt for the user name and password of an administrator user. This can allow to build some simple workflows that require user interaction and administrative privileges really easily.

Conclusion

Combining Script Bundles and AppleScript Applications with shell scripts can create a powerful combination. You can use the “best of both worlds” with some of AppleScript’s user interaction commands and the shell’s strength in file manipulation and similar workflows. You can also sign AppleScript applications with a valid Apple Developer ID and pre-approve them for privacy exemptions with a PPPC profile.

If this explanation is not detailed enough for you, there is an amazing Tech Note in Apple’s Documentation Archive.

This post covered launching shell scripts from AppleScript. In the next post we will launch AppleScript code from shell scripts.

Weekly News Summary for Admins — 2022-04-22

Yesterday, Apple updated the support article on macOS Server stating the app has been discontinued. They also announced that the Fleetsmith service, which they have maintained since the acquisition in 2020 will be discontinued in October.


(Sponsor: vast limits)

uberAgent: web app monitoring

uberAgent Logo

uberAgent is an innovative user experience monitoring product for macOS and Windows. uberAgent’s highlights include detailed information about application performance, network reliability drill-downs, application usage metering, browser performance, and web app metrics. Try for yourself and get your free 100 user community license at uberagent.com.


The end of both macOS Server and Fleetsmith do not come as a surprise. Apple gutted the functionality of macOS Server in 2018. Back then I wrote a post with my thoughts, and they still hold up well. Most management features and workflows now come from hosted cloud services.

All that was left were Profile Manager and Open Directory. With the release of Apple Business Essentials there is no need for macOS Server/Profile Manager and Fleetsmith to continue. There will surely be missing features and elements, and it will be the MacAdmin’s job to identify these and find workarounds and alternative solutions. For example, Apple Business Essentials is currently only available in the US. MacAdmins in other regions have to look at third party solutions.

File Sharing, Time Machine Server, Content Caching, and Xsan are now part of ‘normal’ macOS. Xcode Server moved into Xcode and then into the cloud.

The macOS Server app cannot be found in the Mac App Store anymore. You can still find it in the list of purchased apps. macOS Server 5.12.2 will be the last update. It should continue to work on Macs running Monterey, but the description in the Mac App Store explicitly points out it will “not be compatible with future versions of macOS.”

Nevertheless, this is a moment to be nostalgic about Mac OS X Server.

Mac OS X Server 1.0 was released before Mac OS X for the client, mostly as a proof of concept, but also as a platform for some services, such as Apple FileSharing, NetBoot and WebObjects. Together with the Xserve and Xserve RAID, Mac OS X Server was part of a strategy to provide services and management to fleets of Macs, in a time where support from third-parties was challenging to non-existent. Even though the path wasn’t always smooth, or even clear, it was an important part of what made enterprise style deployments of Macs possible.

Apple canceled the Xserve and changed the distribution and price model of Mac OS X Server in 2011, and an era ended. Apple ceded most of the services to third parties, some of which were and are rivals, such as Microsoft and Google. With few exceptions, Apple always seemed to be following instead of leading in this field and in the end, the commitment wasn’t there. Nevertheless, the modern tools for MacAdmins: MDM, Automated Device Enrollment, and all the various workflows, all have their roots in the previous server tools.

Because Apple’s tools, documentation and support were often… a challenge, this time also generated the MacAdmin community, in mailing lists like ‘mac-enterprise’, IRC chat rooms and later the MacAdmins Slack. This is also when the MacAdmins culture of sharing and open source emerged, which is still alive and well.

In most ways, Mac OS X Server ended in 2011, then again in 2018. What was left was finally discontinued yesterday. But, during its lifetime, Mac OS X Server and the many people who worked on and with it, defined and earned a place for Macs and Apple devices in organisations and enterprises.

If you would rather get the weekly newsletter by email, you can subscribe to the Scripting OS X Weekly Newsletter here!! (Same content, delivered to your Inbox once a week.)

macOS Server

MacAdmins on Social

  • Glenn Fleishman: “As Apple expands communication safety to the UK (on-device AI-based ID of images with nudity for kids < 18), note the version rolled out doesn’t include an option for parental notification (for under 13). Apple proposed that as two separate options, but hasn’t added the second.”
  • Rich Trouton: “In the wake of macOS Server being discontinued, a non-zero number of folks will now need to look at migrating away from Open Directory to something else. Charles Edge has guidance available

Security and Privacy

Support and HowTos

Scripting and Automation

Apple Support

Updates and Releases

To Watch

To Listen

Just for Fun

Support

If you are enjoying what you are reading here, please spread the word and recommend it to another Mac Admin!

If you want to support me and this website even further, then consider buying one (or all) of my books. It’s like a subscription fee, but you also get a useful book or two extra!

Launching Scripts #2: Launching Scripts from Finder

In this series of posts, I will explore the many ways that you can launch a script on macOS. In the previous, inaugural post, I described what happens when you launch a script from an interactive terminal shell.

There are several virtual terminal applications available for macOS. iTerm is very popular. Some text editors like Visual Studio Code and Nova, have terminals built-in. Since the actual launching of an executable is done by the shell running inside the virtual terminal, the launch process remains the same.

That said, Terminal app has a useful trick up its sleeves.

command file extension

When you change the file extension of a script to .command, double-clicking the file will open it in a new Terminal window and run it there. Any input or output the script requires will happen in that Terminal window. When the script exits, the shell session in the Terminal window will exit.

Let’s take this simple script:

#!/bin/sh
echo "Enter your name: "
read -r username
echo "Hello, $username"

When you put this this in a .command file and double-click it, you get a new Terminal window with:

/Users/armin/Desktop/hello_name.command ; exit;                                 
~ % /Users/armin/Desktop/hello_name.command ; exit;
Enter your name: 

You can see that Terminal opens a new window with a new, default shell and all your configurations, then launches the script right away. The script prints its output and then waits for the user input (the read command). When you enter the name at the prompt, the script continues.

Armin
Hello, Armin

Saving session...completed.

[Process completed]

When the script ends, the shell in the Terminal window exits, as well. No more interactive prompt will be shown.

This script expects user input in the Terminal and then presents output to stdout in the same window. While you could re-write a script to use AppleScript’s display dialog to handle both in the input and the output, it would make the script significantly more complex.

Instead, you can change the file extension to .command and then a double-click will create a new Terminal window where the user interaction (input and output) takes place. For the right kind of user and workflow, this can be a sufficient solution with practically no overhead.

You can also remove the file extension completely. The behavior when you double-click such a file in Finder will be the same. Extension-less executables also get a different the icon. Either way, you need to have the executable bit set for the script.

Note: iTerm can also open .command files, but I have had some trouble with user interaction in these cases. Since I usually don’t use iTerm, maybe I have something setup wrong?

Quarantine and Gatekeeper

A Terminal window is not a user interface that many users will appreciate, but this allows you share scripts with other users in a form they understand. “Double-click this to run” is something that fits with most users’ idea of how macOS works.

Before you start creating dozens of .command scripts and share them, there is a major tripwire that macOS security has set up.

When you share an executable file through a website, email or a chat message, macOS will attach a quarantine flag. With applications, this flag triggers a GateKeeper scan before the app is launched and it will show the standard dialog, even when the app is signed and notarized and a much more “scary” warning when it is not.

When you launch a command or script from Terminal, either directly or indirectly with a double-click, and it still has the quarantine flag set, it will not launch. You will not get one of the standard Gatekeeper dialogs. Just an opaque operation not permitted error in the Terminal output.

You can check if a file has the quarantine flag set with the xattr command:

> xattr hello_name.command
com.apple.TextEncoding
com.apple.lastuseddate#PS
com.apple.quarantine 

Your list list of extended attributes may be different. The quarantine flag has the label com.apple.quarantine.

The xattr command also can remove the quarantine flag:

> xattr -d com.apple.quarantine hello_name.command

Apple seems to assume that when you are using Terminal, you know what you are doing. That means you can bypass most of the mechanisms that attach a quarantine flag with command line tools. When you download something with curl it won’t get quarantined. You can install an unsigned, unnotarized pkg installer using the installer command. Because this is possible, it doesn’t mean it is always wise. Piping a curl command directly into sh or bash or any interpreter is still poor security.

Most of the time though, a script file shared to another Mac or another user will almost certainly get the quarantine flag. Users who are comfortable with using Terminal should be able to use the xattr command to disable this protection, but this is not something for ‘normal’ users. So quarantine, makes the use of the command file extensions far less effective than it could be. This is probably intentional, since executables that are opened by double-click can be an easy way to sneak malware and other unwanted software onto a system, leveraging a user’s ignorance of what is happening.

This is generally true when you move scripts and executable files between macOS systems. I have also seen the quarantine flag getting set when you store a script in a cloud sync service (especially iCloud) or when you edit an executable with a sandboxed application.

One way around the quarantine, would be to distribute and properly install the scripts with an installer pkg. Then you can properly sign and notarize the installer pkg and the scripts will not be quarantined, as they come from a trusted and verified source. This may be a good solution for some workflows, but generally feels a bit “over-designed.”

Output flashes by so quickly

There is a setting in Terminal’s preferences which determines what happens with windows when the shell exits. You can find it under the ‘Shell’ tab in the ‘Profiles’ area. This setting can be different for each profile. Under ‘When the shell exits’ there is a popup menu with the options ‘Close the window,’ ‘Close if the shell exited cleanly,’ and ‘Don’t close the window.’ The last ‘Don’t close’ is the default.

When you have this option set to ‘Close the window,’ the new Terminal window from a command file might only be active and visible for a short time. This may or may not be a good thing, depending on what you want.

Conclusion

Script files with the command file extension can be a simple, straightforward way to make scripts easily ‘launchable’ from Finder. You can also put them in the Dock or in the Login Items. The user experience is, well, a terminal, so not terribly nice, but it can be useful, and does not require any modification of the script.

When you share executable scripts, whether they have the command file extension or not, Gatekeeper quarantine on macOS can prevent the script from running. You should get familiar with the quarantine flag and the xattr command to manipulate it.

In the next post, we launch shell scripts from AppleScripts.]

Weekly News Summary for Admins — 2022-04-15

Even though it is a long week-end here this news summary still delivers!

Happy Easter to everyone who celebrates and I hope you get a bit of a reprieve this week-end either way.


(Sponsor: vast limits)

uberAgent: application usage monitoring

uberAgent Logo

uberAgent is an innovative user experience monitoring product for macOS and Windows. uberAgent’s highlights include detailed information about application performance, network reliability drill-downs, application usage metering, browser performance, and web app metrics. Try for yourself and get your free 100 user community license at uberagent.com.


If you would rather get the weekly newsletter by email, you can subscribe to the Scripting OS X Weekly Newsletter here!! (Same content, delivered to your Inbox once a week.)

News and Opinion

MacAdmins on Social

  • Matt Godden: “If you’re using macOS HighSierra or Sierra, iCloud has stopped working / can’t log in, and you can’t access icloud.com in Safari – here’s a solution: Install the Apple IST CA 2 – G1 certificate, and everything will work again.” (via Michael Tsai)

Security and Privacy

Support and HowTos

Scripting and Automation

Apple Support

Updates and Releases

To Watch

To Listen

Support

If you are enjoying what you are reading here, please spread the word and recommend it to another Mac Admin!

If you want to support me and this website even further, then consider buying one (or all) of my books. It’s like a subscription fee, but you also get a useful book or two extra!