Extracting Adobe CC icons for Munki

Generally, Munki has no problems extracting icons from .app or .pkg items it imports. Adobe makes its installers a bit annoying to get icons out of, so when you import an Adobe CC item into Munki and try to get the icon out, you'll get this instead:

Attempt to create a product icon? [y/n] y
Attempting to extract and upload icon...
Can't generate icons from installer_type: AdobeCCPInstaller.

With some idea help from some people on the MacAdmins Slack team, I cobbled together a script that extracts the Adobe CC icons. The only bummer is that you have to actually install the Creative Cloud items on to a client machine first and then run the script on the client machine to get the icons.


Terminal command to get the full name of a Mac user

Munki-Enroll is a great little script combo that automatically changes the ClientIdentifier for Munki clients and then automatically creates a corresponding manifest on the Munki server that includes the old manifest.

I wanted to tweak it quite a bit to fit some of the quirks of how our organization does Munki client manifests, so I wrote up a tweaked version of the enroll shell script.

One of the things I wanted to get via the script is a particular user's full name, and I had trouble tracking down a tutorial on exactly how to get that. I also found that even when I used the usual instructions, on one computer, it didn't work—there was an extra carriage return before the full name... but that wasn't the case on other computers (and it wasn't a Yosemite vs. El Capitan thing either).

