Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: wwdc2007-503
$eventId
ID of event: wwdc2007
$eventContentId
ID of session without event part: 503
$eventShortId
Shortened ID of event: wwdc07
$year
Year of session: 2007
$extension
Extension of original filename: mov
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: ...

WWDC07 • Session 503

Scripting for SysAdmins

Information Technologies • 1:06:47

Every IT professional has to perform repetitive tasks. Mac OS X supports a number of scripting languages so that you can automate many of these tasks. Learn from Apple engineers how to build valuable scripts in Automator, AppleScript Studio, Python, Ruby, and UNIX shells to save you time.

Speakers: Steve Hayman, Jeff McCune, Tim Perfitt

Unlisted on Apple Developer site

Transcript

This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.

Scripting for SystmAdmins. We had a good crowd last year. I think we got a very good crowd this year. I think you're a better crowd this year. Very much so. Already feeling the love. So, a couple of things here. Big, big session. Huge session. Big, huge people that are up here doing great things. All right? New scripting ideas. So new stuff that you can learn for this. New scripting methods. We got very, very current. We have Ruby on Rails.

Here now, Ruby on Rails. Some stuff that can hopefully help you out tomorrow, some stuff that can hopefully help you out a month from now. A little mix of web, a little mix of system administration, a little mix of comedy. So last year we got a lot of feedback. We had some cool stuff, but all of these scripts weren't made available. So this year, if you reach under your seat, You'll find a DVD. Nobody's doing it.

This was the whole joke. You would reach under, you wouldn't find it, I would yell at Steve. He would, Steve, he would say that he put him in the wrong room. Because we're in Nob Hill, but we really put him in Russian Hill. And then we'd all get up and walk to Russian, yeah.

So, but I'm serious about that. We will make all this code available. That's definitely what we're doing with this through a couple of various sites. So we'll talk about those as we go through. So you will have all the scripts and all the samples that we use up here. So we definitely very much wanted to give that to you.

If the only thing I do is tell you that and you clap, I'm happy. All right, so three great people for you today. We got the ineffable Steve Hayman. talking about cool stuff to do with scripts, little neat tips and tricks, things like that. We then have presenting for the first time ever, Jeff McCune. You may know him from the Mac Enterprise Group. He's from Ohio State University.

is going to show you how to pull strings with Puppet. Ooh. Probably something you might not have heard of. Great little Puppet fans in the back. And finally, we have the amazing Mr. Tim Perfit reprising his role from last year. And this time, he's doing Ruby on Rails. Wonderful. All right, without further ado, he's Canadian so this is scripting from A to Z. Steve Hayman.

Big huge people, thanks a lot. Big huge people. How many Canadians are here? We're glad that for once WWDC is not on a Canadian long weekend. Isn't that nice? Not civic holidays, not Victoria Day. Don't need to take off our shirts. I may not have time to get all the way from A to Z. We only get A to K today, so I'll do my best here.

So people come up to me and say, Steve, what is scripting? And I say, come on, Sal, you're the product manager. You've been here for a long time. You should have this figured out by now. By the way, the new green Apple, we are reusing old jokes from WWDC 2001. So that was an old WebObjects joke.

I think scripting is telling other programs what to do. Here's an example of telling other programs what to do. This is a nice, obvious piece of sample C code that tells the finder to go and do something. You could do that, or you could do this in AppleScript. I think even if you don't speak AppleScript, you might be able to look at that and have a rough idea what it does. What does it do? It tells the application finder to reveal the startup disk.

New in Leopard, you can even use other languages like Ruby, which will inspect the dictionary of these scriptable applications and give you a different syntax for talking to the same things. If you are one of those people who think that AppleScript's way of handling files and strings and so on is a little peculiar, you may prefer to do this work in Ruby or Python. There's nice bindings for those. And why do we write these? I think we happen to write scripts because we've got personal problems that need solving.

Maybe our users are bugging us for something, and if we have time, maybe we would like to help the users rather than write our own scripts. I don't know. I'm pretty busy, but sometimes I'm willing to do my job. And we can also quit waiting for vendors to fix stuff. Just between you and me, there are a couple of issues in Tiger that I have come across over the years in helping out with large deployments, and rather than waiting for Leopard, we can sometimes come up with a workaround.

Tons of languages out there. So many scripting languages. In fact, I bet that several have been created since WWDC started. Just when you think you have a handle on what a good scripting language is, along comes Perl, and then Python, and then Ruby, and Lua, and Erlang. And I have a message to the script language developing community. Would you slow down for crying out loud so that we can get caught up and learn just one of these? Pick a language and get good at it. Pick a language and get good at it. And we've got lots of choices in Mac OS X.

Plenty of places you can put scripts, too. The most obvious is things you can click on. I think that's what we usually think of for Apple scripts, anyway. Things you can click on and they do something. But there's lots of other places to hide scripts, too. The script menu that I'll talk about a bit, a way to categorize scripts according to what application is front most. Automator is a big scripting engine.

Apple Remote Desktop has some scripts that you can see in our session on Thursday. There's login hooks and launch the agents and podcast producer workflows. Man, if you're a scripter, podcast producer is something you're going to love. But I want to talk about a few of these places we can actually put some of these scripts. And let me show you one example right now. This is what I do all day. We're on the demo machine here. This is the kind of thing I do.

All day, I look at the screen and I win. I like writing scripts and I like iChat. Who doesn't like iChat? Anybody not like the iChat? You always see iChat. So, Script Editor is your standard AppleScript development environment. And you can certainly write ordinary boring programs like this set.

Let's see, set the sign to 1 and set p to 0, and then repeat with-- the i from 1 to 10,000, where is he going with this? Set p to p plus sign times 1 over i, what the heck, set sign to minus sign, this is doing some screwy math thing and it's waiting for a second and it's done.

That's a -- pardon me, set sign to 1, pardon me, this is doing some kind of peculiar math and then waiting for a second in a big loop. And you can write programs like that with AppleScript but it gets a lot more interesting when you start talking to other applications.

I want to tell the application iChat to set my status message. To this string, pi is approximately equal to... P times 4. End. If we run this now, all your buddies who have you on their script menu will be totally impressed by your studly scripting prowess as your status message constantly gets in closer and closer approximations to pi.

You really shouldn't clap because this is just about the worst series for approximating pi there is. There are much better tools that converge a lot faster for approximating pi. In fact, I bet you didn't even know there were tools out there that in hexadecimal can give you a particular digit of pi without computing all the others. Isn't that neat? You could figure out the one trillionth digit of pi in hex without having to compute the first-- let's not do that one.

Let's think of some others. So I happen to think that setting your iChat message is an interesting way to just broadcast your scripting coolness to all of your colleagues because they're going to see that your status message is constantly updating. I collect things like this. Here, you know, I was watching Forrest Gump the other day and got motivated to write a little script here that just loops through all the different ways to prepare shrimp.

This is very handy so you can follow along with the... Shrimp kebab, shrimp creole, gumbo, pan fried, deep fried. Now this is all the sort of thing you can do today in Tiger. In Tiger, you can send scripts to iChat to tell it to set the status. In Leopard, Leopard has a great new iChat thing where you can have a script that hangs around waiting for an incoming message in iChat.

You can say, wait until I receive a message, and your script is sent the string of the message and the sender, and then you can do something. You can run a command, you can look something up, you can send a reply. So I'm not gonna show you this, but I have another Leopard machine over here.

I want to talk to this other account. iChat demo-- this other machine is running over here. And it's actually an iChat Hangman server. So I can play Hangman in iChat. And you'll notice the status message, an E, a T. Zed. No Zeds. Oh, see, look, it's updating the little picture here with the hangman guy. It only took about three radars to get that to work. Cue.

D, give up. Screechbird? Screechbird? What kind of a word is screechbird? But I wanted to show you this as an example of the kind of things you can do now in Leopard. You can build some little information service using iChat. People can send commands to it. It can do something and give you back some interesting results. So I think iChat's an interesting way to mess around with scripts. I want to go back to Slice for a moment, please. Not for a moment, for a while. Let's go back to Slice.

So no, no, no, no. Come on. Slides, yeah. No more iChat demos. Great. Thanks, Tony. Everybody be sure to come to Tony Graham's session and ask him hard questions and sit in the front row. Now, another way to do scripts is to write these .command files. These are simply terminal commands that you type and you put in a file, and if somebody clicks on it, it opens up terminal and runs the command right there in the middle of the terminal window. I've got to tell you, this is a little bit unsatisfying. It's nice that you can double-click on a script like this, but that UI is for determining how full my boot disk is.

It's not really going to win any prizes. Fortunately, AppleScript has what must be my favorite operator in the entire AppleScript world, DoShellScript. Now, there are people who think that this is cheating, that this is not real AppleScript. Once you're running DoShellScript, I do not care what they think.

This is allowing me to get my job done and run Unix commands in the AppleScript context. You give it a string, it runs the task, and it hands the output back. Anything that you might type in the command line, you can use with DoShellScript. That last one there is a convenient line that will count. out the number of words in the online dictionary file, for instance.

We've also got, and we're all admins here, we've also got do shell script with administrator privileges. Woo-hoo. This is a way of telling AppleScript to run the shell command as somebody other than yourself. Normally, if you did this, the output would be your username. Who am I? Simple UNIX command that just returns your short username. But if you say instead, do shell script with administrator privileges, when you run a script like that, an authentication dialog like this pops up. Anybody can fill in a username and password of an admin, and the script itself will actually run as root.

This is the key to writing interesting AppleScripts as admins, packaging up things that require admin authorization in a handy way like this. So I think you can build much more sophisticated GUIs by combining some of these things. For instance, there was my original terminal command to decide how full the disk is. Here's the AppleScript version. We run it, we get a window like that, and next year I'm looking forward to being rewarded for that particular script.

Way better, way better. Note that it doesn't use terminal. People get these confused sometimes. Do shell script actually runs the command in the background. You don't see it running, you just get the output. Here's an alternative. You can tell terminal to do something. The syntax is a little bit different. It's do script rather than do shell script. This will actually launch the command in a new terminal window.

You might want that if you had a long running command like top that was never gonna complete. You might want that if you were launching an interactive FTP session or something and you were expecting the user to type the password or interact in the terminal. So keep in mind that there's two different ways you can do this. I gotta tell you, 90% of the time I'm using the first one 'cause I want one of the little tasks in the background.

So that's what the second one looks like. If you say do shell script date, it launches a new terminal window and runs the command right in the middle of the window. Sometimes handy. It also waits until the command finishes. Sleep 3600, what does that do? UNIX command does nothing for an hour.

In fact, that's what I do. I just need to put that command on my monthly report. You know, tested this command for an hour. Do shell script will wait until the command finishes. So if you've got to get going, you might want to put the command in the background.

The traditional UNIX way is to use an ampersand to run a task in the background. Doesn't quite work the way you think. You have to construct this peculiar syntax that you see in the third example there of redirecting both standard output and standard error to dev null and then putting the command in the background. And that is a way with do shell script you can successfully launch something in the background.

I think the major nuisance with all of this is that much of AppleScript is dealing with these lovely colon paths. Who likes the paths with the colons in them? Who's a UNIX person that can't stand that? Yeah, alright. I, uh, Tony likes them. You can come and beat up on him here.

Many things in AppleScript are going to return one of these HFS style paths. Your friend, if you do not want an error message like this, when you try to pass that path, your friend is this operator, posix path of, that will take one of these colon paths in AppleScript and turn it into a normal path with slashes in it.

Don't try to do it yourself. You'll never quite get it right. But this is a feature built into the system that will let you move from one to the other. So anything you do in AppleScript that comes with one of these colon paths, you probably want to use posix path of before you pass it to shell script. But, Users love to create files with all kinds of screwy characters in their names. Dollar signs, spaces. My God, files with spaces in their names. I used to hate that.

Exclamation marks. File names that are going to mess up the shell. The shell has a series of characters that it cares about. The blank space, the dollar sign, braces, the pipe symbol. Those are all special to the shell. And if you don't quote them properly, if they're part of a file name, bad things will happen. So your other friend, in addition to POSIXPATHOF, is quoted form of.

Quoted form of will take a string, will find all the special characters for the shell, will put a backslash in front of them. The single quotes, the double quotes, the dollar signs. People sometimes try to do this yourself. You'll never get it right if you try to do it yourself. The shell interprets more weird characters than you could possibly imagine.

And that's exactly what this is for. So I would say any time you've got input that came from the user, they chose a file or they typed a string in a dialog box. Before you send it to a UNIX command, I think you want to protect it with this quoted form of operator.

If you think this is just the most fascinating topic ever, have I got a tech note for you. This tech note goes into a huge level of detail on a do-shell script and all of these subtleties. And believe it or not, there are even more obscure subtleties we could talk about, but we're not going to.

Now, you can click on things or you can, I happen to prefer locating them in the script menu. The script menu is a nice way to organize scripts so that the ones that are relevant to the frontmost application appear at the top. I have a bunch of scripts I've written that work with Finder.

I have some others that work with Terminal. I have some others that work with Mail. And if you set up the script menu, this is the AppleScript utility program. If you set up the script menu in this way, you get a little S icon in the menu bar.

And you'll notice that in this particular screenshot, the Finder is the frontmost application. So the top four scripts are all scripts that relate to the Finder. Then you have all your other scripts down at the bottom. This is a great thing that I wonder why more people don't use to organize your scripts in a context-sensitive way. Let me show you. If we go back to the demo machine, let me show you a couple examples of that kind of thing.

I'm tempted to play Hangman again because it's so much fun. So this is my scripts menu on this particular computer. And if you organize your scripts menu in this way, if you have library, scripts, applications, and then subfolders for the different application names, you could have scripts for the finder over here, and then the script menu will have those at the top. But if we switch to iChat, the script menu has iChat-related scripts at the top. If you switch to Mail, it has Mail-related scripts at the top.

So you eventually build a fairly large collection of these things, and this is a terrific way to actually organize them. I'm a big script menu guy as a way of working around missing functionality in certain programs. Have you ever noticed that iChat tends to truncate your status message at something like 43 characters? If you're not careful, you don't notice it, but your friends do. Your friends notice that you've created some extremely clever status message that seems to be chopped off in the middle of the word. Well, I have a little script here that creates a non-truncated status message. Amen.

Boy, I really like WDC this year because it is so much fun to-- anyway, you try to set that to your status message, this is going to tell you that's too long. It'll get chopped off there and give you a chance to write in a shorter one. I think this might be actually fixed in Leopard. I'm not sure. But there's something about the iChat protocol that truncates status messages. So little scripts like this will keep you out of hot water.

Yeah, that's a good one. I think maybe I'll go back to the ways to prepare shrimp. That was much more exciting. But let me show you a couple others. For instance, here is a great way to incur the wrath of the IT department. I'm sending a message to everybody at Apple. Cute cat pictures.

drag in some tremendously large files like that to go to the entire company. The IT people, your phone will ring very quickly after you try to do something like this. But how about this? How about a script? This is actually an Automator workflow, but they can appear in the script menu as well.

How about a script that lets me choose a file I have an emergency backup joke ready. I may have to get out the emergency backup joke. This Canadian guy and this Iranian guy went to a German restaurant. and the Canadian guy says the Iranian guy-- oh, sorry. Hang on. Here we are.

I want to add those files to this message, but what I wanted to do is to actually copy them to my .mac public folder first, which this script is doing. It's copying those large files to my .mac public folder. and figuring out the URL of those files and adding the URL to the mail message.

You can do a lot with this. You can have a hot folder that you drop things in and it copied it to .Mac and put the URL in the mail message. This is not a bad way to send out big files to a large group of people. I've often wished for a mail application that figured out how to do this kind of thing automatically, but until I have that, I got this. I'd like to go back to slides, please. If we have time, we'll finish the joke about the Canadian guy and the Iranian guy at the German restaurant.

Now, we all have users that are running in a managed environment where we restrict what programs they can run. You can run these, but not others. You've got work group management, you've got parental controls, and they all key off of bundle identifiers in Cocoa applications. If an application does not have a bundle identifier, and scripts do not, you cannot manage it in this way.

Scripts are ordinarily flat files. However, I want to suggest that if you save a script as an application instead, which you can do in Script Editor, it now looks like this. It's got the contents and the resources and everything. It's got an Info.plist in it, and in that Info.plist, if you were to add a CFBundle identifier with a unique string, you've turned your script into something that can be managed.

If you don't do this, you can't deploy a script in a managed environment. It will not run, and you cannot add it to the list of approved apps. If you do do this, suddenly your script becomes something that can be managed. I'll go back to the demo for a moment here.

I've got a script here that can't be managed. One of my friends here is in the front row, and he once sent his iChat status message to, you can't spell very sexy without XServe. I thought, wow, that was pretty good. He must have spent a lot of time thinking that one up. Surely we can have a program that can do this kind of thing for us. So there's a little application. You can't spell Dave Lopata-- and Dave Lopata.

This is just a little example application that I've written. I can set my iChat status appropriately. But if I were to try to make this a manageable script, I can't do it. I go to system preferences here and I have a managed account. If I try to add this particular application, You can't spell. That's actually an application. Now, it does not work with the limitations you have selected. It does not have a bundle identifier.

That's easy to rectify manually if you want, but I got a droplet. I can drag a script without a bundle identifier on a droplet, and it will say, "Oh, what do you want the bundle identifier to be? How about that?" Okay, this script now has a bundle identifier and can now be managed. I could drill back into Terminal here, or pardon me, to System Prefs.

And I want to add this account to my managed parental controls. This particular application, I mean, located again. Isn't this fascinating? Where is he going with this? Let's try that again. So the Canadian guy says to the Iranian guy, "What are you having?" And the Iranian guy says, There, it's now successfully been added to the list of manageable applications. If you don't do this, the app can't be managed. There's plenty of simple things you could do as manageable scripts that you want to add this way. Can I go back to slides, please? All right, I want to run one last idea past you here.

AppleScript and Root. We all have problems that could be solved if only our users were able to run one particular command as root. They've got some runaway process we'd like them to kill. We need them to be able to create a folder. We need them to run some peculiar command as root, and we do not wish to go over there and run that command as root ourselves.

We have a large deployment in the Northeast of thousands of iBooks, and someone calculated once it would cost over a million dollars to send a technician out to each machine just to push the power button. So if you can think of a way to have an admin task work, you can save a million dollars, and you can share it with the guy who told you how to do it.

