A while ago I filled up my final unused memory slot in my awesome Mac Pro with an additional 4 gigorams (for a grand total of 16). Since then, whenever I reboot I’m showered with praise by the Memory Slot Utility for a job well done. This made me feel pretty good for the first couple months, but eventually it got old and I was ready to say goodbye for the last time. Googling around, I found the usual colorful variety of suggestions, ranging from “do a permissions repair” to “reinstall Mac OS X” to “reformat your hard drive”. Manual invocations of Memory Slot Utility as root (e.g. sudo open -a Memory\ Slot\ Utility.app) didn’t help, although it was obvious that it needed to twiddle some bit somewhere, and my hunch was that this was most likely failing for authorization reasons.

The winning move turned out to be logging in briefly as root. Generally not a good idea to log in as root, but in this case it’s the easiest way to clear this condition. All you need to do is enable the root account by setting a password for it, and then log in as root from the login window.

  1. In Finder, choose Go –> Go to Folder… (or shift command g), and enter /System/Library/CoreServices
  2. In the CoreServices folder, open Directory Utility.
  3. From the Edit menu, choose “Enable Root User”, and supply a password.
  4. Open System Preferences –> Users & Groups prefpane, and under Login Options, turn off Automatic Login, and set the login window display to Name and password.
  5. Reboot. Log in as root from the login window. Perform one final heroic click of Memory Slot Utility’s OK button, going for maximum style points.
  6. Log out, log back in as yourself, put settings back the way you like them. I suggest using Directory Utility to disable the root account.

SJ

Posted by dre on October 6th, 2011

I only worked under Steve’s leadership for a few years, and never spoke to him in person. Even so, he earned my respect for thinking big and really wanting people to *understand* what he was after. The technology is definitely just a means to an end.

I admire his dedication to building tools, both for developers and end-users. It’s pretty central for us as a species, and it’s been fascinating to see how such tools enable people to communicate better, find information better, organize thoughts better… all of it. Not to have cool gadgets, but to be empowered with abilities that would be impossible without the gadgets. And yeah, if you’re going to do gadgets, might as well make them beautiful.

For a while I was pretty conflicted about Apple’s direction with iOS and the conclusions one might draw about how it might affect the future of Mac OS X. I felt like my beloved computing environment was about to get dumbed down, and my concerns marginalized as an edge case. I still feel this way, but in the last year or so I’ve come to understand (and observe) that it’s totally worth it. Making an iPhone this easy to use means it gets *much* more widespread use than something else that might be more appealing (at least, at first blush) to geeks. The overall value of countless computer illiterates gaining access to iOS is surely far greater than the cost of some graybeards occasionally yelling about stuff on their lawns. My desire for people to be able to handle larger amounts of complexity in their computing devices seems completely selfish in retrospect.

So thanks, Steve, for the relentless focus on the ‘high order bit’. Your presence will be missed, but your message not forgotten.

Exploring web apps in Lion Server

Posted by dre on July 24th, 2011

There is some new glue in Lion Server to help manage infrastructure sharing between services, mostly targeted at web-related services referred to as web apps. This post aims to shed a bit of light on the ‘web apps’ layer to see how it interacts with the server admin tools and with launchd.

Much of what you need to know can be found in the man pages for webappctl and webapp.plist (the man page links only work on Lion Server). I won’t repeat what’s already there; go read them ;)

Going backwards

First, let’s take a look at a fairly vanilla config to demonstrate how to work backwards from a webapp configuration to find who / what it is. On a server with no (visibly configured) services enabled, let’s use webappctl to get a list of the web apps that are loaded:

bash-3.2# webappctl status -
web:webAppState:_array_index:0:state = "RUNNING"
web:webAppState:_array_index:0:virtualHostName = ""
web:webAppState:_array_index:0:webAppName = "com.apple.webapp.ACSServer"

What is this ACSServer? Looking at the com.apple.webapp.ACSServer.plist, we see:

bash-3.2# /usr/libexec/PlistBuddy -c print \
/etc/apache2/webapps/com.apple.webapp.ACSServer.plist
Dict {
    name = com.apple.webapp.ACSServer
    proxies = Dict {
        /AccountsConfigService/api/ = Dict {
            urls = Array {

http://localhost:31415/AccountsConfigService/api

            }
            path = /AccountsConfigService/api/
        }
    }
    sslPolicy = 1
    requiredModuleNames = Array {
        mod_rewrite.so
    }
    includeFiles = Array {
        /etc/apache2/httpd_ACSServer.conf
    }
    launchKeys = Array {
        com.apple.AccountsConfigService
    }
}

The “launchKeys” entry specifies the name of the associated launched job, com.apple.AccountsConfigService, so let’s look at that:

bash-3.2# /usr/libexec/PlistBuddy -c print \
/System/Library/LaunchDaemons/com.apple.AccountsConfigService.plist
Dict {
    Program = /usr/libexec/scsd
    OnDemand = true
    Disabled = true
    Sockets = Dict {
        Listeners = Array {
            Dict {
                SockFamily = IPv4
                SockNodeName = 127.0.0.1
                SockServiceName = 31415
                SockType = stream
            }
        }
    }
    UserName = _scsd
    ProgramArguments = Array {
        /usr/libexec/scsd
        -l
    }
    GroupName = _scsd
    Label = com.apple.AccountsConfigService
}

… lest you think this job should actually be disabled, don’t forget about the ol’ overrides file. Let’s query it to see if this job’s state is overridden there:

bash-3.2# /usr/libexec/PlistBuddy -c "print :com.apple.AccountsConfigService" \
/var/db/launchd.db/com.apple.launchd/overrides.plist
Dict {
    Disabled = false
}

We’ve determined what the associated process is (scsd) and that this webapp should be loaded based on the launchd config. Since it’s configured to load on demand, we might not expect to see the scsd process running; it’s not running on my system. There is a tiny man page for scsd. Don’t stop things you didn’t start ;)

Going forward

webappctl has a method called ‘tree’ that “displays the hierarchy of webapps declared by the requiredWebApps property.” Let’s look:

bash-3.2# webappctl trees - | fold -s

com.apple.webapp.ACSServer: com.apple.AccountsConfigService

com.apple.webapp.auth: com.apple.collabauthd

com.apple.webapp.collab: com.apple.collabcored1, com.apple.collabcored2,
com.apple.collabcored3, com.apple.collabcored4, com.apple.collabsandboxd,
com.apple.collabfeedd, com.apple.collabd, com.apple.collabd.notifications,
com.apple.collabd.quicklook, org.postgresql.postgres
. com.apple.webapp.auth: com.apple.collabauthd

com.apple.webapp.devicemgr: com.apple.devicemanager,
com.apple.DeviceManagement.SCEPHelper, org.postgresql.postgres
. com.apple.webapp.auth: com.apple.collabauthd

com.apple.webapp.mailman

com.apple.webapp.passwordreset: com.apple.passwordreset

com.apple.webapp.php: 

com.apple.webapp.podcastwikiui: com.apple.collabd.podcast-cache-updater

com.apple.webapp.webcal: com.apple.wikid.compatibility
. com.apple.webapp.auth: com.apple.collabauthd

com.apple.webapp.webcalssl: com.apple.wikid.compatibility
. com.apple.webapp.auth: com.apple.collabauthd

com.apple.webapp.webdavsharing: 

com.apple.webapp.webmailserver: com.example.placeholder, org.postgresql.postgres
. com.apple.webapp.php: 

org.calendarserver: org.calendarserver.calendarserver, org.postgresql.postgres

It might be tempting to think that the above is a complete expression of the dependency graph of related web apps. This is not true. For example, we see that org.calendarserver expresses dependencies on org.calendarserver.calendarserver and org.postgres.postgres. These two things are not web apps, but launchd jobs.

Diversion: just because you can…

So then, can we deduce that by starting the ‘org.calendarserver’ web app, we’d end up with a running calendar and postgres service? Well, we could, but we’d be wrong.

bash-3.2# webappctl start org.calendarserver
web:state = "RUNNING"
bash-3.2# webappctl status -
web:webAppState:_array_index:0:state = "RUNNING"
web:webAppState:_array_index:0:virtualHostName = ""
web:webAppState:_array_index:0:webAppName = "com.apple.webapp.ACSServer"
web:webAppState:_array_index:1:state = "RUNNING"
web:webAppState:_array_index:1:virtualHostName = ""
web:webAppState:_array_index:1:webAppName = "org.calendarserver"

Where’s postgres? What gives?

