The Multifunctioning DBA:

Windows

Oct 29 2009   8:00PM GMT

Windows 7



Posted by: Colin Smith
Microsoft Windows, Windows, Media Streaming, Media

I have played with one of the preview releases and I liked it just fine. I just read some good info on Engadget that leads me to believe that I will like Windows 7 just because of the media center upgrades that have been done.

I am excited to hear about media center starting to play nice with DLNA devices and not just Media Extenders. This means that I will be able to use my PS3 to stream music via windows media center and no longer have to use a third party app. Not that I mind using a third party app to do so but I think that everyone needs to get along and talk to each other when it comes to media sharing. I think that most media will be online soon and I think that the more devices that can talk nicely together the better off we will be.

Based on just that I can not wait to get my hands on Windows 7 and get the install complete.

Sep 24 2009   4:13PM GMT

Powershell Remove files



Posted by: Colin Smith
Powershell, Microsoft Windows, Windows, Windows Administration

I have a server that attempts to backup up the SQL Server databases and it always fails because not enough space is available. This usually is not a big deal as I would run a SQL Clean up task before the backups run to remove the old files. In this case though I am using a third party utility to run the backups and it does not have that functionality. So, since I am no sqljockey yet, I have chosen Powershell as my tool. Here is what I have done.



$days = [datetime]::now.adddays(-7) E: cd \ cd Directory ls | where {$_.name -like "*.bak"} | rm -force cd tranlogs ls | where {$_.name -like "*trn"} | rm -force cd ../../Directory ls | where {$_.name -like "*.bak"} | rm -force cd tranlogs ls | where {$_.name -like "*bak"} | rm -force ls | where {$_.name -like "*txt"} | where{$_.creationtime -lt $days} | rm -force c:

You can see that I simple cd to the directory that I have my backupfiles in and do an rm or Remove-object. I am also keeping 7 days worth of the txt log files that the backups create. Just in case I need them. Hope that helps. Enjoy


Jul 23 2009   9:43PM GMT

More with Quest AD Powershell CMDLETS



Posted by: Colin Smith
Powershell, Active Directory, Microsoft Windows, Windows, Windows Administration, Domain Administration

I am continuing work on the script that I am converting from VBScript to Powershell and I must say that it is going quite well with the help of the Quest cmdlets. In the script I want to go through a particular OU and delete any accounts that are currntly disabled, and were created a minimum of 180 days ago, and have not been used in a minimum of 180 days. I can do this with the following block of code.

$deletedays = - 180
$deletedate = [datetime]::Now.AddDays($deletedays)

Get-QADUser -SearchRoot “pni.us.ad.gannett.com/PNI/Users/Disabled” | where{(($_.lastlogontimestamp.value -lt $deletedate) -and ($_.creationdate -lt $deletedate) -and ($_.AccountIsDisabled -eq “True”))}  | Tee-Object -filepath “c:\removedaccounts.txt” | Remove-QADObject -Force

So you will also notice that I am using the Tee-Object cmdlet. This is not a quest cmdlet but it is nice as I can log what accounts I am deleting with the Remove-QADObject cmdlet that is provided by Quest. Be careful when doing things like removing accounts in scripts and be sure to test completly. A good way to test is to use the -whatif clause. This will show you what would happen if you did run it.


Mar 30 2009   9:57PM GMT

Scripting



Posted by: Colin Smith
Scripting, Powershell, Unix, Windows, System Administration, Windows Administration, Linux, Database Administration, Active Directory

So I have people ask me all the time how I can get so much done in a day. I have to be honest with you, I do not really do that much. This is because I write scripts to do anything and everything for me if I have to do it more than once I script it. If I think something might be useful I script it. I hate doing the same work over and over. Take something as simple as creating a new user on a domain. This is a very simple task in AD but it takes about 2 minutes per account. It is easy to find a script that will create mass accounts with some generic name. Why not take that same script and make it so it creates one account at a time or ten or whatever you need. You can make it so you type in the name of the user interactively or read names in from a list that you have. Simple things like that. Creating this account only takes 2 minutes in AD but I can do it in under 10 seconds.

When you work in the fast paced world like we do, especially in IT where everyone wants it now now now, every second counts. Saving just under 2 minutes does not seem like a lot but that is the just the beginning. If you save 5 minutes here and 10 there and 2 there then it adds up very fast so you can leave work an hour early, or you just make your boss think that you are that much better and more effective. It does not really matter if you are a Windows person or a Unix/Linux person. SCRIPT anything you can and save time.

I come from a Windows background and in this area the Unix/Linux admins are years ahead of the Windows users. I had done some automation using VBScript when I was a Windows Admin, but when I got into Unix for Database Admin, I quickly learned that scripting is the way. Now with Windows Powershell, Windows administrators can be much more effective in less time. Please learn a scripting language that is of use to you and that you understand. I prefer Powershell but VBscript is a good way to go if you like it better.

Good luck scripting and as always, if you have a question let me know by heading to http://sysadminsmith.com and click the ‘Submit a Question’ link on the right.


Feb 24 2009   6:18PM GMT

Powershell commands for Active Directory



Posted by: Colin Smith
Powershell, Active Directory, Windows, Windows Administration

I have been asked how to manage Active Directory with Powershell. The best way is with the Quest Software cmd-lets for Active Directory. They are free and available at http://www.quest.com/powershell/activeroles-server.aspx. Once you download them and install them you will still need to add the snapin to your powershell profile. In order to do this just open powershell and do the following.

This will open your powershell profile in notepad. The Powershell profile is really just a powershell script. You can have it do anything you want. I have mine add a few psdrives that I use often and add the snapins that I need. Just add the following line to your profile script and you will be able to use all the AD cmd-lets that Quest has been so kind to supply for free.

add-pssnapin quest.activeroles.admanagement

You can do this with any set of snapins that you find. I have some for sqlserver as well that come in handy.

Let me know if you have any questions by going to http://sysadminsmith.com and clicking the submit a question link to the right.


Feb 17 2009   10:42PM GMT

File Copy with Powershell



Posted by: Colin Smith
Powershell, Microsoft Windows, Windows, Windows Administration

I have a friend that I work with that has to copy files out to the same 10 servers anytime our developers create a new report. To do this manually he has to log into the UNC of each server, verify that the server does not already have a report with the same name, if it does he needs to rename it, and then copy the file to the server. He thought that he would be able to script this in powershell and asked me for some help along the way. I think that he has a solution but I decided that this is something that may be handy for many of us Admins. So I went ahead and wrote a script that will do what he needs. I decided to add a few extras in as well. Here is what I ended up with.

#Get list of servers to push new files to#

$servers
=
Get-Content
“d:\test2\servers\servers.txt”

#Set where the new files are located and read them in as a variable#

$newfilepath
=
“d:\test2″

$newfiles
=
Get-ChildItem
$newfilepath
|
where {$_.name
-like
“*.txt*”}

#Get Date and Time Information#

$date
=
Get-Date
-format
MM_dd_yyyy

$time
=
get-date
-format
HH:mm:ss

#Test to see if OUT directory and Log file Exist. If not create them#

if (!(test-path
“d:\OUT”))

{

New-Item
-type
directory
“d:\OUT\”

}

if (!(Test-Path
“d:\OUT\rptmove.log”))

{

New-Item
-type
file
“d:\OUT\rptmove.log”

}

$log
=
“d:\OUT\rptmove.log”

#Start Checking each server to see if it has a file with the same name in the destination path#

foreach ($server
in
$servers)

{

Echo
“########################################################################################” >> $log

Echo
“`n########################################################################################” >> $log

Echo
“Working with Server $server” >> $log

# Ping server to make sure it is available for this task#

$pingresult
=
Get-WmiObject
win32_pingstatus
-f
“address=’$Server’”

if($pingresult.statuscode
-eq 0)

{


write-host
$server
is
available
-background
“green”
-foreground
“black”

Echo
“$server is available” >> $log

$prodfolderpath
=
“\\$server\d$\Reports”

$oldfiles
=
Get-ChildItem
$prodfolderpath
|
where{$_.name
-like
“*.txt*”}

foreach ($newfile
in
$newfiles)

{

$found
= 1

$newrpt
=
$newfile.Name

foreach ($oldfile
in
$oldfiles)

{

$oldrpt
=
$oldfile.name

# If the server has a file with the same name, Rename file with datestamp, copy new file to destination#

if ($newrpt
-eq
$oldrpt)

{

Echo
“`nMatch found for $newrpt” >> $log

Echo
“Renaming $oldrpt to $oldrpt.$date” >> $log

Rename-Item
-path
“$prodfolderpath\$oldrpt”
-newName
“$oldrpt.$date”

Echo
“copy $newrpt to $prodfolderpath\newrpt” >> $log

copy-Item
-path
“$newfilepath\$newrpt”
-destination
“$prodfolderpath”

echo
“moving of file $newrpt is complete on $date at $time” >> $log

$found
= 0



}

}

# if server does not have a file with the same name then move the new file to the server. #

if ($found
-eq 1)

{

echo
“`n$newrpt not found in $prodfolderpath” >> $log

copy-Item
-path
“$newfilepath\$newrpt”
-destination
“$prodfolderpath”

echo
“moving of file $newrpt is complete on $date at $time” >> $log

$found
= 0


}

}

}

else

{


write-host
$server
is
NOT
available. Please
check
server
and
try
again
-background
“red”
-foreground
“black”

Echo
“$server is not available for this operation. Please check server and try again!” >> $log

}

Echo
“`nCompleted Working with $server” >> $log

}

Echo
“########################################################################################” >> $log\

So this script fist gets a list of all the servers that it needs to copy the files to. Lucky for me that all the servers keep the reports in the same location. I then get a list of all the file names that I need to upload to the servers. Then I get Date and Time info so that I can use that in renaming files as well as logging actions. Then I start my loop. First I ping the server that I want to work with. If the server is down I echo a notification of this as well as log it. I then move to the next server in the list. If the server is up then I get a listing of all the files that the server has on it in that folder so I can compare them to the files that I need to copy to the server. Then I compare the files. If I find that the server has a file with the same name as a new file then I rename the file on the server using the datestamp so I will know when the file was last used. I also log that action. Then I copy out the new file to the server. If the server does not have a file with the same name as one that I need to upload I upload that file to the server and log that action as well. This will loop thru as many servers as you want with as many files as you want. In this example I am searching only for .txt files but you do not have to do that. Please let me know if you have any questions about this by leaving a comment or by heading over to http://sysadminsmith.com and clicking on Submit a Question to the right.


Jan 27 2009   10:53PM GMT

Partitioning Tool



Posted by: Colin Smith
Windows, Windows Administration

I made a big mistake at home and only gave myself a 10 Gig partition of a 250Gig drive to be my boot drive. This was OK for a while but I did not manage the space well and before I knew it I was out of space and could not delete any more files. I found this great tool for home that is free for home use and I am sure that the other pay per versions of this are even better. All I can say is that it worked awsome for me so I thought I would let you all take a look as well.

 http://www.partition-tool.com/

And come check out my site and let me know if you have any questions at http://sysadminsmith.com


Jan 27 2009   8:52PM GMT

Disk Monitoring Q and A



Posted by: Colin Smith
Powershell, Windows, Windows Administration