One way you could do it is to make every user an admin. I think it's a bad idea. You could do that. Then do shell script with administrator privileges would work for everybody. Another way is to put the admin password directly into the script. You can also do this. Supply a username and a password. This is an even worse idea. It works, but people will eventually figure out what the password is no matter how hard you try to obscure it in there.

I got a better idea. You know the sudo command? sudo on the command line normally lets people run commands as root provided that they are an admin and provided they type their admin password. What sudo does is to collect that password and then run the command as root.

What if we messed around with the sudo program? sudo has this little-known config file called sudoers, which describes the rules by which the sudo command plays. Normally, it says members of group admin can execute any command they want, that's the second line, as root, provided they type the password. However, you can actually add, in a peculiar, bizarre language, you can add your own entries to this.

You can specify certain very specific commands and say users are allowed to run this exact command and this one only as root with the sudo command without typing the password. That's what that no password colon in that config file means. Think of all the problems that this could solve if you distributed a file with your one special repair command in that sudoers file. Be very careful with this file. Do not let them run the shell as the command or the RM program.

a couple clicks away, but as an administrator tool, I think this could be pretty useful. So, here's an example. Despite our best efforts, clocks get out of sync from time to time. I believe if you boot a machine and it's not on the network, the network time daemon does not start correctly. If the machine later joins the network, it still does not start correctly, and the clock is now wrong.

This can be fixed by typing sudo ntpdate -u, but your users don't know an admin password, so how's that gonna work? Well, what if you put that line in the sudoers file? Now, any user would be able to type that command to fix the clock, but if they don't have terminal access, you could certainly write a little Apple script that simply said, "Click here, "and I'll fix the stupid clock for you," and then it ran that command.

They don't need to be admins, they don't need to be root. Because you've set up the sudoers file, certain very specific commands will run as root. I think this is a handy technique, and I wish I'd found this out several years ago. There are some very complicated hacks I've come up with that could have been simplified by this. Now, just in closing, I wanna tell you, I got a little carried away.

Apologies to Phil Collins, there's an app that's been on my mind all the time, Sudo Studio. It's a little application that lets you specify the command line, and it will both write the necessary string to sudoers, and it will create the trivial AppleScript for you and set it all up for you.

I'm going to make all this stuff available post-conference, and thank you for your interest. And I'd like to turn things over now to a UNIX hacker from Ann, Ohio State. Is it Ann, Ohio State University? Oh, I'm sorry. The, excuse me, the Ohio State University, Jeff McCune. Thanks, Steve. Right hand.

So I'm Jeff McCune, and I'd like to talk to you about Puppet, which is a new automation tool that I've been using for the past year. So a little bit about myself first. I'm one of the network administrators at the Maths Department at Ohio State University, and I'm currently responsible for about 200 Mac OS X workstations, about 12 UNIX servers, and I've got 250 faculty, staff, and graduate students that I support. So this keeps me pretty busy on a day-to-day basis.

The problem that Puppet is trying to address is the sneaker net. So the sneaker net is good for moving a 120 terabyte database from one location to another, but it's not really well suited if you're a network administrator and you need to walk around to each of your machines and apply the Office 2004 patch. So Puppet helps by configuring machines quickly and easily regardless of how many of them you have.

I started off with Puppet at Ohio State about a year ago last summer, and I needed to quickly install software packages on all of my machines. So we were doing software updates to Firefox and things like this, and the problem I was facing was that I wasn't quite sure if the faculty and the grad students were using the machine at the time, if it was a laptop, if it was even in the department.

So I needed a way to centrally configure the packages and make sure that all of my machines would download those and install them. So Puppet handled this great. I was able to update all of my machines quickly, and I decided that as more problems cropped up in the department, I would go ahead and try to solve them with the help of Puppet. The end result was that after about six months in December, I found out that everything I was configuring on a Mac OS X was not working.

So I had to go back to the Mac workstation, was being done with Puppet. So I had achieved complete automation. I could net boot a machine, and I didn't have to touch it after that. Puppet went ahead and configured everything for me. So that ended up saving me a lot of time.

Here's some information about Puppet itself. The main website is puppet.reductivelabs.com. It's written by Luke Caines, who is a veteran system administrator who was frustrated with existing tools at the time. So he started working on Puppet a few years ago, and he founded Reductive Labs in 2003 in order to offer professional support and consulting services. Puppet is open source software. It's written in Ruby, and it's got a fairly large community of users and developers who are willing to exchange ideas and the scripts that they've written, so that's a pretty good resource.

There's a few existing tools out there that also try to address the problem of managing a large number of machines. In particular, FileWave and Landesk deploy software in patches. RadMind takes a slightly different approach. It keeps machines in a known good state by synchronizing all of the files on the hard drive. CFEngine is probably most similar to Puppet. We were using that at the math department prior to Puppet.

And it's described as a multi-purpose adaptive system configuration engine. I'm not quite sure what that means, but that's from the CFEngine website. I would describe it more as a framework for downloading shell scripts and making sure that they get run on all of your machines. And then finally, custom scripts do get the job done.

So here's sort of a comparison of the tools I just mentioned. Puppet is more of a jack-of-all-trades, really. It tries to help you automate anything that you might do as a system administrator to a large number of machines. So I started out with package installation, and it's pretty good at that and keeping my machines up to date. It doesn't support Windows yet, although it is written in Ruby, and Ruby works quite well in Windows. We don't really have Puppet support in Windows, but that might be added in the future.

Puppet also doesn't support any inventory tracking or asset tracking yet, but it does have some features that might lend itself to that in the future, and it is open-source software. CFEngine I have marked as poor for package installation and software updates because it really leaves you to do all of that yourself.

So when I was using CFEngine on our Mac workstations, I ended up writing shell scripts anyway to do all the package installation. CFEngine doesn't support Windows, and it doesn't have any asset tracking, although it is open source. So I'm going to show you how to use open-source software.

And then we have FileWave and Landesk, which are commercial products, and they're particularly good at software installation and updates. That's what they're designed to do, actually. And they're also good if you have a mixed platform. So if you support Windows and Mac workstations, FileWave and Landesk are pretty good at that. And they do also provide inventory tracking if you need to track your purchases.

Finally, Radmind takes a slightly different approach. It's particularly good at managing machines that are identical in nature. So if you have a lab or something like that, it's good at installing all of the files initially, but I found it was a little bit cumbersome to do small updates on each machine. So I have it marked as OK for software updates. And it does currently support Windows, but it doesn't have any asset tracking.

So here's the big picture about how Puppet works. It's similar to a lot of other tools in that it's got a client and a server. So in the math department, I have one master server that all of the workstations connect to every 30 minutes, and they pull down their configuration. So on each client, I've got this agent installed, and it makes a connection over a standard secure HTTP connection, and it uses the XMLRPC web service to transfer all of the information back and forth.

Puppet is particularly good if you have a general standard operating environment that needs to be tweaked slightly for different roles. So in the math department, I've got a role for the graduate students, a standard operating environment for them, a role for the staff members, and a role for the faculty. So this allows me to install different applications for different people quite easily.

So here's a little bit more detail about how Puppet is working on an individual machine. The first thing that happens is when Puppet needs to configure that machine, it will collect a list of information about the particular workstation. And Puppet uses a separate library called Factor to get all of this information.

And the information will contain things like the IP address of the machine, the MAC address of the Ethernet interface, the amount of memory in the machine, if it's an Intel or a PowerPC machine, things like this. The Factor library is also very easy to add additional information if you need to track different things.

So something I've been hoping to write but haven't gotten around to is something that tracks the serial number on every machine. Once Puppet collects this list of information about the machine, it will upload it to the Puppet Master server. And the Puppet Master then takes over, and the scripts that you and we as a system administrator write are more general for the entire network.

So I usually configure the Puppet Master to install packages if it's an Intel or a PowerPC machine. So if it's an Intel, I'll install the 1049 universal update. But if it's a PowerPC, I'll have the 1049 TI update installed on that machine. So the manifest is more of a general picture of your entire network.

And the Puppet Master takes the facts that are uploaded and puts them in the Puppet Master server. And generates a unique and dynamic configuration for that machine, which it sends back. So the Puppet client, once it has this actual configuration that contains things specifically tailored to it, will actually go to the work of configuring that machine for you. So this might involve downloading packages, copying files from the Puppet Master, or making sure that a local administrator user is created for you, things like this.

So this is how I sort of got started with Puppet on the math department. First, I just needed to do package installation, and I was able to quickly do that with Puppet. And then I added managed printers on all of our machines. So I needed a way to configure all the public and private printers in a particular faculty member's office. And Puppet helped me out with that quite a bit.

So I also update our login hooks quite a bit. And Puppet allows me to copy down the updated shell script and configure the login window, which we'll see a little bit later on. And then finally, I set up the open firmware password to secure the machine and make sure that it's bound to our LDAP directory. So in total, this only ended up being a few thousand lines of Puppet. It really saved me a lot of time because for the complete configuration for OS X, it didn't end up being that much work to completely configure everything.

So Puppet has a simple syntax. Here we're just going to manage two different types of things. We're going to install a package and make sure that a file is actually deleted. So each thing that you manage will have a name. And in this example, we've got the Firefox, which is the name of the package we're installing, and the source file that we're going to get that from. And this DMG will contain a standard Apple installation package inside of it. And then we're just going to make sure that it's installed.

So when Puppet runs for the first time, if Firefox is not installed, it'll go ahead and install it. And then on later runs, it won't do anything because Firefox is already installed. And this also allows you to update the package later on. You just need to change the version number of Firefox, and you can easily install that on all of your machines. With the Etsy no login file, this is sort of different. We're telling Puppet here to make sure that this file doesn't exist. So it's deleted on all of the machines.

Something I would frequently do is when I would log into a machine to do some work, I'd touch this file in order to make sure that the user didn't log in and start working while I was fixing their machine for them. So I'd forget to delete their machine.

So I'd forget to delete their -- delete this file that I'd touched when I was done working, and the user would be locked out of their machine, and I'd get a nasty phone call. So now I just make sure to run Puppet when I'm done working on any of the workstations in the department, and it goes through the trouble of deleting this file for me and making sure that the machine is usable by the customer.

So under the hood, Puppet is doing quite a bit of work for you. With a package in only the four lines that you saw earlier, Puppet downloads the DMG file to the temp directory. It can download this from the master server itself or from an HTTP server or copy it from an AFP volume, things like that.

Once it's downloaded it, it mounts the DMG with the HDI util command, and it does this in a way that's private to the finder, so the user doesn't get any interruptions while they're working. If this is happening in the background, they don't see the disk image pop up in the finder.

And then Puppet looks inside the DMG, checks for any packages, installs them with the HDI command line installer, and when it's done with that, it ejects the DMG and cleans up the temp directory. So quite a bit of work is done for you automatically with just a few lines of Puppet script.

With the file, Puppet behaves a little bit more like RadMind or... or rsync. The configuration that it receives from the Puppet master server will contain a timestamp and a checksum for each of the files that Puppet needs to manage. So if the local workstation is out of sync, the timestamp or the checksum will be different, and Puppet will make a backup copy for you, then synchronize the file from the master server and enforce any permissions that you might specify. So if you need to make sure that the file is owned by root and not readable or writable by any of the users, Puppet will make sure that that happens for you.

With the executable scripts, Puppet's actually sort of nice because it allows you to mix and match these with the other package resources and the file resources. So you can do order of operations, and if you already have existing shell scripts that you've written to do some of the work, Puppet can automatically call these for you, and you don't need to sort of throw away the work that you've already done. So that's the Puppet script.

So here's an example of something that I do frequently with Puppet. This is setting MCX settings on the local machine. So we don't have an open directory server set up currently, and what I'll need to do is set a lot of default values. So if I need to enforce a password on the screen saver, or if I need to configure the login window to execute my login hooks, then I need to run the defaults command to configure these things.

So with Puppet here, we're telling it to enforce these settings, and what it will do is first check the current setting on each of the machines, and if it doesn't exactly match the value that we want it to, we'll use the defaults write command to set that for us.

