Archive

Posts Tagged ‘Windows Server’

Powershell One-liners – Folder cleaning

Some application just log to much, and the log files tend to get huge.

Or maybe you have a situation where you just don’t need the log’s from the last 2 years, but would like to retain a few days back, in case of error:

Windows Scheduled task and Powershell to the rescue

 

powershell.exe -command "& {get-childitem -Path e:\IIS_Logs -Recurse| %{if ($_.CreationTime -lt ([DateTime]::Now.AddDays(-5))){remove-item $_.FullName}}}"

This will delete files older than 5 days in the targeted folder (IIS_logs) and all subfolders

I have tried to wrap this in a schtasks command, so far been unsuccessful.

In the Windows Server 2008 R2 GUI:

  • Task Scheduler
  • Create a basic task
  • Give it a name and a description
  • Choose the Task trigger and the properties for the selected trigger
  • Choose the action (start a program)
  • Add the path for powershell.exe in the program/script box and everything following to the Add arguments (optional) box
  • image
  • Review and Finish.
    /theadminguy

Powershell One-liners – IP scanner

So why use powershell? I even heard someone say “this powershell is so over-rated, what does it offer, that cannot be done with cmd.exe and a another tool?”

Well, to me, that is exactly it, what does powershell offer, which cannot be done with cmd.exe?

What if you wanted just to check a defined range of IP’s in you managed subnet, to find which ones have live hosts on them?

[PS]# 1..100 | %{ping -n 1 -w 15 11.2.7.$_ | select-string "reply from"}

Reply from 11.2.7.83: bytes=32 time=5ms TTL=122
Reply from 11.2.7.84: bytes=32 time=7ms TTL=122
Reply from 11.2.7.85: bytes=32 time=6ms TTL=122
Reply from 11.2.7.86: bytes=32 time=6ms TTL=122
Reply from 11.2.7.87: bytes=32 time=6ms TTL=122
Reply from 11.2.7.89: bytes=32 time=6ms TTL=122
Reply from 11.2.7.91: bytes=32 time=6ms TTL=122
Reply from 11.2.7.95: bytes=32 time=6ms TTL=122
Reply from 11.2.7.99: bytes=32 time=6ms TTL=122

This one-liner ping’s the range from 1 to 100 and returns the machines which replied.

The point here is not, that only Powershell can do this on Windows, and I know that ping.exe is not a native powershell cmd-let and what if the host does not respond to ICMP…bla bla.. Smile

But this method is simple, fast and intuitive. No need for starting up a dedicated application, no fiddling with scripts, just get the job done, which in turn leaves more room for other stuff.

/theadminguy

Modify Disk layout in Windows using powershell – updated version

At work one of my colleagues is fond of the phrase: Assume – makes and ass of you and me

Now this has, again, become very appropriate for me to use:

In my first post of the disk layout script, found here, I wrote with assumption and confidence: “but should also work on Windows Server 2003, if it does not then I have to redo the Altiris job”…

So I have redone the Altiris job powershell script:

#first we find and initialize physical disks with no partitions
$drives = gwmi Win32_diskdrive
$scriptdisk = $Null
$script = $Null
$OSversion = (((Get-WmiObject Win32_operatingsystem).version).ToString()).Split('.')[0]

foreach ($disk in $drives){
if ($disk.Partitions -eq "0"){
    $drivenumber = $disk.DeviceID -replace '[\\\\\.\\physicaldrive]',''
    
    If ($OSversion -eq "5"){
$script = @"
select disk $drivenumber
online noerr
create partition primary noerr
"@
    }
    ElseIf ($OSversion -eq "6"){
$script = @"
select disk $drivenumber
online disk noerr
attributes disk clear readonly noerr
create partition primary noerr
format quick
"@
}
    }
    $drivenumber = $Null
    $scriptdisk += $script + "`n"
    }
$scriptdisk | diskpart

#then we will move the CDRom drive to x:
(gwmi Win32_cdromdrive).drive | %{$a = mountvol $_ /l;mountvol $_ /d;$a = $a.Trim();mountvol x: $a}