bash-3.2# tail -n 4 /var/log/system.log | cut -d' ' -f6-20
Reading configuration from file: /etc/caldavd/caldavd.plist
Neither EnableCalDAV nor EnableCardDAV are set to True.
(org.calendarserver.calendarserver[11258]): Exited with code: 1
(org.calendarserver.calendarserver): Throttling respawn: Will start in 59 seconds

Not so fast, smart guy. What makes you think you can just go around using new and mostly unknown tools for starting and stopping services, without being given express permission?! Don’t tell me you read it on the Internet. The point is that things are becoming more complex, and you really need to use the highlest-level interface available for doing things. In this case, that means Server.app or the serveradmin command line tool. In this specific case, the same Calendar Server software can provide both CalDAV (for calendaring) and CardDAV (for address book) services, but each is only enabled when they are configured to be enabled (in /etc/caldavd/caldavd.plist). It is only through Server.app / serveradmin that these config keys get enabled prior to loading the launchd job.

What about that dep graph again?

Now that you are sufficiently chastised, let’s get back to our example and see what happens when we start calendar server the right way, after first undoing the damage from earlier:

bash-3.2# webappctl stop org.calendarserver
web:state = "STOPPED"
bash-3.2# serveradmin start calendar
calendar:state = "RUNNING"
calendar:setStateVersion = 1
calendar:readWriteSettingsVersion = 1
bash-3.2# webappctl status -
web:webAppState:_array_index:0:state = "RUNNING"
web:webAppState:_array_index:0:virtualHostName = ""
web:webAppState:_array_index:0:webAppName = "com.apple.webapp.ACSServer"
web:webAppState:_array_index:1:state = "RUNNING"
web:webAppState:_array_index:1:virtualHostName = ""
web:webAppState:_array_index:1:webAppName = "com.apple.webapp.webcal"
web:webAppState:_array_index:2:state = "RUNNING"
web:webAppState:_array_index:2:virtualHostName = ""
web:webAppState:_array_index:2:webAppName = "com.apple.webapp.auth"
web:webAppState:_array_index:3:state = "RUNNING"
web:webAppState:_array_index:3:virtualHostName = ""
web:webAppState:_array_index:3:webAppName = "org.calendarserver"

Who said anything about com.apple.webapp.auth or com.apple.webapp.webcal, and where is postgres? Well, first of all remember that postgres won’t show up here, because ‘org.postgresql.postgres’ refers to a launchd job, not a web app. If we check launchd and a process listing, we see that postgres is indeed running:

bash-3.2# ps ax | grep -i post | fold -s
11452   ??  Ss     0:00.15 /usr/bin/postgres -D /var/pgsql -c listen_addresses=
-c log_connections=on -c log_directory=/Library/Logs -c
log_filename=PostgreSQL.log -c log_lock_waits=on -c log_statement=ddl -c
log_line_prefix=%t  -c logging_collector=on -c
unix_socket_directory=/var/pgsql_socket -c unix_socket_group=_postgres -c
unix_socket_permissions=0770
11459   ??  Ss     0:00.08 postgres: logger process
11461   ??  Ss     0:00.29 postgres: writer process
11462   ??  Ss     0:00.22 postgres: wal writer process
11463   ??  Ss     0:00.16 postgres: autovacuum launcher process
11464   ??  Ss     0:00.35 postgres: stats collector process
11837 s001  R+     0:00.00 grep -i post
bash-3.2# launchctl list | grep -i postgres
11452	-	org.postgresql.postgres

Ok, but what about the ‘auth’ and ‘webcal’ web apps? Well, calendar server is cool and has a nifty log that keeps track of what happens through its servermgrd bundle. Let’s see if it’s doing any webcal stuff:

bash-3.2# grep webcal /var/log/caldavd/servermgr_calendar.log | tail -n 1
[cal] 7/24/11 2:48:15 PM PDT : Changing com.apple.webapp.webcal WebAppState to START

We could then look at the webcal webapp plist to see that it also starts the ‘auth’ one. Whew, ok. Maybe you liked it better when it was mysterious and magical :)

The take home point here is that services can and do directly start web apps on their own. The policies controlling this behavior may be codified in the app, so you should have no expectation of being able to directly lay eyes on these policies, although you can get a good feel for it through experimentation. It’s probably a good idea not to use webappctl to twiddle the state of any web apps that you didn’t create, lest you invalidate somebody else’s expectations.

Mailman members only

Posted by dre on April 17th, 2011