Mike sent me an email asking about the input file for the disk monitoring script that I posted a while back. He could not get the script to work as he was putting the hostname and the IP of the machine in the computerlistall.txt file. The script was written to have either the hostname or the IP of the machine but not both. This started me thinking that a file with both the hostname and the IP of the machine would be useful in more ways then just this script. We may be able to use this file for multiple scripts and certainly is a good idea just to manage and keep track of names and IP’s. So I did the following to accommodate Mike. I hope this helps Mike and some others out there.

Here is a screenshot of my new computerlistall.txt file. notice that I do have headers in the file. This is very important because of the way the import-csv cmdlet works.

Computerlistall.txt

Computerlistall.txt

Now that I have that as my input I have to modify the script just a bit to accommodate this format.

The arrows point out what I have changed. I put in the $computer and the $ip lines just to show you the output when doing this.

So you can see that $compuuter is now the value of the hostname and $ip is now the value of the IP for that server. I do not know about you but I think this is freaking Cool.
So if you modify your computerlistall.txt file to be a file with header values and data values seperated by commas and modify the script as I have shown you here then you should be all set. This will allow you to use either the $computer or the $ip variable in the WMI connection string. Below is the entire modified script.

##########################################

###         Gather PAC Disk Information      ###

##########################################

Clear-Content “D:\Scripts\Powershell\PAC\lowdisk.txt”

$i = 0

$users = “some.email@address.com”

$computers = import-csv “D:\Scripts\Powershell\PAC\computerlistall.txt”

echo “ServerName        Drive Letter      Drive Size  Free Space  Percent Free” >> “D:\Scripts\Powershell\PAC\lowdisk.txt”

echo “———-        ————      ———-  ———-  ————” >> “D:\Scripts\Powershell\PAC\lowdisk.txt”

foreach ($line in $computers)

{

$computer = $line.hostname

$ip = $line.ip

$computer

$ip

}

$drives = Get-WmiObject -ComputerName $computer Win32_LogicalDisk | Where-Object {$_.DriveType -eq 3}

foreach($drive in $drives)

{

$size1 = $drive.size / 1GB

$size1

$size = “{0:N2}” -f $size1

$size

$free1 = $drive.freespace / 1GB

$free = “{0:N2}” -f $free1

$ID = $drive.DeviceID

$a = $free1 / $size1 * 100

$b = “{0:N2}” -f $a

##############################################

##    Determine if any disks low    ##

##############################################

if (($ID -eq “D:”) -or ($ID -eq “S:”) -or ($ID -eq “T:”) -or ($ID -eq “C:”) -and ($free1 -lt 1))

{

echo “$computer         $ID               $size       $free       $b” >> “D:\Scripts\Powershell\PAC\lowdisk.txt”

$i++

#[char]10 | Out-File -append ./low.txt

}

}

####################################################

##    Send Notification if alert $i is greater then 0         ##

####################################################

if ($i -gt 0)

