Apple has a number of different logging APIs. For the past few releases, Apple has tried to capture everything possible in logs, creating what many administrators and developers might consider to be a lot of chatter. As such, an entirely new interface needed to be developed to categorize and filter messages sent into system logs.
The logger command is still used to create entries in system logs. However, if you are then using tail to view /var/log/system.log then you will notice that you no longer see your entry being written. This is because as the logs being created in macOS have gotten more complex, the tools to read and write those logs has gotten more complicated as well.
Let’s take a simple log entry. Below, we’ll write the string “Hello Logs” into the system log. To do so, use the –i option to put the process id of the logger process and –s to write to the system log, as well as to stderr. To make the entry easier we’ll tag it with –t followed by the string of the tag. And finally, we’ll quote the entry we want written into the log. This is basically the simplest form of an entry:
logger -is -t krypted "Hello Logs"
Once written, use the log command to read your spiffy new entries. This isn’t terribly different than how things worked previously. If you’re a developer, you will need to note that all of the legacy APIs you might be using, which include asl_log_message, NSLog, and syslog, have been redirected to the new Unified Logging system, provided you build software for 10.12 (you can still build as before for 10.11, iOS 9, tvOS 10, and watchOS 3 and below). These are replaced with the os_log, os_log_info, os_log_debug, os_log_error, os_log_fault, and os_log_create APIs (which correspond to various levels of logs that are written).
Logs are now stored in the tracev3 formatted files in /var/db/diagnostics, which is a compressed binary format. As with all binary files, you’ll need new tools to read the files. Console has been updated with a new hierarchical capability and the ability to watch activities, subsystems, etc.
The log command provides another means of reading those spiffy new logs. To get started, first check out the man page:
That “Hello Logs” string we used earlier is part of a message that you can easily view using the ‘log show’ command. In the below example, we’ll just run a scan of the last 3 minutes, using the –last option, and then providing a –predicate. We’ll explain those a bit later, but think of it as query parameters – here, we’ll specify to look for “Hello Logs” in eventMessage:
log show --predicate 'eventMessage contains "Hello Logs"' --last 3m
Filtering the log data using “eventMessage CONTAINS “Hello Logs”” shows us that our entry appears as follows:
Timestamp Thread Type Activity PID
2017-03-23 23:51:05.236542-0500 0x4b83bb Default 0x0 88294 logger: Hello Logs
Log – Default: 1, Info: 0, Debug: 0, Error: 0, Fault: 0
Activity – Create: 0, Transition: 0, Actions: 0
How do you find out what to use where? Here’s an example where I’m going to try to find all invalid login attempts. First, I’m just going to watch the logs. Many will prefer the “log stream’ command. I’m actually going to just use show again, because I like the way it looks more. I’m also going to use log with the syslog –style so it’s easier to read (for me at least), and then here I’m just looking at everything by specifying a space instead of an actual search term:
log show --style syslog --predicate 'eventMessage contains " "' --info --last 24h
Looking at the output, you can see an entry similar to the following:
2017-03-23 14:01:43.953929-0500 localhost authorizationhost: Failed to authenticate user <admin> (error: 9).
Oh, I’ve got to just search for Failed to authenticate user” and I’ll be able to count invalid login attempts. To then take this and place it into a command that, for example, I could build an extension attribute using, I can then just find each entry in eventMessage that contains the string, as follows:
log show --style syslog --predicate 'eventMessage contains "Failed to authenticate user"' --info --last 1d
As with many tools, once you have a couple of basic incantations, they become infinitely simpler to understand. These few commands basically get you back to where you were with tailing logs. If you want to get that –f functionality from tail, to watch the logs live, just swap show with stream. The most basic incantation of this would just be ‘log stream’ without bothering to constrain the output:
Running this is going to spew so much data into your terminal session. So to narrow down what you’re looking for, let’s look at events for Twitter:
log stream --predicate 'eventMessage contains "Twitter"'
You can also view other logs and archives, by calling a file name:
log show system_logs.logarchive
The new logging format also comes with Subsystems. If you’re a developer you’ll be able to file your messages into, for example, a com.yourname.whatevers domain space, so you can easily find your log messages. You can also build categories, and of course, as we noted previously, tag. So there are about as many ways to find log entries as you can possibly ask for. Apple has a number of subsystems built into macOS. I put together a list of Apple subsystems into a class that you should be able to throw into your python projects at https://gist.github.com/krypted/495e48a995b2c08d25dc4f67358d1983.
You also have different logging levels. These include the basic levels of Default, Info, and Debug. You also have two special levels available: Fault and Error. All of this is to add hierarchical logs (which makes tracing events a much more lovely experience) and protecting privacy of end users (think sandbox for logs). I’d recommend watching the WWDC session where Unified Logging was introduced at https://developer.apple.com/videos/play/wwdc2016/721 if you’re interested in learning more about these types of things, especially if you’ll be building software that makes use of these new logging features.
The one thing that’s worth mentioning for the Mac Techs out there, is how you would go about switching between logging levels for each subsystem. This is done with the ‘log config’ command. Here, I’ll use the –mode option to set the level to debug, and then defining the substyem to do so with using the –subsystem option:
log config --mode "level:debug" --subsystem com.krypted
If you have a particularly dastardly app, the above might just help you troubleshoot a bit. As mentioned earlier, we also have these predicates, which you can think of as metadata in the searching context. These include the following:
OK, now let’s make things just a tad bit more complicated. We’ll do this by stringing together search parameters. Here, we have a number of operators available to us, similar to what you see in SQL. These include:
To put these into context, let’s use one in an example. Thus far my most common as been a compound search, so matching both patterns. Here, we’ll look at the WirelessProximity subsystem for Bluetooth and we’ll look at how often it’s scanning for new devices, keeping both patterns to match inside their own parenthesis, with all patterns stored inside single quotes, as follows:
log show --style syslog --predicate '(subsystem == "com.apple.bluetooth.WirelessProximity") && (eventMessage CONTAINS[c] "scanning")' --info --last 1h
Developers and systems administrators will find that the Apple guide on predicate programming, available at https://developer.apple.com/library/prerelease/content/documentation/Cocoa/Conceptual/Predicates/AdditionalChapters/Introduction.html, to be pretty useful if you’re doing lots of this kind of work.
Note: sysdiagnose, a tool long used for capture diagnostics information to include in bug reports, is still functional, and now includes Unified Logging information, so Apple developers can get a complete picture of what’s going on in systems.
Ultimately, the new Unified Logging is a bit more complicated than the previous options for both creating and reading logs. But once you get used to it, you’ll log it – I mean, love it. I find that I use less grep and awk and get more concise results. I also like the fact that the same code is useable with all four platforms, so learn once and re-use across devices. There’s a lot of information out there, but I had to go hunting around. Hopefully having a number of links and a the structure used in this article makes it easier to learn how to use all these new new little toys! Good luck!
krypted July 26th, 2017
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 http://www.krypted.com:
To view header information:
curl -s -D - http://www.krypted.com -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.
curl --user admin:krypted http://www.krypted.com/wp-json/users/me
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 http://www.krypted.com/wp-json/posts --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 http://www.krypted.com/wp-json/posts/48390
If successfully deleted the response would be as follows:
To dig in deeper, check out http://v2.wp-api.org/reference/posts/ where the whole schema is documented. You can also use the https://github.com/WP-API 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 http://gerhardpotgieter.com/2014/02/10/woocommerce-rest-api-client-library/ or https://woocommerce.github.io/woocommerce-rest-api-docs/.
krypted July 14th, 2017
Posted In: WordPress
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 https://www.ultimatewindowssecurity.com/securitylog/encyclopedia/default.aspx.
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
krypted July 11th, 2017
My latest inc.com piece is available at https://www.inc.com/charles-edge/your-employees-want-extra-training-but-youre-going-to-have-to-help-them-get-star.html. 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.
krypted July 7th, 2017
Posted In: Articles and Books
krypted July 3rd, 2017
Posted In: MacAdmins Podcast
My latest @inc piece is up at https://www.inc.com/charles-edge/5-ways-your-it-staff-can-make-your-business-more-tech-savvy.html.
Remember Nick Burns, the “company computer guy” played by Jimmy Fallon on “Saturday Night Live”?
IT people have long been fixtures in the office (though hopefully seldom as grumpy as Nick). However, their jobs have been radically changed by two trends — the cloud and consumerization.
The cloud has amplified what a small business can do by moving the physical server and network infrastructure that staff or consultants used to be needed to manage, to off-premises locations.
krypted June 22nd, 2017
Posted In: Articles and Books
krypted June 21st, 2017
Posted In: MacAdmins Podcast
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=192.168.50.100”
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=192.168.50.100.
krypted June 15th, 2017
Posted In: Mac OS X Server
krypted June 12th, 2017
Posted In: MacAdmins Podcast
krypted June 7th, 2017
Posted In: MacAdmins Podcast