North East Bytes - a Microsoft technology usergroup in North East England.

Tweets

Powered by Squarespace

Wednesday
Jun182008

Scripting/Sysadmin Meme

I've been called out by Richard to fill in Steven Murawski's Scripting/Sysadmin Meme, so here it is...

How old were you when you started using computers?

I'm only guessing here, but I think I was about 8. I was in junior school anyway.

What was your first machine?

The first machine I used was the BBC Micro Model B at school, then my friend got a BBC Master with a whole 128k which we put to good use playing Elite. The first machine that was actually mine was the spiritual successor to the BEEBs, the Acorn Archimedes A3000.

What was the first real script you wrote?

The first code of any kind I wrote was in BBC BASIC - it was a text adventure game and was neither long nor good. I'm not sure what my proper sysadmin script was, but I have a feeling that it could well have been one that populated our brand new Active Directory with user accounts in 1999. A bit like jumping in at the deep end!

What scripting languages have you used?

I mostly used VBScript (with a bit of JScript from time to time) for a bunch of years before PowerShell came along. Now it's all PowerShell, all the time.

What was your first professional sysadmin gig?

Well I (along with a friend) was the IT support for the school (when I was about 8) because the teachers didn't know what they were doing, but I wasn't paid so it was hardly professional, although it did get me out of assemblies, so that was some reward. Then I suppose I could count some work I did on some Apple machines in the theatre/sports centre where I worked in my teens. It's probably more reasonable to say the job that I've been in for the last 9 years, which is a proper sysadmin gig.

If you knew then what you know now, would have started in IT?

If I knew then that all the hard slog around the cluster rooms, building hundreds of NT4 workstations with Ghost boot floppies and disk images on CD, would lead on to the success and growth of our systems in the Active Directory era, and that we'd be able to expand into different areas and services with basically the same number of people running them; firstly I wouldn't have believed you, but I think I'd have been as excited about being part of the industry as I am now! This isn't a great job for someone who fears change, but if you love technology, it's a great roller coaster ride!

If there is one thing you learned along the way that you would tell new sysadmins, what would it be?

Definitely get involved in the IT community. Join user groups, go to the TechEd event in your region (or, what the heck, why not another region) and try to learn as much from people in the hallways or the dining room as you do in the formal sessions (I think a week at TechEd is better value than any training course). Communicate with peers any way you can. If you're not in a position to meet people physically, chat online with them; comment on blogs, participate in online forums. It may not pay off immediately, but it will pay off.

What’s the most fun you’ve ever had scripting?

Ever since I started to really get PowerShell, it's been almost non-stop fun. Finding out how very much you can achieve with how very little code is like a game on top of the puzzle of actually solving the original problem.

Who am I calling out?

Jonathan Walz and Chris Warwick

Friday
May232008

R2 or not R2, that is the question

If you want to access the OS version of a computer you've got a few options. The easiest way in PowerShell is to use the Get-QADComputer cmdlet from the excellent free set of Quest AD cmdlets. However, you'll find that you can't tell the difference between Windows Server 2003 and Windows Server 2003 R2.

In order to find out which of your servers are running R2 (if you want to audit your licences for example), you'll have to use WMI and access the OtherTypeDescription property of the Win32_OperatingSystem class. This one-liner will do the job for you (just alter the search root to match your Active Directory structure):


get-QADComputer -searchroot "yourdomain.com/servers/sql servers" | `
%{gwmi -Class win32_OperatingSystem -Namespace "root\CIMV2" -ComputerName $_.Name `
-ea silentlycontinue} | `
sort version,othertypedescription -Descending | `
ft @{label="SERVER";expression={$_.csname}},@{label="OS";expression={$_.caption}}, `
@{label="R?";expression={$_.othertypedescription}}, `
@{label="SP";expression={$_.servicepackmajorversion}} -a

 

What it will give you is a handy table like this:


SERVER    OS                                                       R? SP
------    --                                                       -- --
SPURS     Microsoft(R) Windows(R) Server 2003, Standard Edition    R2  2
PISTONS   Microsoft(R) Windows(R) Server 2003, Standard Edition    R2  2
LAKERS    Microsoft(R) Windows(R) Server 2003 Standard x64 Edition R2  2
CELTICS   Microsoft(R) Windows(R) Server 2003, Standard Edition        2
CAVS      Microsoft(R) Windows(R) Server 2003, Standard Edition        2
HORNETS   Microsoft(R) Windows(R) Server 2003, Standard Edition        2

 

Footnote:
That's fine if all of your servers are going to allow that incoming WMI query. You may have servers which are tightly locked down and you'd prefer not to open them up. If that's the case, you can do what we do and query the WMI locally on the server and write the results out to a database as part of a startup script (we currently do this in VBScript). If you take this approach, especially if you have a lot of servers, be sure to make the date part of the record so you have an idea how good it is.

Saturday
May172008

Pipelines of Objects: Adding Power to the Shell

I'm writing this to help anyone wondering about PowerShell, and those just getting started and struggling with the paradigm-shift that the PowerShell pipeline represents. What does it mean to have a pipeline of objects? It's a prominent bullet-point in the PowerShell marketing, and while it may instantly make sense to developers and computer scientists, it's not a straight forward concept for everyone. I thought of an analogy which I think will help...

Say you're on your way home from work and your spouse calls to ask you to stop on the way for a new light bulb to replace a dead one in the bed-side lamp. In order to make sure that you get the right bulb, your spouse is going to have to describe it in a fair amount of detail: bulb style=candle, bulb height=short, wattage=40w, fitting type=screw, fitting size=small, glass type=pearl, glass col=white. Basically, your spouse is going to give you a load of strings of text to describe the different properties of the bulb that you need.