So this is sort of a quick and easy way to get around the lack of an open directory server if you don't have one. And then we can reuse this MCX setting later on. So with this example, I'm actually managing the complete login hook in the math department. So on all of my machines, I frequently will update my shell scripts that run when people log in in order to fix small problems like a lock file with Thunderbird or something like that. And there's really three pieces to this.

So first, we need to make sure that the iHook package is installed, and this provides user feedback to the user when they log in. And then we need to actually synchronize the shell script that I've written to all the machines. So that's the file. resource here which will check the the time stamp and the checksum on every single machine every 30 minutes and then download that if it's changed.

So we're going to put that in the temp directory and then make sure that it's executable and that it's owned by root and wheel so that the users can't see what's inside. And then once we've installed the the ihook package and downloaded the shell script from our central server we need to actually configure the login window to execute this shell script when somebody logs in.

So here we're going to use the MCX setting that we previously defined and configure the actual login hook parameter of the login window to point to the actual path of the shell script. We've also got these requirement statements in each of these so that Puppet is smart enough to know that if it couldn't install the ihook package then the shell script probably won't work correctly.

So we shouldn't bother to try and copy the shell script or configure the login window if any of any of that didn't work. And likewise if the file didn't download correctly we don't reconfigure the login window to actually execute it. So Puppet saves you a lot of time with that.

If you're interested in getting started with Puppet, I have a few recommendations for you. You don't actually need to set up a Puppet master server. Puppet works just fine as a standalone client, so you can download that to your laptop right now and start playing around with it.

I'd also recommend that you start small and pick something that you constantly do to a workstation. For me, it was just installing and updating packages. And then if Puppet can help you out with that quite well, you might be able to grow that and automate other things later on.

And then finally, Puppet, like Mac OS X Server, does require some good DNS, at least initially, for the certificate generation. But if you're in a dynamic DNS environment, once you have the initial certificate, you can change host names and Puppet will still work in a secure way. So it doesn't actually check the fully qualified domain name if you're in dynamic DNS. So thank you very much for your time. I'd encourage you to email me or ask some questions after the session.

If you have any questions about Puppet. We're also working on a Puppet recipe manager, which is sort of like a CPAN interface for Perl, but to share and exchange recipes for how we're configuring things with Puppet. So that might save you some time as well. So thank you, and I'd like to introduce... I'd like to introduce Tim Perfitt, who's doing some really cool stuff with Ruby on Rails. Thanks, Jeff.

I'm Tim Perfitt. I'm a systems engineer in Southern California. And how many people are excited about Rails and Ruby on Rails? All right, think about what Steve Jobs said yesterday that there's no SDK for the iPhone. Well, I disagree. I think there is an SDK, and I think it's Rails. And it comes installed on Leopard Client and Leopard Server.

So you can quickly develop these Web 2.0 apps and deploy them on your iPhone. So just imagine you're walking around with your iPhone, and you say, "I want to reboot every machine in my lab from the beach." And you press a button, and all your machines reboot, and you get -- your phone starts ringing because all the students are pissed off at All right.

So whenever we think about writing dynamic web pages, right, we think JavaScript. And if you notice in Steve Hayman's presentation, JavaScript wasn't listed as one of the languages that is up and coming or that you might want to learn because, I mean, I don't want to learn JavaScript because it's very specific to web browsers.

And I hate web browsers because they're all different, right? I don't like web programming because you got to write one app and have all these if statements, if it's Internet Explorer, if it's Netscape, if it's Safari. And so I've run away the other way. So we're not going to write any JavaScript today.

Actually, we're going to write a lot of JavaScript, but we're not going to actually write it. It's going to be written for us with Rails. So this originally the idea of this came up from the session last year. We talked about how we could dynamically image machines using a Web 2.0 Ajax app. And I had a customer come up to me and say, I have a lab worth of machines that are all sleeping. And I wake them up at maybe 8 o'clock at night and I send out some commands to them.

The problem is you've got to be on the same subnet to do that. So he bought a copy of ARD, which makes me very happy because I like selling people copies of ARD. But all the ARD did is sit on the instructor's machine and wake up. He'd ARD into the instructor's machine, get on ARD there, and then wake up the lab. It didn't really seem a good use of $500. So there might be a better way to do this.

So one way you could do it is like, OK, just from your office, SSH into the instructor's machine. Just type SSH, whatever user account. And then there's a great command line tool called Wake on Land. And you just type in the MAC address of each one of the machines, and then they all wake up.

So the customer was very happy. He ran through the app. And he's like, OK, I'm going to do this. No, not really, because it's probably the worst way to do it. But let's look at a better way to do it. So we can always do just a web page that allows you to do this. But what you really want to do is deploy a web app that looks like a desktop app. And Rails exceeds at this. It allows you to embed JavaScript and AJAX asynchronous requests.

And so you're dynamically updating the elements of the page. And so I wrote this little app that allows you to-- we can see there's status indicators that tell you if the machine's available on the network. All it does is sends a ping in the background. If it receives a reply back, it will turn the indicator green. Otherwise, it's red. It will have some status indicators, basically all the elements of a desktop app that you would expect.

But I mean, that's great. You can have Steve Heyman write you an AppleScript app to do that. And I'll give you his email address. It's [email protected]. Or you could write it in something that's cross-platform, a browser. I mean, who's going to have a browser? And you think about the iPhone, if you're running Safari on it, you basically point it at it.

And because it's just JavaScript and these asynchronous AJAX requests, you can just run it from your iPhone. So I'll be doing this at the end. And so what I want to do is walk you through kind of how to start off with Rails and creating a Rails application and then demo this at the end. So you can run it on your iPhone as well.

Okay, so before we get started, I just want to do a quick brief of how the URL scheme kind of works with Rails. So if you have a webpage, you enter a URL, example.com slash main slash index. That actually, it's called RESTful. The URL actually means something. Instead of having this kind of, you know, ampersand percent, web objects, ID, oh, I'm sorry, did I say web objects? Okay. Just this kind of cryptic hexadecimal thing. It actually makes sense. So you have slash main slash index. Main is the name of the controller, basically your code.

And then index is the name of the method that you're going to run within the controller. So it sends it off to the controller. You have this really simple shell command. We use the back text to actually run it. And then it takes the output, the variables that are set inside the methods, or actually go to the view. You have access to them. You can make them look pretty. And then ships it back to the browser. So that's what actually we're going to look at.