{

foreach ($user in $users)

{

echo “Sending Email notification ro $user”

$smtpServer = “smtp server”

$smtp = New-Object Net.Mail.SmtpClient($smtpServer)

$emailFrom = “fromuser@domain.com”

$subject = “Email Subject”

foreach ($line in Get-Content “D:\Scripts\Powershell\PAC\lowdisk.txt”)

{

$body += “$line `n”

}

$smtp.Send($EmailFrom,$user,$subject,$body)

$body = “”

}

}

Hope that helps and please drop me a line by heading over to http://sysadminsmith.com/ and clicking the Submit a Question link on the right hand side of the page. Thanks


Jan 21 2009   5:25PM GMT

Powershell 2.0 CTP (Transactions)



Posted by: Colin Smith
Powershell, Windows

As I said I am just starting to fool around with Powershell V2.0 and I ran across a cmd-let that really grabbed my attention and I went to read more about it. This is a Fanatastic Idea and I am so excited to see Powershell use this in more Providers.

Transactions, How cool is that? Just like when running a query in a database, this will run the commands as a transaction and have the ability to roll back the changes. If all of the changes that you would like to be made are not completed correctly it will rollback to the way it was before the script ran. Currently it looks as though only the registry PSProvider supports this but man I hope that changes. I can think of many scripts where this would be useful. One example is my SQL Server Monitoring tools, I have a function that goes out and changes the on-call contact. I think it would be nice for it to be all or nothing. That way you do not get two people on call if for some reason the function does not complete. I love it. Read more at http://www.microsoft.com/technet/scriptc…


Jan 20 2009   5:49PM GMT

Environmental Variables in Powershell



Posted by: Colin Smith
Powershell, Windows

I have a script that I run in production that requires the script to access the Environment Variables for the server the script is executing on. This is a very simple task in powershell and very very useful. In my script I am using it just to verify that the machine name that it is executing on is the same as the machine name that I want the script to execute on. This is because the script is run from a single location and runs on many servers. The script compares the name that I am inputting to the actual machine name before moving on. Here is how easy this is in Powershell:

$name = (get-content env:Computername)

$name will now hold the value of the environmental variable on that machine for ComputerName. Powershell makes this so easy by having env as a PSDrive. This means that you can connect to it like you would a drive letter and get information from it. try the following:

cd env:

ls

and here is a sample of the results.

PS C:\Documents and Settings\smithco> cd env:
PS Env:\> ls

Name                           Value
—-                           —–
Path                           D:\oracle\ora92\bin;C:\Program Files\Oracle\jre\1.3.1\bin;C:\Program Files\Oracle\jre\1.1.8\bin;D:…
TEMP                           C:\DOCUME~1\smithco\LOCALS~1\Temp
SESSIONNAME                    Console
PATHEXT                        .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.PSC1
APPDATA                        C:\Documents and Settings\smithco\Application Data
SYBASE                         D:\Apps\sybase
PROCESSOR_ARCHITECTURE         x86
SystemDrive                    C:
HOMESHARE                      \\pni-pcfs01\HOME
DEFLOGDIR                      C:\Documents and Settings\All Users\Application Data\McAfee\DesktopProtection
windir                         C:\WINDOWS
USERPROFILE                    C:\Documents and Settings\smithco
TMP                            C:\DOCUME~1\smithco\LOCALS~1\Temp
SYBASE_JRE                     D:\Apps\sybase\shared-1_0\jre1.2.2
USERDNSDOMAIN                  PNI.US.AD.GANNETT.COM
USERDOMAIN                     PNI
ProgramFiles                   C:\Program Files
FP_NO_HOST_CHECK               NO
HOMEPATH                       \
COMPUTERNAME                   PNI-BT15689
CLASSPATH                      .;D:\Apps\sybase\ASEP_Win32\3pclass.zip;D:\Apps\sybase\ASEP_Win32\monclass.zip;C:\Program Files\Ja…
USERNAME                       smithco
NUMBER_OF_PROCESSORS           2
PROCESSOR_IDENTIFIER           x86 Family 15 Model 4 Stepping 3, GenuineIntel
VSEDEFLOGDIR                   C:\Documents and Settings\All Users\Application Data\McAfee\DesktopProtection
INCLUDE                        D:\Apps\sybase\OCS-12_5\include;
ComSpec                        C:\WINDOWS\system32\cmd.exe
LOGONSERVER                    \\PNI-DVADDC02
SYBASE_OCS                     OCS-12_5
CommonProgramFiles             C:\Program Files\Common Files
SystemRoot                     C:\WINDOWS
PROCESSOR_LEVEL                15
PROCESSOR_REVISION             0403
QTJAVA                         C:\Program Files\Java\jre1.6.0_05\lib\ext\QTJava.zip
lib                            D:\Apps\sybase\OCS-12_5\lib
ALLUSERSPROFILE                C:\Documents and Settings\All Users
WF_RESOURCES                   D:\oracle\ora92\WF\RES\WFus.RES
OS                             Windows_NT
HOMEDRIVE                      H:

PS Env:\>

Pretty cool huh….