#then we will assign letters and labels to physical drives
# thanks to powershell.com for this bit
#(http://powershell.com/cs/blogs/tips/archive/2009/01/15/enumerating-drive-letters.aspx)
$volumes = gwmi Win32_volume | where {$_.BootVolume -ne $True -and $_.SystemVolume -ne $True}
$letters = 68..89 | ForEach-Object { ([char]$_)+":" }
$freeletters = $letters | Where-Object { 
  (New-Object System.IO.DriveInfo($_)).DriveType -eq 'NoRootDirectory'
}
foreach ($volume in $volumes){
    if ($volume.DriveLetter -eq $Null){
        If ($OSVersion -eq "5"){
          mountvol $freeletters[0] $volume.DeviceID
          format $freeletters[0] /FS:NTFS /q /y
        }
        Else {
            mountvol $freeletters[0] $volume.DeviceID    
        }    
    }
$freeletters = $letters | Where-Object { 
    (New-Object System.IO.DriveInfo($_)).DriveType -eq 'NoRootDirectory'
}
} 

As it turns out, diskpart v5.2 does not support either the online disk command nor the format quick command, which is why I have had to add OS filtering (got to love the one-liner 🙂 and the format command.

I have also had to remove the $_.DriveType -eq "3", as an unformated primary partition under Windows Server 2003 R2 does not have a drivetype defined. But in order to salvage some honor, I’ll call that optimization, as it is actually not required, because that part of the script only assigns drive letters to volumes without one, and both the floppy and CDRom have one already.

/theadminguy

Export DHCP leases to html using powershell – update

There was a minor quirk in the original script, as lease dates where being mixed with hostnames in the final output html. As it turns out it was all a matter of what date it was, when I created the script 🙂

Line 21 in the original:

$l = $l -replace '[-]{1}\d{2}[/]\d{2}[/]\d{4}',''

matches dates in the following format: -xx/yy/zzzz but not -x/yy/zzzz or for that matter -xx/y/zzzz.

The correct –replace should have been:

$l = $l -replace '[-]{1}\d{1,2}[/]\d{1,2}[/]\d{4}',''

Thanks you for the comments, which was the final spark to get me to fix it in my production environment 🙂

Modify disk layout in Windows using powershell

So I have been configuring the company Altiris server (I love that tool) with some new jobs.

One of the headaches of past times, for me anyway, has been the modification of the disk layout, e.g. cd-rom must have letter so, a random number of physical disks must be formatted etc.

This is the powershell solution that I ended up with:

#first we find and initialize physical disks with no partitions 
$drives = gwmi Win32_diskdrive
$scriptdisk = $Null
$script = $Null
foreach ($disk in $drives){
    if ($disk.Partitions -eq "0"){
        $drivenumber = $disk.DeviceID -replace '[\\\\\.\\physicaldrive]',''        
$script = @"
select disk $drivenumber
online disk noerr
attributes disk clear readonly noerr
create partition primary noerr
format quick
"@
}
$drivenumber = $Null
$scriptdisk += $script + "`n"
}
$scriptdisk | diskpart

#then we will move the CDRom drive to x:
(gwmi Win32_cdromdrive).drive | %{$a = mountvol $_ /l;mountvol $_ /d;$a = $a.Trim();mountvol x: $a}

#then we will assign letters and labels to physical drives
# thanks to powershell.com for this bit
#(http://powershell.com/cs/blogs/tips/archive/2009/01/15/enumerating-drive-letters.aspx)
$volumes = gwmi Win32_volume | where {$_.BootVolume -ne $True -and $_.SystemVolume -ne $True -and $_.DriveType -eq "3"}
$letters = 68..89 | ForEach-Object { ([char]$_)+":" }
$freeletters = $letters | Where-Object { 
  (New-Object System.IO.DriveInfo($_)).DriveType -eq 'NoRootDirectory'
}
foreach ($volume in $volumes){
    if ($volume.DriveLetter -eq $Null){
        mountvol $freeletters[0] $volume.DeviceID
    }
$freeletters = $letters | Where-Object { 
    (New-Object System.IO.DriveInfo($_)).DriveType -eq 'NoRootDirectory'
}
} 

The script has been tested in PSHv2 installed on Windows Server 2008 and in native Windows 2008 R2 PSH, but should also work on Windows Server 2003, if it does not then I have to redo the Altiris job 🙂 – Update 14-11-2009: As it turns out the above will not work under Windows server 2003 – the updated version can be found here

The script first gets all the physical disks which have no partitions. Then it creates a script for use with diskpart. Once all physical disks are formatted, driveletters are assigned. First we move the cd-rom drive to x: then we loop through all volumes which are not BootVolume (e.g. c:\) or SystemVolume (W2k8 R2 reserved system partition)

Throw some comments or input to improve. I am particularly interested in a way to do this using .NET, so I do not have to use diskpart.

Export DHCP leases to html using powershell

So I was in a need of having the active leases in my DHCP server exported to an web (html) page:

On the surface this would not present a problem, however as there is only one way to read the DHCP leases, netsh.exe, and the output format of this app is somewhat … I also got the chance to to play with regular expressions (love those) and <string> –replace

Just so everyone can share the pain, this is the netsh command:

netsh dhcp server 1.1.1.1 scope 1.1.1.0 show clients 1

And this is the output:

Changed the current scope context to 1.1.1.0 scope.

Type : N - NONE, D - DHCP B - BOOTP, U - UNSPECIFIED, R - RESERVATION IP
============================================================================================
IP Address      - Subnet Mask    - Unique ID           - Lease Expires        -Type -Name   
============================================================================================

1.1.1.5     - 255.255.0.0    - 00-ff-ff-ff-ff-ff   -10/13/2009 12:33:16 AM  -D-  host01.domain.com
:::
::: Lot of lines here
:::
1.1.1.227   - 255.255.0.0    - 00-ff-ff-ff-ff-ff   -10/13/2009 12:42:06 AM  -D-  host10.domain.com

No of Clients(version 4): 355 in the Scope : 1.1.1.0.

Command completed successfully.

So is there any logic here? Double tabs, single tabs from which I can split? No. only spaces…. and hyphens.. and useless data

As I only needed the IP and hostnames in a html table, this is what I ended up with in powershell:

$a = (netsh dhcp server 1.1.1.1 scope 1.1.1.0 show clients 1)

$lines = @()
#start by looking for lines where there is both IP and MAC present:
foreach ($i in $a){
    if ($i -match "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"){
        If ($i -match "[0-9a-f]{2}[:-][0-9a-f]{2}[:-][0-9a-f]{2}[:-][0-9a-f]{2}[:-][0-9a-f]{2}[:-][0-9a-f]{2}"){    
            $lines += $i.Trim()
        }
    }
}
$csvfile = @()
#Trim the lines for uneeded stuff, leaving only IP, Subnet mask and hostname.
foreach ($l in $lines){
    $Row = "" | select Hostname,IP
    $l = $l -replace '[0-9a-f]{2}[:-][0-9a-f]{2}[:-][0-9a-f]{2}[:-][0-9a-f]{2}[:-][0-9a-f]{2}[:-][0-9a-f]{2}', ''
    $l = $l -replace ' - ',','
    $l = $l -replace '\s{4,}',''
    $l = $l -replace '--','-'
    $l = $l -replace '-D-','-'
    $l = $l -replace '[-]{1}\d{2}[/]\d{2}[/]\d{4}',''
    $l = $l -replace '\d{1,2}[:]\d{2}[:]\d{2}',''
    $l = $l -replace 'AM',''
    $l = $l -replace 'PM',''
    $l = $l -replace '\s{1}',''
    $l = $l + "`n"
    $l = $l -replace '[,][-]',','
    $Row.IP = ($l.Split(","))[0]
    #Subnet mask not used, but maybe in a later version, so let's leave it in there:
    #$Row.SubNetMask = ($l.Split(","))[1]
    $Row.Hostname = ($l.Split(","))[2]
    $csvfile += $Row
}

#let create a csv file, in case we need i later..
$csvfile | sort-object Hostname | Export-Csv "Out_List.csv"

#Create the HTML formating
$a = "<style>"
$a = $a + "body {margin: 10px; width: 600px; font-family:arial; font-size: 12px;}"
$a = $a + "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}"
$a = $a + "TH{border-width: 1px;padding: 2px;border-style: solid;border-color: black;background-color: rgb(179,179,179);align='left';}"
$a = $a + "TD{border-width: 1px;padding: 2px;border-style: solid;border-color: black;background-color: white;}"
$a = $a + "</style>"

#And create HTML file...
Write-Host "Please contact theadmin@void.null for support" | Out-File "DHCPLeases.html"
$csvfile | sort-object Hostname | ConvertTo-HTML -head $a | Out-File -Append "DHCPLeases.html"

The resulting output, then looks like this:

HostName IP
host01.domain.com 1.1.1.5
host10.domain.com 1.1.1.227

which is what I wanted. Another great job by powershell.

I hope that this might prove useful to someone else, and a my thanks goes out to the powershell community and all the people who might recognize some of the code, no one mentioned, no one forgotten.

Please do drop a line if you have comments or suggestions to how the script could be optimized. Life is a learning curve and I love climbing 🙂

%d bloggers like this: