TweetFollow Us on Twitter

The Shell: Automation

Volume Number: 21 (2005)
Issue Number: 4
Column Tag: Programming

Mac In The Shell

by Edward Marczak

The Shell: Automation

Doing Something Useful

Automation: it's everything. There's little other reason to have computers in a business. While that may be a slight oversimplification, let's agree that it's a compelling reason to have them around. Sometimes, you automate smaller tasks so you can free up your time to automate the bigger tasks.


Last month, we touched on some basic shell commands. This month, we'll take those, and a new one or two, and create a script that helps us automate some system maintenance.


The March "Mac In The Shell" talked about how the bash shell works with files, interprets pattern matching characters, and can get you help. As you've been practicing your shell-fu, hopefully you've found some new commands that are simply too useful to give up. For now, though, they're just commands. By chaining commands together, or letting them interact in any way, they become greater than the sum of their parts. Unix is built on this philosophy. You'll find that most commands are small, single-purpose programs. Each program can concentrate on being great at one thing. Then, we can write a script or function, or use i/o redirection to have the output of one program act as input to another.

Here's an example: 'wc' is the "word, line, character, and byte count" program. You can feed it a file, and it will happily spit back these statistics:

$ wc 
      93     299    2350

'' has 93 lines, 299 words and 2350 bytes. Sometimes, you just have to know these things. Additionally, 'wc' accepts switches that tailor the output to your needs. If you just need to know how many lines, use the '-l' (ell) switch:

$ wc -l 

But what if we need to know how many lines in a directory listing? The 'ls' command doesn't have an option for that. That's why we let each program do what it does best! We'll let the 'ls' command list the directory, and have 'wc' use the output from 'ls' as its input. An example from my home directory:

$ ls -l | wc -l

(Yes, that's about 20-or-so too many, OK?) The "|" character is the pipe, or more properly, "pipeline." I'll give a quick overview of the going-ons here, but for more information and usage examples, see my article in the December 2004 MacTech.

Most of us take for granted the fact that we have a keyboard in front of us, and when we type, characters show up on the screen. Additionally, few people run and remember that this is supposed to be emulating a real terminal. Well, in some ways, the underlying system does still treat each terminal session as if it were a real, physical terminal hooked into it. It does this through the use of virtual terminals (or, 'pseudo-terminals'). I suppose "Virtual" just didn't roll off the tongue.

Whether you're using a real text-terminal connected via wire to an AIX server, or locally on your OS X box, some things are constant. We all have learned (or should have, at some point), about "Input, Process, Output" in computer information handling. When you're running a shell, there are defaults for 'input' and 'output', called 'standard input' and 'standard output'. Standard input is taken from your typing at the keyboard. Standard output is the screen. There are several ways to redirect this input and output, and the pipe is one of the ways to do that.

In the previous example, we could certainly have done this:

$ ls -l > filelist.txt
$ wc -l filelist.txt

The '>' character lets us redirect standard output. Instead of the output from 'ls' printing to the screen as it usually does, we redirect it to a file. Then we can have 'wc' operate on the file. However, it's a lot easier and neater to use the pipe redirector to do it all in one step, isn't it?

The Automator

Apple apparently agrees with my stance on automation, as evidenced by the 'Automator' feature of Tiger. However, in reality, you are the automator. We're not quite up to the stage where operating systems and applications really watch what you do over time, and then modify behavior purely on your actions. So, you have to automate actions. Automator in Tiger is a great step in this direction, and it will even call shell scripts for you!

A fair amount of automation is already built into OS X for you. Shell scripts that clean up log files, rebuild databases, and more run from cron. 'cron' is a system utility that runs shell scripts ("jobs," more precisely, as it can really kick off any program, such as perl, PHP or python) on a set schedule. We learned how to massage cron and have it run our own jobs from Josh Wisenbaker in the March issue of MacTech. Despite the maintenance that already exists in OS X, there's always more work to do. Here's an example of a script that I like to run on OS X Server, but there are parts that will be useful on OS X as well (remember that OS X makes a great server, too, as it will run pretty much anything that OS X Server will). I'll also introduce one of my favorite commands.

What We Need To Know

An OS X Server box that is tasked with just about everything that it can do has a lot of responsibilities: DNS, e-mail, file serving, web serving, and more. There are certain critical parameters that we should be kept abreast of, such as free disk space, if there's anything stuck in the mail queue, if any binaries have been altered, etc. I like knowing this summary every morning. So, how can we get this in a simple, single source? A shell script that e-mails its output to us, of course!

First, running out of disk space pretty universally bad. OS X, with its "I advocate a single partition" disk scheme makes watching disk space even more critical. 'df' is the tool we use to find out how much disk space is used and free on local, mounted volumes. I like using the '-h' 'human readable' switch:

$ df -h
Filesystem                  Size     Used     Avail     Capacity     Mounted on
/dev/disk4                  173G      73G      100G          42%      /
devfs                       110K     110K        0B         100%      /dev
fdesc                       1.0K     1.0K        0B         100%      /dev
<volfs>               512K     512K        0B         100%      /.vol
/dev/disk5                  234G     221G       13G          95%      /Volumes/Data2
automount -nsl [436]          0B       0B        0B         100%      /Network
automount -fstab [449]        0B       0B        0B         100%      /automount/Servers
automount -static [449]       0B       0B        0B         100%      /automount/static
/dev/disk10                 932G     444G      487G          48%      /Volumes/Data1

It's good to know about all of our volumes, but the super-important one is our system volume. The system volume is represented by the "/" on the first line of output above. We can see that of the three real volumes on this system, one is getting pretty close to being full (Data2 at 95% capacity = 'only' 13GB left!).

We can find out about what's in the mail queue with the 'mailq' command. This will tell us what has been deferred in a sendmail or postfix queue. I just happen to have an example: (see bottom figure.) Here, we see this server has three messages that are still waiting to be delivered for one reason or another. Sometimes, you'll find that messages to a certain destination are backed up because the mail host is genuinely down or unreachable. Other times, you'll find that routing is borked on your end, and the queued messages have a bit more of a random pattern.

There are several systems that will take a hash of your files, and then later tell you if anything has changed. This has become known as a tripwire function, named so after the application "Tripwire" that basically fathered this genre of utility. Naturally, the goal of running a system like this is security. If someone/something replaces your 'ls' binary with one that hides certain files, you want to know about it. I run tripwire on most of my Mac OS X boxes, more as a notification of things that have been installed than for the paranoid security reasons, so that's what I'll discuss here. Of course, there are others, such as radmind (which also can do a lot more than simply compare files), and Checkmate. We'll be discussing tripwire in a future column, but for now, I'm just going to go though the motions.

First, I go dump all of the old reports from the reports directory:

rm -f /usr/local/tripwire/report/*

Then, we want to run the tripwire and generate our new report:

/usr/local/tripwire/bin/tripwire -m c

Finally, we can update the database with the new changes, so we're reset for the next run:

/usr/local/tripwire/bin/tripwire -m u -a -r 
   /usr/local/tripwire/report/`ls /usr/local/tripwire/report` 
   -P "My really long passphrase" -v

What's a system without backup? Even if I have a tape backup running, I like to a) copy certain files locally on the same

$ mailq
-Queue ID-          -Size-           -Arrival Time-                -Sender/Recipient-
0C4125B83A8         2615             Fri Apr  1 02:59:56           MAILER-DAEMON
 (Name service error for type=MX: Host not found, try again)

B8E2A4EF0EF         2628             Thu Mar 31 01:28:52           MAILER-DAEMON
 (Name service error for type=MX: Host not found, try again)

D7ACD4439EE         3204             Wed Mar 30 07:59:25           MAILER-DAEMON
 (connect to[]: Operation timed out)

-- 9 Kbytes in 3 Requests.

disk, simply for ease of access, and b) get files off of the server to a remote location. I use rsync for both of these tasks. If you plan on implementing this as outlined here, please note: you must replace the Apple-supplied rsync with RsyncX if you want to sync files with resource forks ( So, what do we want to copy here? I like to get /etc locally:

rsync -a -q --delete /private/etc/ /backup/etc/

On a server running mail, I like to grab the mail store:

rsync -a -q --delete /var/imap/ /backup/var/imap/
rsync -a -q --delete /var/spool/imap/ /backup/var/spool/imap/

Lastly, I like to move certain files off-site. rsync will do that, too:

rsync --delete -l -a -v /Shares/shared/
   /Volumes/Backup/rsync-bu/shared/ --eahfs -stats

Lastly, I make sure I clean up any directories that may be building up files. Some of my servers run OpenBase databases (for the excellent DayLite by MarketCircle). One of the options for OpenBase is an automatic backup. Great! The only problem with this is that, while it's happy to make the backup, it doesn't know when to get rid of it. Files can pile up pretty quickly, which means disk space can disappear quickly, too. Here's where my favorite command comes in. The 'find' command is one of those commands that certainly fits the philosophy that we discussed earlier. However, it's also a bit of a Swiss Army knife in that it will handle certain tasks even though other utilities would do the job just fine. Yes, this will be talked about in more depth next month. The find command lets us find files based on several different criteria. One parameter is the age of the file. I want to delete any OpenBase backup files that haven't been modified for 7 days:

find /Library/OpenBase/Backup/ -mtime +7 -delete

This will rid us of files that have not been modified in 7 days in the /Library/OpenBase/Backup directory. find is very powerful, and can be a system admin's best friend on many occasions. However, while you're learning, please note: find is also one of those commands that you have to be a little careful with, and it will descend recursively into all of the directories below the path you specify. Used with the "-delete" switch, it can do damage! As a last measure in my old-file-removal routine, I like to also dump old quarantined mail caught by amavis:

find /var/quarantine/ -mtime +7 -delete

Put It All Together

Now that we know exactly what we want to do, let's turn it into a shell script. To do this, we need a text editor. I typically reach for vi. Apple tends to lead people through these examples with pico. While there are some GUI tools that will also do the trick (TextWrangler and SubEthaEdit come to mind), this is a column on using the terminal, and that's what we'll do! Remember: vi, emacs and pico can easily be used over ssh, with no access to a GUI at all - TextWrangler and SubEthaEdit can't!

Creating a shell script involves a few steps. We'll call this one ''. Get into vi to edit this file by typing "vi". Press the 'i' key to go into insert mode. You should now see the word 'INSERT' at the bottom of your screen. First thing we need to do is to declare what kind of script this is:


Alternatively, this could have been a perl script (#!/usr/bin/perl), PHP, Python, a different shell such as tcsh, or other variety. When you invoke this as an executable, the shell looks at this first line to determine which interpreter to use to run your script. This is a nice shorthand way to execute a script, rather than have to specify everything on the command-line. Then, we'll add each of our commands, one by one, with some comments. So, the whole thing looks like this:


# Our nightly maintenance routine
# Problems?  Contact Joe Admin
# version 1.0 - 2005-04-04

# Let the logs know that we've begun
logger -p local0.notice -i -t Nightly Starting nightly routine

# Get disk stats
/usr/bin/df -h

# See what's in the mail queue

# Run tripwire reports
logger -p local0.notice -i -t Running tripwire reports
rm -f /usr/local/tripwire/report/*
/usr/local/tripwire/bin/tripwire -m c
/usr/local/tripwire/bin/tripwire -m u -a -r /usr/local/tripwire/report/`ls 
   /usr/local/tripwire/report` -P "My really long passphrase" -v

# Backup files
logger -p local0.notice -i -t Backing up files
/usr/bin/rsync -a -q --delete /private/etc/ /backup/etc/
/usr/bin/rsync -a -q --delete /var/imap/ /backup/var/imap/
/usr/bin/rsync -a -q --delete /var/spool/imap/ /backup/var/spool/imap/
/usr/bin/rsync --delete -l -a -v /Shares/shared/
   /Volumes/Backup/rsync-bu/shared/ --eahfs -stats

# Clean up old files
find /Library/OpenBase/Backup/ -mtime +7 -delete
find /var/quarantine/ -mtime +7 -delete

logger -p local0.notice -i -t Nightly maintenance complete

Lines that start with a hash mark ('number sign') are comments and are ignored by the bash interpreter. This script will execute, one line at a time from the beginning to the end. It sends its output to standard output. However, we're going to run this from cron, which, by default, will take any standard output and e-mail it to the owner of the crontab.

Let's save this script. If you're still with me in vi, press the escape key once, and then type ":" (colon, not semi-colon - so hit the shift key, too). The colon character puts you into command mode. When you see the colon character at the bottom of your screen, type 'wq' and press enter. That's short for 'w'rite the file and then 'q'uit. You'll be back at the command line. So, just one more thing: we need to mark this script executable. Type "chmod u+x" and press return. This adds the executable bit to the permissions of our script. Without it, the shell won't (easily) execute our file.

I want to test this script, but a word of warning first: Do NOT run this script as-is. It needs to be adjusted for your environment. The 'logger', 'du' and 'mailq' lines are harmless. Everything else needs to be changed to some sane value. You may or may not have tripwire installed. If you do not, simply remove that section. What directories are you concerned with backing up? Naturally, the 'Clean up old files' section will remove files! Make sure you either remove these lines, or point them at a directory that makes sense for you!

Did you read all that? Really? OK. Now we'll....wait. Go read the preceding paragraph again....I'll wait.......OK, thanks. If you're really ready, let's run this sucker. At the command line, type "./" (don't type the quotes), press enter, and you'll see a good deal of info come spewing back at you. You can also check /var/log/system.log and you'll see lines like the following produced by our script:

Apr  4 18:28:13 localhost Nightly[668]: maintenance complete

The output you see on your screen is the same information that will get sent to you via e-mail.

Last comments on this script: you may have noticed that I prefixed each command with its full path in the script, but usually don't bother when I simply call it on the command-line. Two reasons: First, we want to be sure we get the right binary, if there are multiple on our system. Secondly, it's a bit of a (good) habit: depending on how your script gets called, it may not have access to the environment, which means no path variable. So, absolute paths should go everywhere in a script like this.

Additionally, if you ever need to put a password or passphrase into a shell script (rare, but it happens), you should mark the file only readable by root ("chown root", followed by "chmod 700").

Schedule It

We don't want to have to run this manually every day, do we? (Shouts of, "No!" heard nearby) So, let's get this into cron.

A script like this will need to run privileged as root. There are a few ways to do this. We could drop it in root's crontab. We could drop a line in the system crontab. Or, as a variant, we could ignore messing with cron directly at all. They're all good methods, and which you choose really depends on your style. However, OS X already schedules maintenance tasks that run on daily, weekly and monthly schedules. We're going to take advantage of that.

We need our script to run on a daily basis, so let's move our script to the appropriate place:

sudo mv /etc/periodic/daily/
sudo chmod 550 /etc/periodic/daily/
sudo chown root:wheel /etc/periodic/daily/

That's all! Now, the system will run our script as part of its regular 3:15am daily maintenance.

Closing time

This month we learned how to create a simple shell script. This script runs through its commands in order, with no conditions or loops. I will say that this exercise glossed over a few small details, and completely ignored the fact that OS X Server already has a decent way to monitor free disk space (called "diskspacemonitor"), and do some of what we talked about (see /var/log/daily.out). This example script certainly isn't perfect, nor was it meant to be all-inclusive of every system administration ill. It introduced you to a few new commands. More importantly, it should give you ideas. It should allow you to create something that works for you.

You can now start to automate some tasks that are repetitive in your computing environment. Perhaps you need stats on processes chewing up too much CPU. Perhaps you need to monitor open file count. Whatever it is, now you have a way. Ask questions - here if you'd like. You can send in questions to Once you start automating, you start getting some time back. Time to read that new book on OS X, time to spend with friends and family, time to watch that new Battlestar Galactica episode, or time to rest. All fine goals, no?

Ed Marczak owns and operates Radiotope, a technology consulting company that asks, "how can we help you automate that?" Automate at


Community Search:
MacTech Search:

Software Updates via MacUpdate

Kodi 17.1. - Powerful media center tool...
Kodi (was XBMC) is an award-winning free and open-source (GPL) software media player and entertainment hub that can be installed on Linux, OS X, Windows, iOS, and Android, featuring a 10-foot user... Read more
Kodi 17.1. - Powerful media center tool...
Kodi (was XBMC) is an award-winning free and open-source (GPL) software media player and entertainment hub that can be installed on Linux, OS X, Windows, iOS, and Android, featuring a 10-foot user... Read more
Bookends 12.8 - Reference management and...
Bookends is a full-featured bibliography/reference and information-management system for students and professionals. Bookends uses the cloud to sync reference libraries on all the Macs you use.... Read more
Apple iTunes 12.6 - Play Apple Music and...
Apple iTunes lets you organize and stream Apple Music, download and watch video and listen to Podcasts. It can automatically download new music, app, and book purchases across all your devices and... Read more
Default Folder X 5.1.4 - Enhances Open a...
Default Folder X attaches a toolbar to the right side of the Open and Save dialogs in any OS X-native application. The toolbar gives you fast access to various folders and commands. You just click on... Read more
Amazon Chime 4.1.5587 - Amazon-based com...
Amazon Chime is a communications service that transforms online meetings with a secure, easy-to-use application that you can trust. Amazon Chime works seamlessly across your devices so that you can... Read more
CrossOver 16.2 - Run Windows apps on you...
CrossOver can get your Windows productivity applications and PC games up and running on your Mac quickly and easily. CrossOver runs the Windows software that you need on Mac at home, in the office,... Read more
Adobe Creative Cloud - Access...
Adobe Creative Cloud costs $19.99/month for a single app, or $49.99/month for the entire suite. Introducing Adobe Creative Cloud desktop applications, including Adobe Photoshop CC and Illustrator CC... Read more
MegaSeg 6.0.2 - Professional DJ and radi...
MegaSeg is a complete solution for pro audio/video DJ mixing, radio automation, and music scheduling with rock-solid performance and an easy-to-use design. Mix with visual waveforms and Magic... Read more
Bookends 12.8 - Reference management and...
Bookends is a full-featured bibliography/reference and information-management system for students and professionals. Bookends uses the cloud to sync reference libraries on all the Macs you use.... Read more

The best deals on the App Store this wee...
Deals, deals, deals. We're all about a good bargain here on 148Apps, and luckily this was another fine week in App Store discounts. There's a big board game sale happening right now, and a few fine indies are still discounted through the weekend.... | Read more »
The best new games we played this week
It's been quite the week, but now that all of that business is out of the way, it's time to hunker down with some of the excellent games that were released over the past few days. There's a fair few to help you relax in your down time or if you're... | Read more »
Orphan Black: The Game (Games)
Orphan Black: The Game 1.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0 (iTunes) Description: Dive into a dark and twisted puzzle-adventure that retells the pivotal events of Orphan Black. | Read more »
The Elder Scrolls: Legends is now availa...
| Read more »
Ticket to Earth beginner's guide: H...
Robot Circus launched Ticket to Earth as part of the App Store's indie games event last week. If you're not quite digging the space operatics Mass Effect: Andromeda is serving up, you'll be pleased to know that there's a surprising alternative on... | Read more »
Leap to victory in Nexx Studios new plat...
You’re always a hop, skip, and a jump away from a fiery death in Temple Jump, a new platformer-cum-endless runner from Nexx Studio. It’s out now on both iOS and Android if you’re an adventurer seeking treasure in a crumbling, pixel-laden temple. | Read more »
Failbetter Games details changes coming...
Sunless Sea, Failbetter Games' dark and gloomy sea explorer, sets sail for the iPad tomorrow. Ahead of the game's launch, Failbetter took to Twitter to discuss what will be different in the mobile version of the game. Many of the changes make... | Read more »
Splish, splash! The Pokémon GO Water Fes...
Niantic is back with a new festival for dedicated Pokémon GO collectors. The Water Festival officially kicks off today at 1 P.M. PDT and runs through March 29. Magikarp, Squirtle, Totodile, and their assorted evolved forms will be appearing at... | Read more »
Death Road to Canada (Games)
Death Road to Canada 1.0 Device: iOS Universal Category: Games Price: $7.99, Version: 1.0 (iTunes) Description: Get it now at the low launch price! Price will go up a dollar every major update. Update news at the bottom of this... | Read more »
Bean's Quest Beginner's Guide:...
Bean's Quest is a new take on both the classic platformer and the endless runner, and it's free on the App Store for the time being. Instead of running constantly, you can't stop jumping. That adds a surprising new level of challenge to the game... | Read more »

Price Scanner via

Updated iPad Price Trackers
Scan our Apple iPad (and iPod touch) Price Trackers for the latest information on sales, bundles, and availability on systems from Apple’s authorized internet/catalog resellers. We update the... Read more
12-inch 32GB Space Gray iPad Pro on sale for...
B&H Photo has 12″ Space Gray 32GB WiFi Apple iPad Pros on sale for $50 off MSRP including free shipping. B&H charges sales tax in NY only: - 12″ Space Gray 32GB WiFi iPad Pro: $749 $50 off... Read more
2.6GHz Mac mini on sale for $559, $140 off MS...
Guitar Center has the 2.6GHz Mac mini (MGEN2LL/A) on sale for $559 including free shipping. Their price is $140 off MSRP, and it’s the lowest price available for this model. Read more
SSD Speeder RAM Disk SSD Life Extender App Fo...
Fehraltorf, Switzerland based B-Eng has announced they are making their SSD Speeder app for macOS publicly available for purchase on their website. SSD Speeder is a RAM disk utility that prevents... Read more
iPhone Scores Highest Overall in Smartphone D...
Customer satisfaction is much higher among smartphone owners who use their device to operate other connected home services such as smart thermostats and smart appliances, according to the J.D. Power... Read more
Swipe CRM Free Photo-Centric CRM Sales DEal C...
Swipe CRM LLC has introduced Swipe CRM: Visual Sales 1.0 for iPad, an app for creating, managing, and sharing visually stunning sales deals. Swipe CRM is targeted to small-and-medium creative... Read more
13-inch 2.0GHz Apple MacBook Pros on sale for...
B&H has the non-Touch Bar 13″ 2.0GHz MacBook Pros in stock today and on sale for $150 off MSRP. Shipping is free, and B&H charges NY sales tax only: - 13″ 2.0GHz MacBook Pro Space Gray (... Read more
15-inch Touch Bar MacBook Pros on sale for up...
B&H Photo has the new 2016 15″ Apple Touch Bar MacBook Pros in stock today and on sale for up to $150 off MSRP. Shipping is free, and B&H charges NY sales tax only: - 15″ 2.7GHz Touch Bar... Read more
Apple’s iPhone 6s Tops Best-Selling Smartphon...
In terms of shipments, the iPhone 6s from Apple bested all competitors for sales in 2016, according to new analysis from IHS Markit, a world leader in critical information, analytics and solutions.... Read more
Logitech Rugged Combo Protective iPad Case an...
Logitech has announced its Logitech Rugged Combo, Logitech Rugged Case, and Logitech Add-on Keyboard for Rugged Case for Apple’s new, more affordable $329 9.7-inch iPad, a complete solution designed... Read more

Jobs Board

*Apple* Mobile Master - Best Buy (United Sta...
**492472BR** **Job Title:** Apple Mobile Master **Location Number:** 000470-Seattle-Store **Job Description:** **What does a Best Buy Apple Mobile Master do?** Read more
*Apple* Mobile Master - Best Buy (United Sta...
**492562BR** **Job Title:** Apple Mobile Master **Location Number:** 000853-Jackson-Store **Job Description:** **What does a Best Buy Apple Mobile Master do?** Read more
*Apple* Retail - Multiple Positions - Apple,...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
Fulltime aan de slag als shopmanager in een h...
Ben jij helemaal gek van Apple -producten en vind je het helemaal super om fulltime shopmanager te zijn in een jonge en hippe elektronicazaak? Wil jij werken in Read more
*Apple* Retail - Multiple Positions - Apple,...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.