Okay, so let's actually look about how we write this code and a little bit about erb, which is the embedded Ruby language. This is most of the other languages, Pearl, Python, those kind of things actually allow you to be able to write code within HTML and have it rendered within the page. So that's in Ruby, you'll see the less than percent, it means run this Ruby command.

You see less than percent equals means run this Ruby command and put the output of that command in the output of the page. So this is where the magic all happens, the form remote tag, what it makes it just a Ruby command within HTML that allows you to create a form or starting of a form and it'll run a JavaScript command in the background asynchronous off and do it.

And you can see it's the URL is actually an action, which is process request. Process request is just name of a method. So you write a method over there, as soon as you click on, you submit this form, it's going to run this method. Very simple, but other things you can do within this is that you can have all these other sections to this request that are other JavaScript requests. So before you run the command, you can do something else. After you run it, you can do something else. You can, if it fails, you can do something.

If it completes successfully, you can do something. This is all embedded within your HTML. So that means that you can have all these JavaScript requests go off, updating status indicators and, you know, actually doing the work or, you know, maybe throwing up a dialogue box saying that there was an error asynchronously. And you can have this loading page. You have little, you know, widgets happening on the page.

So in this example, I do it before and we actually, I lied a little bit, we're writing as much JavaScript as I know, which is the alert message. So alert command unsuccessful. And that will probably pretty much be the limit of it. And then when it's completed, it will run another function called command completed. So we have two methods. One is called process request. One is called command completed. And then we actually have to have an HTML element we operate on. And that's this. Okay. So we have a host. Oh, I don't actually have that.

That will come later. Sorry. It will actually have the host name that you type in the MAC address. It's a very simple example. But you can type in the MAC address and then when you hit the submit tag, we'll be able to button that says do it. So very simple. You'll have a form and we'll actually Mach this up really quickly.

Okay, then the actual methods. This is the one that was in HTML or ERB, the embedded Ruby. And this is the actual method in our controller. So the process request, it'll call the wake on LAN command with the host that the user typed in. And then this is where the really dynamic part comes in. You get passed in your code an object called page. And page, you can operate on the HTML elements.

So if you have a paragraph tag with an ID, so you have less than, P, ID equals, whatever, paragraph, you can operate on that dynamically. So you can replace the HTML. You can put an image there. You can move it around. You can make it swing around. You can make it disappear. You can make it poof. I don't know if you've seen the demos of the Wiki site, but there's a lot of that dynamic Web 2.0 stuff that's going on that you can do very easily if you're handed an object that's the actual page.

So now, you notice we're not doing like, if Internet Explorer is version 6.2, then do this. This is much more, for me, much more fun programming, because you can actually get in and replace the element in the view. And you're acting on it like it's a real view, not this web-based view.

All right, so we get this object called page, and we can do a couple of things on it. We have page, and then within brackets, indicator. All indicator is is the ID of that element on the page. It's called the DOM element. So if you have your paragraph tag, less than P, ID equals indicator, now we can operate on that element within the page and replace it, make it into a picture of your kid, make it zoom up to the top, whatever you want to do. And Rails also has some ability to do dynamic animations.

So we can do visual effects like fading and those kind of things. And then also within the view, there's the element that I was mentioning before. This one's just the div tag, and we give it an ID so we know how to reference it. All right, so let's actually do this. It's much more fun to do it than to see it.

Before I get started, the code is going to be available so if people want to follow along on some of this, it's going to be located. Oh, sorry. Can you actually see me? This actually goes much smoother if you can't see what I'm doing. Ah, there we go. So the code is actually on my site. It's called 2canoes.com/wwdc.zip. And I take it-- Joel, are we gonna make this available somewhere else? No, I'm trying to. I don't have this build. I'm holding control and scrolling. It doesn't work. Okay, Command-Shift-8-plus-plus-plus. No, I can't.

2canoes.com-slash-WWDC. We'll get that to you in some other place. All right, so let's get started. I do know how to make the terminal bigger, though. There we go. So this is where the magic starts. So I'm on a Leopard, the build you guys got and hopefully installed on your primary machine.

( Transcript missing )

What did he do? Oh, my-- oh, I love that the num lock's on. Isn't that great? Okay, Rails. So you just type "Rails" in the name of the app that you want to create. So this is on a standard Leopard build. I didn't install anything.

There's a great app called Locomotive that you can download for Tiger that would kind of set everything up for you. But on Leopard, you just type "Rails" and we'll call it "Wake Me Up, Please." And it'll go ahead and actually create all the files for you for this application. So now we have a wake me up please directory. Let's go into it.

Okay, we'll open it up in the brand new finder and we'll do it in Cover Flow view. No, not so much. Okay. Yeah, Rails doesn't lend itself real well to the CoverFlow view. Okay, so it did create a couple of things for us. It created a whole bunch of things.

But there's lots of Rails books out there. I'm not gonna go into every little nook and cranny of it. But for me, this is amazing. We're actually in the directory and we'll give it the, there's a scripts directory. You can see here, scripts, and then we'll give it a name.

Here are scripts. And they give you a bunch of scripts to generate code for you and to start a server up. And one of the other things they said is that yesterday is not only do we have Rails but also Mongrel, which is a web server that allows for quick, rapid development. So if we do script-stats-server, it'll start up a web server for us and it'll give us a nice URL to it. So we gave... Oops.

( Transcript missing )

Let me start writing some code. So the other thing I'm going to use is TextMate. Oh wait, I want to, yeah. Use TextMate to actually do this project. TextMate is what the Rails community has really embraced because it allows you to see your whole project on the right side and it does some very cool text editing. So if you haven't used it, check it out.

So let's go ahead and create our code. So we want to create a controller and we want to create a method. And I want to call it index just because that's kind of the default way to load if you don't type anything. So we'll give the command, again, we go to the scripts directory. scripts, our script, generate.

and we'll call our controller main and we'll do a method index. Oh no, we got to generate a controller. Okay, so then it goes and it creates it and you go back to text edit, you'll notice that we now have a controller and we also have a layout. So this is really, it's even getting even more exciting. So now we can go here and we got to go to our controller main and it'll do the index stuff for us. Oh, we actually got to start the web server. Yay.

