Tiny Deathstars of Foulness

WordPress has an app. That means there’s an API to normalize communication using a predictable programmatic interface. In this case, as with many others, that’s done using a standard REST interface to communicate. The easiest way to interact with any API is to just read some stuff from the server via curl. You can feed curl the URL to the API by using your URL followed by /wp-json – as follows, assuming a URL of


To view header information:

curl -s -D - -o /dev/null

In the below example we’ll ask for a list of posts by adding /wp/v2/posts to the URL:


You’ll see a list of some posts in the output along with a little metadata about the posts. You can then grab an ID and ask for just that post, using a post ID of 48390:


You can also see revisions that have been made to a post by appending the URL with /revisions


You can see comments with the comments route:


Or pages with the pages route:


Or users with the users route:


Or media that has been uploaded with the media route:


And the output of each can be constrained to a single item in that route by providing the ID of the item, which shows additional metadata about the specified item. And there are routes for categories, tags, etc.

There’s also some good stuff at such as which is a plugin that allows you to auth against the API.

curl --user admin:krypted

Not only can you look at user information, you can also add and remove posts. You would add by doing a -X followed by a POST and then feeding a file with the –data option

curl --user admin:password -X POST --data @post.json

The output would then include the ID of your new post to wordpress. In the following example, we’ll get rid of the post we were looking at earlier using -X and DELETE in the URL, assuming a username of admin, a password of krypted, and a post ID of 48390:

curl --user admin:krypted -X DELETE

If successfully deleted the response would be as follows:

“message”:”Deleted post”

To dig in deeper, check out where the whole schema is documented. You can also use the GitHub site to access a command called wp (as well as PHP, node, and java clients) that can be run at the command line for simple scripting interfaces. This could allow you to, for example, simply backup posts to json files, etc.

Also, it’s worth noting that various plugins will require their own interface (note there’s no themes or plugins route), such as woocommerce, interfacing with or

July 14th, 2017

Posted In: WordPress

Tags: , , , , , , , ,

Tomcat logs events into the system log. You can use the get-wmiobject commandlet to see events. Here, we’ll look at a JSS and view only system events:

Get-WmiObject Win32_NTLogEvent -ComputerName $jss -Filter "LogFile='system'

We can then use AND to further constrain to specific messages, in this case those containing Tomcat:

Get-WmiObject Win32_NTLogEvent -ComputerName $jss -Filter "LogFile='system' AND (Message like '%Tomcat%')

We can then further constrain output to those with a specific EventCode with another compound statement:

Get-WmiObject Win32_NTLogEvent -ComputerName $jss -Filter "LogFile='system' AND (Message like '%Tomcat%') AND (EventCode=1024)

For a comprehensive list of Windows event codes, see

You could instead use get-eventlog to see system logs. For example, the following will list the latest 100 entries in the system log:

Get-Eventlog -LogName system -Newest 1000

And the following lists the number of unique entries in descending order using Sort-Object, along with the -Property option set to count:

Get-Eventlog -LogName system -Newest 1000 | Sort-Object -Property count -Descending

And the following would additionally constrain the output to entries with the word Tomcat using the -Message option:

Get-Eventlog -LogName system -Newest 1000 -Message "*Tomcat*" | Sort-Object -Property count -Descending

And to focus on a server called jss, use the -ComputerName option:

Get-Eventlog -LogName system -Newest 1000 -Message "*Tomcat*" -ComputerName "localhost" | Sort-Object -Property count -Descending

July 11th, 2017

Posted In: JAMF, Windows Server

Tags: , , , , , , ,

My latest piece is available at It starts off like this, if it’s your kinda’ thing:

Employee engagement is dipping, according to a new study by human resources consultancy Aon Hewitt, but as an manager, you can make the workplace more appealing through positive initiatives such as employee training and development.

Indeed, I’ve often had people I manage ask for more training. My answer is always an emphatic “yes.”