I'm going to assume we have a cmdlet (a PowerShell command, pronounced "command-let") called Buy-LightBulb and we'll use PowerShell syntax to describe what our spouse is saying on the phone, but this basically is the pre-PowerShell way of working:

Buy-LightBulb -bulbstyle candle -bulbheight short -wattage 40 -fittingtype screw -fittingsize small -glasstype pearl -glasscol white

Now let's imagine that we got home before our spouse got round to calling. Instead of describing all of those properties for the replacement bulb, they could give us the old one as a reference. After all, it has all of those properties.

So let us assume that we've got the old bulb in a PowerShell variable called $oldbulb. If we piped $oldbulb to Get-Member, we'd see something like this, showing that it has the properties and methods that we'd expect from a light bulb:

PS > $oldbulb | Get-Member

   TypeName: System.Illumination.LightBulb

Name        MemberType   Definition
----        ----------   ----------
bulbstyle   Property  bulbstyle=candle
glasstype   Property  glasstype=pearl
wattage     Property  wattage=40
....

We can pass (pipe) that light bulb object to the Buy-LightBulb cmdlet with the result that we'll buy a new light bulb with the same properties as the old one (except that we'd hope it will work!). If we assign that pipeline to a variable $newbulb...

$newbulb = $oldbulb | Buy-LightBulb

...then $newbulb will be a new light bulb object with the same properties as the old bulb. This is the PowerShell way of working.

Still, our spouse hasn't forgotten the time we came back from the store with the wrong sized refuse sacks, so we've got to to pass the new bulb through their Check-SpousePurchase cmdlet.

Before PowerShell, you'd expect that Buy-LighBulb would have returned some code to signify success, or the name of the light bulb, or perhaps a set of strings describing the properties of the light bulb we've bought. In order for your untrusting spouse to accept the product you've bought, you'd have to give strings describing all the properties of it to Check-SpousePurchase.

In PowerShell however, the results of Buy-LightBulb is a rich .Net object of type System.Illumination.LightBulb. The Check-SpousePurchase cmdlet can take this object from the pipeline, so the whole process can be expressed in PowerShell by passing objects along the pipeline and never having to describe properties with strings...

Your spouse hands you the bulb to replace, you purchase a replacement and hand the new bulb back to your spouse who confirms it's the right one and we avoid the problem we had with the refuse sacks were we didn't have a full understanding of the properties and bought the wrong ones:

$oldbulb | Buy-LightBulb | Check-SpousePurchase

Really, if you forget about light bulbs, the difference is between passing the physical object from one step to the next, or describing over the phone what has come out of one stage to go into the next. I hope that's helped clear things up for some of you and also shown why pipelines of objects have significant advantages over passing strings from one command to another.

Friday
May162008

Sapien PowerShell Training: update

The ScriptingAnswers.com University Windows PowerShell Full Set, which I blogged about a couple of weeks ago, arrived yesterday. We only got round to sorting out the purchase order on Tuesday, so that delivery has been extraordinarily fast!

Not sure if I'll get a chance to try it over the weekend, but I should be able to provide something of a review in the next week or so.

Wednesday
May142008

How much space are orphaned mailboxes taking up on my Exchange servers?

If your enterprise has a high turnover of people, then at any one time you'll likely have numerous disconnected mailboxes on your Exchange Servers. That's because Exchange, by default, will not purge the mailbox until 30 days after the user it was connected to has disappeared from Active Directory, i.e. it has become orphaned.

Keeping those mailboxes there for a month can be a handy safety net, so I'm not suggesting purging them sooner (although that may suit you), but if you're going to allocate new users to mailbox stores based on how much space is in use/available it can be handy to look at how much space disconnected mailboxes are taking up, i.e. how much white space will be freed up in your .edb file after the disconnected mailboxes are purged (and an online defrag has taken place).

Since we have to talk to Exchange 2003 and Exchange 2007 in different ways, I'm going to deal with them separately, then if you want to combine them into a single script, you can (it's just a case of not re-initialising the hashtable).

Ok, so I'm going to assume that we've got a text file Ex03Servers.txt which contains a list of the Exchange 2003 servers we want to query. We need to setup a hashtable to hold the results, but then the rest of the work is done by a one liner:

$space = @{}
get-content Ex03Servers.txt | `
%{gwmi -co $_ -namespace "root\MicrosoftExchangeV2" -query "SELECT * FROM Exchange_mailbox WHERE DateDiscoveredAbsentInDS IS NOT NULL" | `
%{$space[$_.ServerName+"\"+$_.StoreName]+=$_.Size}}

Thanks to Gaurhoth in the #powershell IRC channel on irc.freenode.net for pointing me in the right direction for finding disconnected mailboxes on Exchange 2003 with WMI.

$space now contains the amount of free space and you can just type $space to see it, although you'll get the output in a random order, so you may want use the enumerator to sort by size:

$space.GetEnumerator() | Sort value -desc

Or by server and store name alphabetically:

$space.GetEnumerator() | Sort name

So, to do the same thing for disconnected mailboxes on Exchange 2007, do this:

$space = @{}
get-content Ex07Servers.txt | `
%{get-mailboxstatistics -Server $_ | `
?{$_.DisconnectDate -ne $null} | `
%{$space[$_.Database]+=$_.TotalItemSize.Value.ToKB()}}