Recently I had occasion to cook up some glue for a Mailman deployment that wanted a privacy and membership management policy that would not be facilitated by the Mailman mailing list software in its current form. We wanted to host a private list (disabling web subscriptions), and we wanted to allow any member to invite new members.

The solution comes in a few pieces:

  • a python script to synchronize the Mailman username / password credentials to an AuthUserFile that can be used by Apache to authorize access to a cgi that wraps the mailman add_member cli tool. Find the source here: mailman_cred_export.py. Put this in root’s crontab at some reasonable interval.
  • the aforementioned script that wraps the add_member tool. Find the source here: addmember.py.
  • this guy’s modified add_members cli tool. The add_members tool supplied by Mailman bypasses confirmation, but we want invitees to respond to a confirmation message before being added. This script makes that happen.
  • Disable web subscriptions by deleting stuff from /etc/mailman/en/listinfo.html

ATI 5870 now available!

Posted by dre on November 12th, 2010

and there was much rejoicing.

The Server Solution

Posted by dre on November 6th, 2010

Following Apple’s announcement of the XServe’s cancellation yesterday, there has been an expected amount of chatter revolving around Apple’s server-oriented efforts in general, and also specifically about Apple’s software and hardware offerings. As somebody who has lived and worked in the Apple IT world for a good while, here are some thoughts.

Over the years, there have been (in my opinion) two primary use cases for Mac OS X Server which both stem from the same underlying concept: any place where there are more than a few macs, those macs can benefit from some form of centralized binding element. The more macs there are, the greater the possible benefit. The two use cases I see are: 1) to provide a turnkey client management solution, and 2) to provide turnkey services. I hate the word ‘turnkey’ cause it sounds blingy, but in this case I mean it: the ratio of ‘ease of use’ to ‘features provided’ is definitely the key metric, and the key ‘win’ for OSXS.

The management use case has opened up a lot since ye old days, and now there are a variety of ways to perform client management that don’t even require Mac OS X Server. However, I would still argue (tentatively, as somebody who doesn’t do a lot of client management these days) that OSXS still provides the best ratio of ease of use to features provided, for client management. The need for client management absolutely still exists, and now there are more options. This is a good thing.

The ‘services’ side is more significant now than it used to be, because it wasn’t until the more recent server releases that OSXS provided services that really broke through and attained critical mass (this is mostly gauged by observing the mac IT community and its users). In my opinion, it’s not that Apple makes the best single wiki, calendar, mail, file, podcast production(, …) service, but that they are pretty good, integrated in one box, and … sigh… ‘turnkey’.

Time is money. Money is money, too. It’s pretty easy for a geek to be all like “pshaw, I don’t need all the autoconfiguration glue crutch annoyance water wing bumper car stuff that you call ‘added value’, I has the power of open source!”, and then proceed to provide all the solutions that are needed using a potpourri of software and perhaps even hardware. Usually, the skilled open source person wins in terms of the ‘absolute value’ of the features provided, and pretty much always loses in terms of the ratio of ease of use (from the implementor’s perspective) to features provided. “Ease of use” is important because it expands to “time, money”, but it’s easy to overlook as a skilled (especially open source) professional, because “easy” is a relative concept, and because *time* is a relative concept. Geeks might not mind plugging away at ${annoying_technical_challenge} all day long, where as most normal people would never think of it.

Of course, it’s possible to get off into the weeds with just about anything related to computers – and this certainly includes OSXS. However, with the right OSXS approach, it’s absolutely possible to deploy and maintain useful solutions, and only expend minimal time and money in the process. Many OSXS sites fit this description exactly, and many OSXS consultants make their living based on this concept.

I used to run my own private instances of all the network services I cared about, on a FreeBSD colo box on which I had root. It was fun for a while, and a great learning experience. Eventually it turned from fun to janitorial in nature – that’s when I got my DreamHost account, and I haven’t looked back. I now prefer the solution that conserves time and money while, and I still think that’s the primary win for OSXS, for its target audience.

The XServe will be missed, though. It’s some kickass hardware. For the people who actually have racks of XServes, eventually something will have to give. It’s simple physics :) Mac sales are only going up, so the big picture isn’t a lot different than it was last week in terms of *needs*. In terms of *options*, it is different. Just as the death of Apple’s XServe RAID did not spell the death of direct-attached storage for Macs, I’m hoping the same will be true for high-density datacenter-grade OSXS deployments. I’m as curious as anybody to see how this plays out…