So this command actually gets the user's full name even if there's a random extra newline in the output. This works on both Yosemite and El Capitan (and probably earlier versions, but I haven't tested on Mavericks and before):

dscl . -read /Users/SHORTUSERNAME dsAttrTypeStandard:RealName | sed 's/RealName://g' | tr '\n' ' ' | sed 's/^ *//;s/ *$//'
where SHORTUSERNAME is the short username you're trying to get the full name of.

Basically, this read's the user's information, specifically the RealName. Then it strips out the RealName: part, then strips out any newline indicators, then finally strips out any preceding or trailing spaces.

Not sure if anyone else out there is looking for how to get the full name of a user using the terminal on a Mac, but that's how you do it.


Putting Dockutil add/removes in arrays in Bash

Most of the time when you see scripts using Dockutil to add and/or remove items from the Dock in Mac OS X, they look like this:

/usr/local/bin/dockutil --add '/Applications/' --no-restart
/usr/local/bin/dockutil --add '/Applications/' --no-restart
/usr/local/bin/dockutil --add '/Applications/' --no-restart
/usr/local/bin/dockutil --add '/Applications/' --no-restart
/usr/local/bin/dockutil --add '/Applications/' --no-restart
/usr/local/bin/dockutil --add '/Applications/' --no-restart
/usr/local/bin/dockutil --add '/Applications/' --no-restart
That's totally fine to do, but I figured putting the additions and removals into arrays may be a cleaner way to manage things, so I wrote up a sample script for that.

There is an array of Dock items to remove and then an array of Dock items to add. Then it loops through all the removal items, makes sure each item already exists (no point in removing something that doesn't exist), and then removes it. Then the script loops through all the addition items, makes sure each item isn't already there (otherwise, Dockutil warns that you should using the --replacing option) and that the source item exists (otherwise, the non-existent item gets added as a question mark), and then adds it.


Checking folder/file creation time using bash on Mac OS X

Why would you want to check the folder/file creation time in Mac OS X?

Outset allows you to run login scripts at every login or only once per user. The way Outset keeps track of whether a script has been run for a user or not is in a .plist at /Users/username//Library/Preferences/com.github.outset.once.plist with the name of the script and the corresponding date and time. Outset also has an option to add certain users to the ignore list, but that means they're ignored for all Outset scripts.

But what if you want to run a certain login-once script only for new users and not existing users?

For example, let's say you want to deploy a default Dock to clients using Outset. The old (now frowned-upon but still works) way to do it would be to modify the /System/Library/User Template/English.lproj folder. Now the new (recommended) way is to script all changes.

You don't want to make it a login-once script, unless you're replacing an already-existing login-once script with the exact same name, because then it will modify the Dock for users who have already customized their own Docks.

So one way to approach this problem is to check the creation time of the user folder. A user folder created in the last two minutes is likely to be new and okay to be scripted to the new default, but a user folder created over two minutes ago may have already been customized by the user. Dock. Actually, the user folder gets created when the user folder is created, not when the user logs in. So it's actually better to check for when the was created, even though that creation date shifts to about a day ago, even if you don't modify the Dock at all—it's still a more accurate indicator than the user folder creation.

Script to check for user folder creation date/time

I wrote up a CheckUserFolderCreationTime script that you can pop into various login-once scripts that you want to have applied to only newly-created users.

The logic of it is basically:

  1. Define a threshold of creation time.
  2. Find the current user's home directory Dock .plist.
  3. Find the date and time it was created.
  4. See if it was created within the past [threshold] minutes.


Filling out a Google Form from the terminal using the curl command

Cheating a bit here by just linking to someone else's blog post, but it's very well written, with screenshots and different colors. Why reinvent the wheel?

Here it is:
Submit Google Forms By Curl Command


Renaming a Mac hard drive from the command line

You know, if your hard drives are set to show as icons on the desktop, you can rename them by selecting them, hitting Enter, and then typing in a new name? If you want to script naming, you can also name from the command line.

For example, if you want to rename the drive you're currently booted to and call it Munki Time, you'd use this command:

diskutil rename / Munki\ Time
The forward slash represents the root (top-level) directory and the backslash just escapes the space, so the terminal knows you're including Time with Munki as one label.


Terminal command to change a user password on a Mac

Update May, 2019

Now that there are SecureToken users, the command below no longer works to reset another user's password. Thanks to mario on the MacAdmins Slack for testing.


Just a cleaned-up version of directions from Mac Script to change Administrator password

Changing a user password via terminal command

If you ever want to—perhaps for scripting purposes?—change a user's password from the command-line (despite what it says in the link above, you don't have to be logged in as the user to change the user's password, but you do have to be logged in as an admin user), these are the commands you'd use:

sudo /usr/bin/dscl . -passwd /Users/username newpassword
sudo security set-keychain-password -o oldpassword -p newpassword /Users/username/Library/Keychains/login.keychain
Substitute in the actual user's username for username, the actual user's old password for oldpassword and the actual user's new password for newpassword.

If you don't know the old password...

If, for some reason, you (and the user both) have forgotten the user's old password and don't want to deal with keychains issues, you can also just delete the existing keychain (instead of running the second command to update the keychain password):

sudo rm -r /Users/username/Library/Keychains/*

Security issues

One strong caveat is that the terminal, by default, will save commands to ~/.bash_history in plain text, so you're essentially storing a user's password in plain text, unless you temporarily disable bash history or later go into the ~/.bash_history file with a text editor (like nano) and delete the offending lines manually.

If you distribute this as part of a .pkg, nothing will be visible in a .bash_history file, but make sure you keep that .pkg extra secure or delete it after deploying it.


Running a post-uninstall script for a Munki package

Much as I love editing text files and entering commands into, I do also appreciate a good GUI frontend. Apart from munkiimport, I mainly manage Munki using MunkiAdmin, as I referenced in Absolute beginner’s guide to setting up Munki (not monkey).

Of course, I got a bit too comfortable with the GUI frontend, and I put in incorrectly a post-uninstall script for a package and got back this error message: Error executing script postuninstall_script: [Errno 8] Exec format error.

After I actually read the Munki wiki page on Pre And Postinstall Scripts, I realized my mistake—I'd put in only the command I wanted without giving the environment for that command.

Turns out (which makes sense in hindsight) I had to put in

before putting the actual command to run after the uninstall.

In case anyone else who's GUI-dependent (and who also hasn't read the wiki carefully) runs into this issue, that's the solution—put in the environment you're using (Is it bash, shell, python, etc.?), and not just the command itself.


Running sudo commands in Automator

If you're wondering how to run sudo (for privilege escalation) commands in Automator, this is one way to do it.

Launch up Automator (of course).

Find Run AppleScript in the library of actions.

Then, drag it over to the workflow area on the right. By default, Automator will put in some script structure for you to work with. Feel free to just delete that all completely.

In place of the predefined script, put in

do shell script "sudo whatevercommandyouwanttorun" with administrator privileges

if it's one command you want to run.

If you would rather run a script, it's a similar syntax of

do shell script "sudo /path/to/" with administrator privileges

You can save your workflow as an application.

When you double-click your .app file, it should then prompt you for an administrator username and password and then run your bash command or shell script in a sudo-like way.


Fix ownership of copied folders for Active Directory Macs


This script does some serious system modifications. If you don't know what you're doing, ask questions in the comments. Don't just run this script if you don't understand what it does or how it's doing it.

This also assumes short usernames match up with user folder names, which they usually do.

What issue this addresses

I'm not sure how often other people will encounter this situation, but if you have an old Mac joined to Active Directory, and you want to transfer the user folders (assuming they are local user folders) to a new Mac also joined to Active Directory, the copied folders may not have the right folder ownership. For example, if you use an admin account to copy the folders over, the copied folders may belong to root.

So when users log in, they may have folders they can't get access to, or you may get the OS X needs to repair your Library to run applications. Type an administrator's name and password to allow this error message when you log into the new Mac as a domain user who'd already logged in on the old Mac.

How you should modify this script before running it

The script is written in such a way that it will not try to change ownership of certain system accounts (e.g., root, Shared, Guest). You can add in others as you see fit.

It also assumes, since you're on a domain, that the proper group for domain users is YOURDOMAIN/Domain Users. Modify to your actual domain, accordingly.

Creating the script

As an admin user, launch up (you can use a text editor, but if you don't have a favorite text editor like TextWrangler or Sublime Text, the built-in text editor in Mac OS X may default to rich text format instead of plain text). You can find in /Applications/Utilities or through a Spotlight search.

Paste in the follow command:

nano ~/Desktop/fix\ folder\

This will open up in a terminal-based text editor a file in which you can paste the script.

In nano (or your favorite text editor, if you opted for a graphical text editor instead of a terminal-based one), paste in the following script:


# Announce what this does
echo 'This script will make sure users own their own user folders. This will not modify the Shared user folder, the root user folder, or any of the admin/admin2 folders.'

# Change directory to the Users directory.
cd /Users

# Loop through the existing users
for p in *; do

# Don't do this for the Shared user, root, or any local admin account...
if [ "$p" != "Shared" ] && [ "$p" != "root" ] && [ "$p" != ".localized" ] && [ "$p" != "Guest" ]; then

# Announce changing folder ownership
echo -e "Changing folder ownership for $p"

# Change ownership to the current user with the group being the domain users group
#sudo chown -R "$p":"YOURDOMAIN\Domain Users" /Users/"$p"/

# End checking it's not a user not to be modified

# End looping through existing users.

Modify the script before you save

Before you save the file, make the modifications you need. You'll see that there's a line excluding modifications for Shared, for root, for .localized, and for Guest. If there are any other user accounts you don't want to modify ownership on, add those into that line as well, using the same format (copy everything from the ampersands through the closing bracket, and then paste it before the semi-colon and then modify the username).

Also, change YOURDOMAIN to your school or company's actual domain name.

Save the file and get it ready to run

Save the file (if you're using nano, press Control-X to save).

Then, to make the file executable, paste in the following command:

chmod +x ~/Desktop/fix\ folder\

Testing the script

Before using the script to actually modify anything, run it once with the change ownership line commented out (that's how it defaults to above).

cd ~/Desktop
./fix\ folder\

Verify that the users that are listed are the actual ones you want to modify. Look very carefully at the list!!!

Running the script for real

If you feel confident about the list, modify the script so it will actually make the ownership changes. (By the way, you may need network connectivity to connect to Active Directory, or you may get warnings about illegal user names or illegal groups.)

Edit it again:

nano ~/Desktop/fix\ folder\

Change the commented-out line:

#sudo chown -R "$p":"SIPREP\Domain Users" /Users/"$p"/

So it will now be uncommented out:

sudo chown -R "$p":"SIPREP\Domain Users" /Users/"$p"/

Then save (Control-X)

Then run the script again, and it should actually change the folder ownership:

cd ~/Desktop
./fix\ folder\

For internal use