Hey, isn't that exciting? Now we have not quite the dynamic page we're looking for. But you can see this iterative element we're running. Now we have our own code. See, it says find me in apps, view main indexed at our HTML, which is nice for it to tell us. So let's actually go in. We can actually see it says there, find me in-- can you see that? Let's actually put in something that's a little bit more interesting. We'll replace that and we'll put in just some HTML. Whoa, you can't see that.

and a few more. So basically your standard HTML you have the document type, you've got a header and a body section. So the magic that comes in here is we have a JavaScript include tag. That just means load up the JavaScript library to use JavaScript. And then we're going to do that same thing we did in example, the former tag action or URL action process request. So now if we actually start this up, oh it's still running, that's fine. So we can just reload it.

Stop it. Reload it. Save, okay. Look at that. Luckily I've memorized my Mac address on this machine. Zero, zero, zero, zero. And that didn't do anything because we don't have any method associated with it. So let's go add a method. So in our main controller we have an index method that was created for us that doesn't do anything.

So let's add one called process request 'cause that's what our ERB calls. So this is very simple. You can see that it just has one of these cool Ruby loops. If you haven't learned Ruby yet, you're required to do that before next year. There will be a quiz.

And it sleeps a little bit and then it calls the wake on land. So now it actually does something. So let's actually run it. I did save it that time. And I say wake up. Okay, it actually worked. Yay! Okay, now let's give some feedback. Obviously we wanna do some feedback to be a little bit better.

So let's add a different body section. So we can do the more dynamic pieces to it. Okay, so now instead of having just go off and do this request, we now have a before section as well as a when it's completed. So let's actually save that. Refresh just because refreshing is always good. And put in a request. That's actually not enough hex digits, but it should now go off and actually, oh, do we start the server? Let me see.

It's not working there. There is, I did find a bug in Safari where the before JavaScript does not actually always render correctly. So let me quickly open up Firefox and see if that helps us better. What was that joke about the Canadian and the Iranian? Okay. All right, let me try saving and then we'll quickly move on. Oh, I'm sorry, I didn't put enough code in. Oh, Spotlight's indexing, thank you. And this is running on a FireWire drive, so.

Okay, so that's why it didn't work. You actually gotta have the methods that make the nice things happen to do that. Okay, so not only do we process the CREST request, but we actually replace a couple of things. So we did these same ones. There's a status element called replace HTML. We're gonna save some text, sending magic packet, and after it's done, we're gonna say it's sent. We're gonna fade it out after a two-second delay. So let's, I'll hold my breath. are sending magic packet. It sends it and then it fades away. Okay, that's kind of nice.

So now envision that on your iPhone. You just press a button and you wake up a machine. And so let's actually go and, let me see, I think I'm at the bottom. So let's actually look at the one that's kind of, we'll put the pie in the oven and then immediately take it out and it'll be cooked. And we'll see.

Oh, I want to use the cool, uh, whoa, boing, whoo, look at that. FlowView, yay. OK, oh, sorry. Am I actually projecting? Oh, I am. Okay, I should pay attention. Okay, so I just CD'd into that through the magic of drag and drop, and I'll do server-- or sorry, script, server, and start this up.

So this is the sample code I gave you. If you just download it and you run server script, it should start it up and give you the URL. And we should refresh it, or... There it is. Do you see the little swinging indicators? That's a JavaScript request that's going out and doing it. I'll refresh again just because I like watching that, and I'll do it one more time because it's just that cool. Look at that. So this is how many people are annoyed by animated GIFs of all types on the Internet, or on the web at least.

This is on AJAX and Rails. They're a wonderful thing because I don't actually have to tell this image to start doing it. I just replace it with that image, and then I hide it when I'm done and replace it with another image. So it very easily can do that. It's just sending a ping off, and if it's correct, it'll come back and set its status as green. And I was going to put this one to sleep. Sleep.

Don't panic, don't panic. Oh, red, yay, okay. So now, yeah, thanks, I got a red indicator. Let's wake it up and then it'll be better, right? Okay, here we go. I have to stand back and do this. Hey, I hear a hard drive swinging up there. And it should update. See this processing on the bottom there completed? And it updated it and came back.

So of course I couldn't let things go. I said, "Okay, I got this great thing. I can wake up computers." But one of the things I can do now is I can run all sorts of other commands. I can use SSH in to go into the machine and maybe grab a picture of the desktop.

And maybe if they have an eye setting or a picture of them, I can reboot the machine. So let's go actually go, I'll do it on my machine itself. And you got to give, unfortunately, you got to give a username and password due to these security things they put on computers these days.

And let's go ahead and take a screenshot of what I'm currently working on. So you can see it done. SSH is in to the other machine, takes a screenshot, brings it back, and actually puts it in line in the table. So now you can see, oh, look at this.

Yay. I couldn't do that, so you have like, is that student over there using MySpace? And you do a screenshot. Like, we need something, so we take them to the PTA or whatever to get them in trouble. So we'll take a picture of them, and we'll use big honking techs, like, "Hi, hi." And then it replaces it and it comes in place.

That got me thinking that earlier, a couple days ago, when Steve Hayman and myself were practicing for this, I thought, Steve, can you go ahead and give me an admin password to your machine so I can do some testing? Because I was always curious what he works on when people aren't watching, and he likes to show these great Hangman games. But let's actually see. He's on his machine right now, I think. Let's look at what he's doing. Yeah, that's the username and password I did.

So let's actually do a, let's make sure he's there, and we'll do a picture of him. Let's see. Oh, let's see. I'm reading some flashbacks. Okay. And he's been a little distracted, so let's actually see what kind of scripts that he's working on. Okay, let me see. Okay.

and the Automator workflows he's doing. That's why I keep getting those messages with those Paris Hilton images. So anyways, the code's going to be available to be able to look over. Thanks very much. Now I'd like to bring up Joel Renick to talk to you more about question and answers. Wonderful. Thank you, Tim.

Some resources here that we have about Ruby. We're a little Ruby heavy this year, but that's topical. It's cool. Next year we'll pick something else that we can hit on a little bit. A couple of things. I'll post a link on AFP548.com to the locations of all the code that we talked about.