“It won’t break…”

Posted by dre on November 3rd, 2010

” … it will break your batteries” says dogbert. This is what happens when you screw the battery cover on the apple bluetooth keyboard too tight! Can you guess which of the batteries below works reliably? :) (yes, these are both negative ends)

p.s. of course not ;) The one on the left is just a badly constructed battery. Not sure why I thought it was ok to play a joke on you, my loyal reader, but there you have it.

Mac OS X QA launches

Posted by dre on October 9th, 2010

New site; Mac OS X QA – Technical Q&A about Mac OS X and Mac OS X Server.

ATI Radeon 5870, where art thou?!

Posted by dre on August 9th, 2010

Want to buy. Can’t click button.

Starcraft II is running pretty nice in my current rig (MacPro4,1 + ATI Radeon 4870), but I’ve read that the 5870 is substantially faster – double the VRAM, too.

Why I closed my facebook account

Posted by dre on August 9th, 2010

I’m writing this so I have something to link to, so I don’t have to keep answering the question over and over.

Starting yesterday, I began to receive emails from various facebook friends, wherein they warned me that perhaps my fb account had been hacked. It seems my fb friends were getting invites for a ‘free ipad’ from me. I don’t have any way to tell whether my account has actually been hacked, but I was able to log in with my current password, change the password, and then disable the account.

I’ve seen this kind of thing before from other users… legit-looking invites that are probably faked somehow. I don’t really know, don’t really care, except that facebook has just become more trouble than it’s worth. I now retreat to platforms where messages are not sent on my behalf, ever. Feel free to follow me via Twitter @GuacamoleQueen. You can find my generic, life-oriented musings here: http://dreness.com

Somniac and a UI scripting quickie

Posted by dre on August 4th, 2010

Just about every time I want an AppleScript to wait a second or two during script execution, I instinctively insert a “sleep x” statement, where x is some small number of seconds. Every time, I’m surprised when I test the script and my computer promptly… goes to sleep. The command to use is delay, not sleep :)

Here’s a short bit of UI scripting I use to wrangle the MouseZoom prefpane, which I require prior to playing Quake4 to get just the right mouse acceleration curve. Even though it’s just an extra click-and-wait, the whole 32 / 64 bit prefpane shuffle has me kinda annoyed, hence this script.

tell application "System Events"
	tell application "System Preferences"
		activate
		set current pane to pane id "com.benhines.mousezoompp"
	end tell
	delay 1
	tell process "System Preferences"
		click button "OK" of sheet 1 of window "Loading MouseZoom…"
                             --that's an elipsis! accessibility inspector ftw
		delay 2
		keystroke tab
		keystroke tab
		keystroke ".02"
		keystroke tab
	end tell
end tel

GNU screen and white space, holy crap

Posted by dre on July 27th, 2010

GNU screen has been a key player in my workflow for a long time, and I’ve been putting up with a strange and very much undesired screen behavior for just about that long. I don’t fully understand the problem, but at least now I have a fix.

The problem is that when in screen, some ‘full-screen’ curses based apps like vim or mutt will cause screen to render empty space as white space… like for example all the space between the end of a line and the right side of the window. Normally this is not a problem. Who cares if it’s white space at the output rendering layer, right? Well, as it turns out, the guy on the other end of the clipboard really cares, even if you are that guy. Trust me. He’s actually kinda angry that it’s taken this long for his lobbying efforts to bear fruit.

Anyway, the fix is to employ the services of background color erase, known on the street as bce.

bce [on|off]
Change background-color-erase setting. If “bce” is set to on,  all  charac-
ters cleared by an erase/insert/scroll/clear operation will be displayed in
the current background color. Otherwise the  default  background  color  is
used.

The correct setting for me is: on, although I can’t really deduce that from the above description. Basically I just showed up in #screen on freenode, started mumbling, and somebody was like “… bce on?”, which was enough for me to arrive at the following .screenrc additions:

defbce on
term screen-bce

Here’s a short demo of expected behavior outside of screen, broken behavior in screen, and then fixed behavior.

SSL Passphrase in Mac OS X Server

Posted by dre on July 8th, 2010

Here’s a one-liner (spread across two lines for the 80 column internet) for mining Mac OS  X Server’s SSL passphrase out of Keychain:

security dump-keychain -d /Library/Keychains/System.keychain | \
grep '"svce"<blob>="Mac OS X Server certificate management"' -A 3 | tail -n 1

Typically this is most useful right before you say something like the following, which writes out a decrypted version of the private key (after you supply the passphrase, of course :)

openssl rsa -in key.pem -out decrypted-key.pem

				
		
				 
				

CalendarServer on Ubuntu 10.0.4 Desktop

Posted by dre on June 23rd, 2010

“Why should I read this silly article when I can just install the CalendarServer .deb?!”, you might be thinking. That’s easy. That deb is release 1.2, which is like a million years old or something. Lots of great stuff has been added since then, such as shared calendars and the integration of the formerly separate AddressBook server.

The concept here is to use apt to satisfy as many of the CalendarServer dependencies as possible, then let the ‘run’ script do the rest. I’ve tested this numerous times, and it works pretty flawlessly. I’ll have more detailed content later, but I just wanted to get the quick steps out there for any bleeding edgers out there…

1) edit /etc/fstab to enable xattrs by adding the “user_xattr” option.

e.g. (all on one line):

UUID=8f2bb850-0e8f-4d81-bba5-fb93ef9b9990 /               ext4    errors=remount-ro,user_xattr 0       1

after doing the above you need to reboot, or “sudo mount / -o remount”

2) sudo apt-get build-dep postgresql

3) sudo apt-get install python-setuptools python-xattr python-twisted subversion curl

4) svn co http://svn.macosforge.org/repository/calendarserver/CalendarServer/trunk CalendarServer

5) cd CalendarServer ; ./run -s

… at this point, if all goes well, you should be prompted with a message indicating that there is no config file. Run the suggested command to use the sample config file. You can then start the server with run -d, and run the protocol tests using the ‘testserver’ script.

VMWare Fusion 3.1 is way faster

Posted by dre on June 2nd, 2010

Check this out. I ran the ‘openssl speed’ benchmark in Ubunto Desktop 10.0.4 in Fusion 3.0.2 and again in 3.1. The difference is pretty impressive.

Of logs and non-boot volumes

Posted by dre on March 14th, 2010

It’s a beautiful Sunday morning, and as you wait for the coffee to start working, you figure it’s probably about time that you started on those benchmark results that have to be done by Monday. You’re sitting there thinking “MAN I wish I’d provisioned a larger boot volume for these Mac Minis, I keep filling it up with logs! Oh wait, I have a smart idea that I acquired from thinking! Maybe I can use the non-boot volume to hold the computer software logs, since it has SO much more space! Ok then, all I need to do is find the buttons for making a symbolic link from /var/log to /Volumes/foo/log, and then… it’ll work! Yeah!”

And lo, it did work, for a time. Imagine my surprise when 2 out of 20 of my mac mini-ons became unusable for my nefarious purposes of generating ical server load because the data volume used by the load simulator was somehow mounted read-only! The two failing minions also happened to be the two that were recently rebooted, after moving their power cables to different power circuits (to prevent blowing breakers, but that’s a whole other story). I didn’t ask for this crazy read-only nonsense!

Volumes get mounted read-only early at boot time, every time you boot, and that is normal. Usually, they are very quickly re-mounted in read-write mode, which is… ya know, more useful and stuff. My best guess at the fail here is that some part of the logging subsystem tried to open /Volumes/foo while it was still read-only, and SUCCEEDED when it probably should have failed. After all, what is the point of a logging system that mounts its log targets read-only, other than to prevent re-mounting of that filesystem read-write!

It appears that this happens. So, don’t do it, unless you wanted both no logging and a read-only data volume.

Recovering from this was not as easy as it should have been. On the first minion, I actually got beyond nuking /Volumes/foo until I remembered the /var/log symlink, so then I removed the symlink, re-created /var/log, and rebooted – this fixed minion number one. The SECOND minion was weirder. I removed the /var/log symlink, made a local /var/log, then rebooted – but /Volumes/foo still came back read-only! What?! Well I’m on a schedule so I just blew that one away too (diskutil eraseVolume), and then it came back ok – *after another reboot*. Funky.

Automator: Variable stacking

Posted by dre on February 12th, 2010

Shortly after discovering the existence of variables as real drag-n-droppable objects in Applescript Studio, I ran smack into a big limitation: the linear flow of an Automator workflow does not seem to allow for storing and recalling multiple values at once. Fortunately I was mistaken, as I discovered by accident while examining the ‘results’ view of each workflow object as it received data from upstream objects. We begin with a touch of background.