But then something funny often happens: nothing. Giving staff approval for trainingdoesn’t necessarily mean that they’ll do it unless you follow up methodically and even micromanage the process.

Why does this happen and what does it show about how employers and employees alike can do a better job to make sure development happens? I have five theories.

July 7th, 2017

Posted In: Articles and Books

Tags: , , , , ,

June 21st, 2017

Posted In: MacAdmins Podcast

Tags: , , , , ,

Clients discover the Apple Caching service bundled with macOS Server (and in the future macOS) automatically. You can create a text recored for _aaplcache._tcp on your DNS server. That would look

_aaplcache._tcp 518400 IN TXT “prs=”

Name: _aaplcache._tcp with a type of TXT and a TTL of 518400 seconds. The prs is the address to be used and is set to a value using prs=

June 15th, 2017

Posted In: Mac OS X Server

Tags: , , , ,

June 2nd, 2017

Posted In: Mac OS X, Mac OS X Server, Mac Security, MacAdmins Podcast

Tags: , , , , ,

Over the users I’ve written a good bit about pushing a workload off to a virtual machine sitting in a data center somewhere. The Google CloudPlatform has matured a lot and I haven’t really gotten around to writing about it. So… It’s worth going into their SDK and what it looks like from a shell using some quick examples.

For starters, you’ll need an account with Google Cloud Platform, at and you’ll want to go ahead and login to the interface, which is pretty self-explanatory (although at first you might have to hunt a little for some of the more finely grained features, like zoning virtual instances.


The SDK will include the gcloud command, which you’ll use to perform most tasks in the Google CloudPlatform. To install the SDK, go to and download the appropriate version for your computer. If you’re on a mac, most likely the x86_64 version.

Next, move the downloaded folder to a permanent location and run the inside it, which will kindly offer to add gcloud to your path.


Welcome to the Google Cloud SDK!
To help improve the quality of this product, we collect anonymized usage data
and anonymized stacktraces when crashes are encountered; additional information
is available at <>. You may choose
to opt out of this collection now (by choosing ‘N’ at the below prompt), or at
any time in the future by running the following command:
gcloud config set disable_usage_reporting true
Do you want to help improve the Google Cloud SDK (Y/n)?  y
Modify profile to update your $PATH and enable shell command
Do you want to continue (Y/n)?  y
The Google Cloud SDK installer will now prompt you to update an rc
file to bring the Google Cloud CLIs into your environment.
Enter a path to an rc file to update, or leave blank to use
Backing up [/Users/charlesedge/.bash_profile] to [/Users/charlesedge/.bash_profile.backup].
[/Users/charlesedge/.bash_profile] has been updated.
==> Start a new shell for the changes to take effect.
For more information on how to get started, please visit:

Inside that bin folder, you’ll find the gcloud python script, which once installed, you can then run. Next, you’ll need to run the init, which links it to your CloudPlatform account via oauth. To do so, run gcloud with the init verb, which will step you through the process:

gcloud init

Welcome! This command will take you through the configuration of gcloud.
Your current configuration has been set to: [default]
You can skip diagnostics next time by using the following flag:
gcloud init –skip-diagnostics

Network diagnostic detects and fixes local network connection issues.
Checking network connection…done.
Reachability Check passed.
Network diagnostic (1/1 checks) passed.

You must log in to continue. Would you like to log in (Y/n)? y

If you say yes in the above screen, your browser will then prompt you with a standard Google oauth screen where you’ll need to click Allow.

Now go back to Terminal and pick a “Project” (when you set up billing the default was created for you):

Pick cloud project to use:
[1] seventh-capsule-138123
[2] Create a new project
Please enter numeric choice or text value (must exactly match list

The Command Line

Next, we’re gonna’ create a VM. There are several tables that lay out machine types. Let’s start by listing any instances we might have:

gcloud compute instances list

Listed 0 items.

Note: If you have a lot of these you can use  --regexp to filter them quickly.

Then let’s pick a machine type. A description of machine types can be found at And an image. Images can be seen using the compute command with images and then list, as follows:

gcloud compute images list

Now, let’s use that table from earlier and make a custom machine using an ubuntu uri, a –custom-cpu and a –custom-memory:

gcloud compute instances create krypted1 –image –custom-cpu 2 –custom-memory 5

You’ll then see that your VM is up, running, and… has an IP:

Created [].
krypted1 us-central1-a custom (2 vCPU, 5.00 GiB) RUNNING

Now let’s SSH in:

gcloud compute ssh krypted1

This creates ssh keys, adds you to the hosts and SSH’s you into a machine. So viola. You’re done. Oh wait, you don’t want to leave it running forever. After all, you’re paying by the minute… So let’s list your instances:

gcloud compute instances list

Then let’s stop the one we just created:

gcloud compute instances stop krypted1

And if you’d like, tear it down:

gcloud compute instances delete krypted1

Overall, super logical, very easy to use, and lovely command line environment. Fast, highly configurable VMs. Fun times!

May 18th, 2017

Posted In: cloud, Mac OS X, Ubuntu, Unix

Tags: , , , , , , ,

Added 3 new flags into precache tonight: –jamfserver, –jamfuser, and –jamfpassword. These are used to provide a Jamf Pro server (or cloud instance), the username to an account that can list the mobile devices on that server, and a password to that account respectively.

Basically, when you provide these, the script will pull a unique set of models and then precache updates for them. It’s similar to grabbing a list of devices:

curl -s -u myuser:mypassword

And then piping the output of a device list to:

perl -lne 'BEGIN{undef $/} while (/<model_identifier>(.*?)<\/model_identifier>/sg){print $1}'

And then running that array as an input to Hope this helps make the script more useful!

May 13th, 2017

Posted In: iPhone, Mac OS X Server

Tags: , , , , , ,

Builtin commands are always kinda’ interesting. At first glance, it’s hard to know which commands are builtins. Luckily, there’s a command that I rarely use, called… command. If you run command with the -V flag it will tell you if the command is a builtin:

command -V cd

cd is a shell builtin

If you run a command that isn’t a builtin

command -V ls

ls is /bin/ls

Some builtins are in /bin (like echo). But not all builtins are in /bin. Some are in /usr/bin (like cd). Information about how to use builtins is built into the help command rather than standalone man pages. So, if you do help followed by the name of a command, you’ll get information about the command, and sometimes how to use the command:

help cd

cd: cd [-L|-P] [dir]
Change the current directory to DIR. The variable $HOME is the
default DIR. The variable CDPATH defines the search path for
the directory containing DIR. Alternative directory names in CDPATH
are separated by a colon (:). A null directory name is the same as
the current directory, i.e. `.’. If DIR begins with a slash (/),
then CDPATH is not used. If the directory is not found, and the
shell option `cdable_vars’ is set, then try the word as a variable
name. If that variable has a value, then cd to the value of that
variable. The -P option says to use the physical directory structure
instead of following symbolic links; the -L option forces symbolic links
to be followed.

There are also commands not in a path, which can be found using the which command:

which dsconfigad


May 6th, 2017

Posted In: bash, Mac OS X

Tags: , , , ,

Here’s a new extension attribute at for grabbing the hash ID used for iTunes Store accounts, useful with VPP:

#Jamf Pro Extension Attribute to return the App Store Account Hash for iTunes
#Note that the return is null if one is not found
result=`/usr/libexec/mdmclient QueryAppInstallation | grep iTunesStoreAccountHash | sed '/.*\"\(.*\)\".*/ s//\1/g'`
echo "<result>$result</result>"

The output is something like:


Which would bring the string into Jamf Pro

April 26th, 2017

Posted In: JAMF, Mac OS X, Mac OS X Server, Mac Security

Tags: , , , ,

Next Page »