I was writing a script recently, and I realized that I was missing the ability to use the standard logging module from Python. I decided to make a stripped-down logging function that would make logging easy, and that could be re-used. I'd be interested to hear what approaches others have taken to solving this problem. Here's what I came up with:
# Set severity constants
$MSG_INFORMATION = 0
$MSG_WARNING = 1
$MSG_ERROR = 2
$MSG_SEVERITY = @('Information', 'Warning', 'Error')
# Set configurable settings for logging
$LOG_LEVEL = $MSG_INFORMATION
$LOG_FILE = 'my_logfile.log'
$SMTP_TO = 'devnull@tojo2000.com'
$SMTP_SERVER = 'smtp.tojo2000.com'
$SMTP_SUBJECT = 'Script error!'
function Write-Log {
<#
.SYNOPSIS
Writes a message to the Log.
.DESCRIPTION
Logs a message to the logfile if the severity is higher than $LOG_LEVEL.
.PARAMETER severity
The severity of the message. Can be Information, Warning, or Error.
Use the $MSG_XXXX constants.
Note that Error will halt the script and send an email.
.PARAMETER message
A string to be printed to the log.
.EXAMPLE
Log $MSG_ERROR "Something has gone terribly wrong!"
#>
param([Parameter(Mandatory=$true)][int]$severity,
[Parameter(Mandatory=$true)][string]$message)
if ($severity -ge $LOG_LEVEL) {
$timestamp = Get-Date -Format 'yyyy-MM-dd hh:mm:ss'
$output = "$timestamp`t$($MSG_SEVERITY[$severity])`t$message"
Write-Output $output >> $LOG_FILE
if ($severity -ge $MSG_ERROR) {
Send-MailMessage -To $SMTP_TO `
-SmtpServer $SMTP_SERVER `
-Subject $SMTP_SUBJECT`
-Body $output `
-From $SMTP_FROM
exit 1
}
}
}
Short posts about Microsoft PowerShell as I learn, trying to focus on one aspect at a time.
Thursday, March 3, 2011
Tuesday, January 25, 2011
Nothing To DO With PowerShell
Just a quick update to plug one of my other projects: py-ad-ldap. Have you ever wanted to run scripts against Active Directory but not wanted to run them on Windows? You haven't? Well, if you had, then this would have been the Python module for you. I haven't packaged it up for download yet (hopefully tomorrow), but it's pure Python, so there are no fancy requirements for installing it, so mosey on down to the repository and take a look at the source files if you're interested.
Sunday, January 23, 2011
Getting Performance Counters in PowerShell
I had a friend ask me recently if there was an easy way to monitor arbitrary performance counters in a script, and I didn't really have time to think about it at the time, but this weekend I decided to give it a whirl, and I came up with this function, that I'll definitely be putting in my profile at work.
The way it works is pretty straightforward, but you need to know some background about Performance Counters if you haven't used them before. There are basically four pieces of information needed to retrieve a counter:
The way it works is pretty straightforward, but you need to know some background about Performance Counters if you haven't used them before. There are basically four pieces of information needed to retrieve a counter:
- Category
- Counter
- Instance
- Computer
If these don't ring a bell right away, fire up Perfmon, right-click and select Add Counters, and you'll see something like this:
In the top-left box you can see the Categories, and if you expand them you'll see the Counter names, and bottom left are the Instances.
Classic example: you want to find out the Current Disk Queue Length on your C: drive.
- Category = 'LogicalDisk'
- Counter = 'Current Disk Queue Length'
- Instance = 'C:'
- Computer = '.' (default, it means "this computer")
Using Get-PerformanceCounter, you'd do it like this:
Get-PerformanceCounter LogicalDisk 'C:' 'Current Disk Queue Length'
Or lets say you want to get all of the counters for the C: drive:
Get-PerformanceCounter LogicalDisk 'C:'
Anyway, here's the function, and you can also find it here: http://poshcode.org/2475
Monday, November 30, 2009
A Great Write-Up on WMI Events and PowerShell 2.0
I haven't been inspired to do a full post in a while, but I stumbled across this article by Trevor Sullivan today, and I thought I'd point it out for those of you that are interested.
Friday, October 30, 2009
Working with CSV Files
It's been a while since I had an update to the blog, and I've been waiting for something to jump out at me. Today I read on the news that the White House has released some visitor logs to the public, and they are making them available for download as a CSV file, and it piqued my interest, so I downloaded the file.
PowerShell v1 and v2 both have a module called Import-CSV that makes it ridiculously easy to work with CSV files. They will slurp up the file and output an array of objects, one per row, with properties that correspond to the columns in the file.
Let's import the file and look at a record:
PS> $visitors = Import-Csv .\10-30-waves-posting.csv
PS> $visitors[-1]
NAMELAST : ZIMPHER
NAMEFIRST : NANCY
NAMEMID : L
UIN : U81194
BDGNBR : 72400
ACCESS_TYPE : VA
TOA : 4/1/20091:45:42PM
POA : D0102
TOD : 4/1/20095:50:21PM
POD : D1
APPT_MADE_DATE : 3/25/20095:07:33PM
APPT_START_DATE : 4/1/20092:00:00PM
APPT_END_DATE : 4/1/200911:59:00PM
APPT_CANCEL_DATE :
Total_People : 3
LAST_UPDATEDBY : J7
POST : WIN
LastEntryDate : 3/25/20095:08:57PM
TERMINAL_SUFFIX : J7
visitee_namelast : DOUGLAS
visitee_namefirst : DEREK
MEETING_LOC : OEOB
MEETING_ROOM : 459
CALLER_NAME_LAST : WILKINS
CALLER_NAME_FIRST : ELIZABETH
CALLER_ROOM :
Description :
Interesting. I wonder, who had the most visitors (I snipped out the middle of the results)?
PS> $visitors |
Group-Object visitee_namelast |
Sort-Object Count |
Select-Object Count, Name
Count Name
----- ----
1 ANDREW
1 LONG
1 BINNIX
1 BREWER
...
7 'SUMMERS'
7 JARRETT
8 'POTUS/FLOTUS'
8 'EMANUEL'
9 POTUS/FLOTUS
9 'DOEBLER'
10 DOEBLER
10 'TCHEN'
12 TCHEN
42 'POTUS'
56 POTUS
69 OFFICE
211
Uh oh. There's something funky about this file. There are empty lines, and it's inconsistent about when it puts quotes around text fields. I'm pretty sure we don't have any fields with commas in them, so let's try stripping out any lines that only have whitespace and/or commas in them and then strip out single quotes from the rest of the lines:
PS> Get-Content .\10-30-waves-posting.csv |
?{$_ -notmatch '^(\s|,)*$'} |
%{$_.replace("'", '')} > wh.csv
** Note: that regex after -notmatch above can be read as:
^ start at the beginning of the string
(\s|,)* zero or more whitespace or comma characters
$ the end of the string
There. Now we can try that again, using our new file (snipped for length again).
PS> $visitors = Import-CSV .\wh.csv
PS> $visitors |
Group-Object visitee_namelast |
Sort-Object Count |
Select-Object Count, Name
Count Name
----- ----
1 SHAH
1 LONG
1 PETER
1 ANDREW
...
19 DOEBLER
22 TCHEN
69 OFFICE
98 POTUS
So now we know that the person with the largest number of visitors was the President of the United States of America. Hardly surprising, but you can easily explore this data with PowerShell. Here are a few more queries you might try:
Look at the records of the visits to the President
PS> $visitors |
?{$_.visitee_namelast -eq 'POTUS'}
How many visits occurred in July?
PS> $visitors |
?{$_.APPT_START_DATE -match '^7/'} |
sort APPT_START_DATE |
select NAMELAST, NAMEFIRST, APPT_START_DATE
What was the description given of the appointments for meeting the President?
PS> $visitors |
?{$_.visitee_namelast -eq 'POTUS'} |
select APPT_START_DATE, NAMEFIRST, NAMELAST, Description |
sort APPT_START_DATE
Hopefully this gives you a good idea of how you can manipulate CSV data using PowerShell using Import-CSV and a little filtering.
Labels:
Comma-Separated Values,
Import-CSV,
Strings
Thursday, September 3, 2009
A Regular Expression Cheat Sheet for PowerShell
Okay, so there's really not much that is PowerShell-specific about this cheat sheet, but I wrote it up in response to a post on microsoft.public.windows.powershell, and I thought I'd share it here, since I know a lot of new PowerShell users haven't been exposed to Regular Expressions very much.
This is not meant as an exhaustive reference on regular expressions, but just something that may be helpful if you get a little stuck. I hope you find it helpful.
1. What kind of character is it?
[] - any of the characters inside the brackets will match
(use the dash to indicate a range)
Examples: [a-z] will match any letter.
[aeiou] will match any vowel
\w - "word" characters. Basically matches [a-z0-9_]
\s - "whitespace" characters. matches spaces, tabs, etc.
\d - any digit. Basically matches [0-9]
\t - a tab character
. - any character
2. How many characters?
(the below appear after the character class)
{x} - matches x number of characters
{x, y} - matches minimum x number of characters, maximum y characters
Examples: \d{4} matches 4 digits
* - matches ZERO or more of the character (as many as possible)
+ - matches ONE or more of the character (as many as possible)
*? - matches ZERO or more characters (as few as possible)
+? - matches ONE or more characters (as few as possible)
3. Where is the character?
\b - matches a word boundary, without actually absorbing any characters
^ - matches the beginning of a string
$ - matches the end of a string
4. Grouping
() - any characters between the parentheses will be their own group
(try checking the value of $matches after using -match)
| - a pipe character is the OR character
Example: (one|two) will match the word "one" or the word "two"
Wednesday, August 26, 2009
Add a List of Users to the Local Admins Group
Just a quick update here, and another real-world example of where the Split() method of a string can come in handy for day-to-day tasks.
Today I had to add a list of about 20 individual usernames as administrators to a particular machine. Someone sent me the comma-separated list in an IM, and it took me about ten seconds:
PS> 'user1,user2,user3,user4,user5,user6,user7,user8,user9,user10'.split(',') |
>> %{net localgroup administrators $_ /add}
The command completed successfully.
The command completed successfully.
The command completed successfully.
The command completed successfully.
The command completed successfully.
The command completed successfully.
The command completed successfully.
The command completed successfully.
The command completed successfully.
The command completed successfully.
Subscribe to:
Posts (Atom)