At first blush, the “Get Value of Variable” action seems like it can only really be used in conjunction with “Set Value of Variable”. You’d use “Set” to catch the output of some upstream object, and then store the value for later use.

set-value-of-variable

For those actions which do not support direct use of variable objects (e.g. “Name Single Item in Finder Item Names), one might instead try to pass the variable data as input, by connecting the input of a “Run Applescript” object to the output of “Get Value of Variable”, as long as you’re prepared to hand-write the stuff you need in Applescript.

That’s all well and good, until you realize that you need to use more than one variable in your “Run Applescript” object. For example, let’s say you’re writing a file re-namer – you might need to pass in the file extension of the ‘old’ file name, as well as the ‘new’ file name. “Get Value of Variable” can only recall a single variable’s value.

Here’s the trick: “Get Value of Variable” ALSO acts as a pass-through for whatever it receives on input, which allows you to stack multiple “Get Value”s, and then connect them to “Run Applescript”. In the “Run” object, the value of ‘input’ will be a list of the values received. In the below example, I’ve got a pair of “Get”s under another object which outputs a file / folder reference, then all of that output is dumped into a “Run” object. Those values are then accessed in the standard fashion: “the first text item of input”, “the second item of input”, etc.

get-double-stack

Finally, the “Get Value” behavior of accepting input can be disabled by control-clicking on the “Get Value of Variable” title text on the object.

get-value-contextual-menu

LDAP client: local static and variable mappings

Posted by dre on November 23rd, 2009

I was recently discussing Mac OS X / Active Directory integration with a friend, and one of the things I mentioned was the local static / variable mappings feature of the Mac OS X LDAPv3 plugin. After some fairly extensive internet searching, it appears that the only reason I know about that feature is because I learned about it in Apple’s official training courses about Mac OS X Server and Directory Services several years ago; in other words, there appears to be no public documentation of this, except for the Peachpit 10.5 Directory Services book (and probably the 10.6 version that is unpublished as of this writing). Until now.

This is all in the context of configuring LDAP mappings using Directory Utility, one of the many topics covered in this PDF from Apple. The following content would fit in around page 149.

In addition to configuring custom mappings by referring to existing attributes by name (e.g. repurposing an unused attribute), you can also create local mappings that are either static or dynamic. A static mapping for an attribute means that a specified text string will be returned when the attribute is queried, instead of checking the actual record on the directory server. A local variable mapping allows you to compose the value from a mixture of supplied text strings and also references to other attribute values.

Background: LDAP Mappings
First, let us visualize what a mapping is. To really see this work on your own machine, you’ll need to be connected to some real LDAP service. Check out these steps if you’re unsure how to get at the LDAP mapping configuration in Directory Utility. In general, the process of ‘mapping’ is used to express relationships between the schema of different directory systems. There is a ‘standard’ name space that is used by Mac OS X to describe things that it needs to talk about (e.g. the name of the attribute that holds the user id). This standard name space is so-called because it is agnostic of any specific directory data storage backend. There are also ‘native’ name spaces for each backend that are used to refer to the things in that directory store.

Let’s say I have a user account in an LDAP directory, and I want to look up the unix ID and the value in the ‘comment’ field. The ‘standard’ names for these attributes are UniqueID and Comment. You can find the full definition of Apple’s ‘standard’ name space on page 273 of the aforementioned PDF.

{28} andre@donk [~] % dscl /Search read /Users/dre UniqueID Comment
Comment:
 just this guy, you know...
UniqueID: 42

If we add the -raw option, we see the name space that is associated with the attributes:

{29} andre@donk [~] % dscl -raw /Search read /Users/dre UniqueID Comment
dsAttrTypeStandard:Comment:
 just this guy, you know...
dsAttrTypeStandard:UniqueID: 42

dsAttrTypeStandard is the prefix for ‘standard’ attributes. Now let’s look in the LDAP mapping configuration to observe how these standard attributes are mapped to native attributes on the LDAP server:

user-comment

For this LDAP configuration, whenever we get a query for the Comment attribute of a user record, we will look up the ‘native’ attribute named ‘description’. Using dscl, we can ask for things using either the native or standard name.

{30} andre@donk [~] % dscl -raw /Search read /Users/dre \
UniqueID Comment description UidNumber
dsAttrTypeNative:description:
 just this guy, you know...
