Thursday, May 15, 2008

New laptop

I'm getting a new laptop at work on Monday. Started a list of the things to do right after I get it. In the order they hit the electronic page (but not the order they'll happen -- more on that in a sec):
  • Create utils and docs folders
  • docs should be a junction of c:\documents and settings\tss04\my documents (powershell New-Junction c:\docs 'C:\Documents and Settings\tss04\My Documents'
  • bring over My documents and docs folder contents (currently separate directories -- fixing that w/ the junction)
  • bring over oreilly folder (put in docs?)
  • install ant
  • install perl
  • install filezilla
  • install firefox
  • install powershell and power shell community extensions
  • install vim, configure _vimrc, vimrc_example.vim, mswin.vim, john.vim, filetype.vim
  • bring over utils
  • selectively bring over d:\ftp
  • bring over d:\powershell
  • bring over notes journal, archive
So the obvious out of order one is that I'm using PowerShell to configure my docs directory as a junction of My Documents before I've installed PowerShell... Reading the list, I know I've missed cygwin and all of my firefox add-ons, bookmarks, profile, etc. Oh, and VMWare -- that's going on this time. Maybe 7-zip. Maybe...

What's the first thing you install on a new machine? What are you going to leave off when you replace your current box?

Monday, May 5, 2008

Powershell template

I'm working on a template for all powershell scripts in our environment. Basically something everyone can take as a starting point for their scripts, that will guarantee a level of homogeneity of functions (logging, debug level messages, email output, etc.).

Below is what I have so far. Any thoughts on improvements/additions?


##########################################################################
## Script Name : template.ps1 ##
## Created : 05/02/2008 ##
## Author : John McDevitt ##
## Function : sample script to be used as a start for all scripts ##
## : in production. ##
## : ##
## Usage : how to call this script (e.g. arguments required or ##
## : accepted) ##
## : ##
## Host/path : where is this script located ##
## : ##
## Notes : Update the help message with meaningful text for ##
## : your script. ##
## : ##
## : include debugging messages by calling debug_msg ##
## : e.g., debug_msg("about to do something weird") ##
## : include log messages by calling log_msg. Log file ##
## : is configurable, but defaults to a scriptname.log ##
## : in the current directory (will be a share soon). ##
## : All debug messages go into the log prefaced with ##
## : DEBUG: ##
## : ##
## : you will probably need to update the param block, ##
## : even though it is above the "your code here" block ##
## : ##
## Update Log : ##
## : ##
##########################################################################
param (
[switch]$debug,
[string]$mailto,
[string]$logfile
)

function Usage
{
""
"Describe the purpose of this script"
""
"Usage: template.ps1 -option <value> "
""
"Required Parameters:"
" -option <value>: Describe the options and their expected values here"
""
"Optional Parameters:"
" -mailto user@domain: User/group to send a copy of any debugging messages"
" or log info to."
""
" -debug: Enables debug messages -- useful for tracing code execution"
""
" -? : Display this usage information"
""
""
exit
}

function log_msg ($message) {
$message >> $logfile
if ($mailto) { $script:email_body = $script:email_body + $message + "`n" }
}

function debug_msg ($message) {
if ($debug) {
$message = "DEBUG: " + $message
$message
log_msg $message
}
}

log_msg ("started execution at " + (get-date))

if ($logfile -eq "") {
$logfile = $($MyInvocation.mycommand.name) + ".log"
}

debug_msg "logfile is $logfile"

##########################################################################
## YOUR CODE BEGINS BELOW THIS LINE ##
##########################################################################

if (( $ARGS -eq '-?') -or ( $ARGS -match "help" )) {
Usage
}

##########################################################################
## YOUR CODE ENDS ABOVE THIS LINE ##
##########################################################################

log_msg ("completed execution at " + (get-date))
if ($mailto) {
send-smtpmail -to $mailto -smtphost mailhost.yourdomain.com -from $mailto -subject $($MyInvocation.mycommand.name) -body $email_body
}

Thursday, May 1, 2008

Reach out and touch someone

A follow on to my previous post. It's great to be able to find a specific copy of a process running on a remote machine (UserA's copy of Notepad, for instance), but the real benefit is being able to do something about it.

Below is kill_processes.ps1. You'll note that it's nowhere near as clean as my pkill for windows script. It turns out that to do much of anything on a remote machine with PowerShell, you need to go through WMI. Basically, this script is a more flexible version of the kill scripts. This one takes four parameters:
  • computername -- defaults to localhost

  • notuser -- this is a pattern for users to ignore. defaults to SERVICE or SYSTEM

  • user -- this is a pattern for users to find. It is required, and throws an exception if not provided

  • name -- this is a pattern for the process name to find and kill. It is required and throws an exception if not found.

Having both the notuser and user parameters is pretty redundant, but it's protection against a bad pattern for the user parm. I didn't want to put this script in the wild and have someone run it like .\kill_processes.ps1 -computername domaincontroller -user "ser" -name "*" when trying to kill all of sergey's processes -- bye-bye domain controller is NOT my goal.

param (
[string]$computername = "localhost",
[string]$notuser = "SERVICE|SYSTEM",
[string]$user = $(throw "enter the user name that started the process"),
[string]$name = $(throw "enter the process name to kill")
)
gwmi win32_process -computername $computername|
where {($_.getowner().User -notmatch $notuser) -and ($_.getowner().user -match $user) -and ($_.name -match $name)} |
foreach {$_.Terminate() >$null }
counter free hit invisible