dsAttrTypeNative:UidNumber: 42
dsAttrTypeStandard:Comment:
 just this guy, you know...
dsAttrTypeStandard:UniqueID: 42

To change the mapping, simply add or remove items from the right-side list. One common use case for a customized mapping is when the Mac OS X client is connecting to a directory service that doesn’t have a defined attribute for storing a piece of data that is required by Mac OS X. You might choose to  instead re-purpose an existing but unused attribute to store this data. To pull that off, you simply add the mapping for the appropriate ‘standard’ attribute, using the native name of the re-purposed attribute.

Local Static Mappings
Suppose that you want all clients to use the same specific value for a given attribute. In this case, a local static mapping will do the trick. Let’s say for this example that I want to create a local static mapping for the “Street” attribute. I currently have no value for that attribute in my user record:

{32} andre@donk [~] % dscl -raw /Search read /Users/dre Street
No such key: Street

Let’s add one. Click “Add…” under the right-side list. Normally this is where you’d type the name of some attribute. To treat the supplied text as a literal value instead of an attribute name to look up, prefix with a hash sign (#).

user-street

Now when we do the same query as before:

{37} andre@donk [~] % dscl -raw /Search read /Users/dre Street
dsAttrTypeStandard:Street:
 Shakedown Street

This also demonstrates that you’re allowed to have multiple mapped values, although the results aren’t that interesting yet… read on.

Local Variable Mappings
Local variable mappings are just a twist on the above. A good example is using a variable that represents the user’s short name to compose a home directory path. Click “Add…” and enter the text #/road/to/$uid$. Next, drag the entry you just created above the existing homeDirectory entry. The order in this list determines the order that results are returned. For attributes that are supposed to be single-value (like this one), that means that the requestor will only get the first result.

user-nfshomedirectory

{40} andre@donk [~] % dscl -raw /Search read /Users/dre NFSHomeDirectory
dsAttrTypeStandard:NFSHomeDirectory: /road/to/dre
/Network/Servers/host.orange.com/Volumes/yowza/dre

At the Open Directory layer, we see that there are actually two values returned – our local variable mapping, and also another (obfuscated) result that came from the LDAP server. What happens if we actually request this data using a ‘real’ directory services client?

{2} andre@donk [~] % cd ~dre
cd: no such file or directory: /road/to/dre

We see that ‘cd’ only gets one result – the first one in the list. Of course it’s a dead end, because this is just an example!

Don’t forget…
Everything you’ve seen here is 100% client-side, and only applies to the computer you used to configure the custom mappings. If you find yourself running around configuring custom mappings on a bunch of computers, you are probably doing it wrong – in this case, please check out the handy “Write to Server…” button. This publishes the custom mappings to the LDAP server where they will be automatically downloaded by other Mac OS X Clients – provided that the LDAP server has the required support for hosting this data; it wants to put this data in a record under Config called macosxodconfig, in an attribute called ‘description’. Here’s a nice techworld article that provides an example of all this from start to finish.

php 5.3: short_open_tag default has changed!

Posted by dre on September 24th, 2009

Snow Leopard Server includes an upgrade of PHP to version 5.3. This version has a changed default for the “short_open_tag” option as compared to the version that shipped in Leopard server. The difference is that short_open_tag is now disabled by default, which means that the following will not work:

<?
phpinfo();
?>

The problem is the opening <?, which is in ‘short’ form. The long / normal form of the open tag would be <?php. If you don’t feel like editing all your scripts, you can simply declare the following in your /etc/php.ini:

short_open_tag = On

To further illustrate the change, consider the following command results, produced on a Snow Leopard Server that was upgraded from Leopard:

bash-3.2# grep 'short_open' /etc/php*default*
php.ini.default:; short_open_tag
php.ini.default:short_open_tag = Off
php.ini.default-5.2-previous:short_open_tag = On
php.ini.server-default:; short_open_tag
php.ini.server-default:short_open_tag = Off

eggdrop1.6.19+ctcpfix

Posted by dre on July 6th, 2009

Not exactly new, but since I’m the eggdrop maintainer for macports, and since I haven’t updated this port for almost 3 years… here ya go!

Macports users may sudo port -d selfupdate to retrieve the updated Portfile (and new patch file).

Details: https://trac.macports.org/ticket/20198