Link to home
Start Free TrialLog in
Avatar of Slator
SlatorFlag for United States of America

asked on

Having Trouble Keeping SBS C: Drive Defragmented

Small Business Server Premium 2003
18gb SCSI with 16.9 useable
20% Free Space

When I run the Analyze process every 3/4 days the results are that I need to defragment drive C:
I have been trying to devise a plan/method to help keep the C: drive from fragmenting so quickly.
I have moved/re-located all the files that feel comfortable with doing to help prevent fragmenting.
However, this seemed to provide little help.

Is there a way/method to move files or configure the SBS C: drive to help keep it from defragmenting so quickly?

Avatar of blohrer
blohrer
Flag of United States of America image

You can use the following VBS Script (Copy and save into a file called defrag.vbs)

' XDEFRAG.VBS - Defragments volumes using the built-in defrag.exe command-line
' tool. Requires Windows XP or later.
'
' Written by: Bill Stewart (bill.stewart@frenchmortuary.com)
'
' Value-added features:
'
' * Can sequentially defragment multiple volumes
' * Can defragment local fixed drives if you specify /L, or you can specify one
'   or more volumes on the command line
' * Can record its activity in the Application event log (/E)
' * Reports contain the volume that was defragmented, date and time when the
'   defrag run started and finished, the elapsed time, and the defrag exit code
'   and description
' * Script exit code will highest exit code that defrag returned
'
' You must run this script using the CScript host.
'
' Version history:
'
' 1.0 (19 Jul 2004)
'
' * Initial version.

Option Explicit

Const SCRIPT_NAME = "XDEFRAG.VBS"

' Global object variables
Dim g_objFSO          ' Scripting.FileSystemObject instance
Dim g_objWshShell     ' Wscript.Shell object instance
Dim g_objErrors       ' Dictionary contains defrag exit codes and descriptions

' Global state variables
Dim g_blnEventLog     ' Log to event log?
Dim g_blnAnalyze      ' Analyze only?
Dim g_blnForceDefrag  ' Force defragmentation even if free space is low?
Dim g_blnVerbose      ' Verbose output?

Main()

' Prints the usage message and exits
Sub Usage()
  Wscript.Echo "Defragments volumes using the built-in defrag.exe command-line tool." & vbNewLine _
    & "Requires Windows XP or later." & vbNewLine _
    & vbNewLine _
    & "Usage: " & SCRIPT_NAME & " {/L | <volume> [...]} [/E] [/A] [/F] [/V]" & vbNewLine _
    & vbNewLine _
    & "/L  specify all local fixed drives" & vbNewLine _
    & "volume" & vbNewLine _
    & "    drive letter (d:) or mount point (d:\vol\mountpoint)" & vbNewLine _
    & "/E  report activity in Application event log (useful when scheduling)" & vbNewLine _
    & "/A  analyze only" & vbNewLine _
    & "/F  force defragmentation even if free space is low" & vbNewLine _
    & "/V  verbose output" & vbNewLine _
    & vbNewLine _
    & "You must specify either /L or one or more volumes."

  Wscript.Quit 0
End Sub

' Returns the scripting host (usually "cscript.exe" or "wscript.exe") in
' lowercase
Function ScriptHost()
  ScriptHost = LCase(Mid(Wscript.FullName, Len(Wscript.Path) + 2))
End Function

' Terminates script with an error message and exit code; if event logging is
' enabled, the error message will also be logged
Sub Die(ByVal strMessage, ByVal lngExitCode)
  strMessage = SCRIPT_NAME & ": " & strMessage
  If g_blnEventLog Then g_objWshShell.LogEvent 1, strMessage
  Wscript.Echo strMessage
  Wscript.Quit lngExitCode
End Sub

' Returns the name of a temporary file in the Temp directory
Function GetTempFileName()
  ' 2 = Temp directory
  Do
    GetTempFileName = g_objFSO.BuildPath(g_objFSO.GetSpecialFolder(2), g_objFSO.GetTempName())
  Loop While g_objFSO.FileExists(GetTempFileName)
End Function

' Returns lngNumber as a string with a leading zero if < 10
Function LeadingZero(ByVal lngNumber)
  If lngNumber < 10 Then
    LeadingZero = "0" & CStr(lngNumber)
  Else
    LeadingZero = CStr(lngNumber)
  End If
End Function

' Using two date variables, returns a string "hh:mm:ss" representing the
' elapsed time between them; requires the LeadingZero() function
Function Elapsed(ByVal dtmStart, ByVal dtmEnd)
  Dim lngSeconds, lngHours, lngMinutes

  ' Start with total number seconds
  lngSeconds = DateDiff("s", dtmStart, dtmEnd)

  ' Get number of hours
  lngHours = lngSeconds \ 3600
  ' If one or more hours, then subtract them from the total
  If lngHours > 0 Then lngSeconds = lngSeconds - (3600 * lngHours)

  ' Same with minutes
  lngMinutes = lngSeconds \ 60
  If lngMinutes > 0 Then lngSeconds = lngSeconds - (60 * lngMinutes)

  ' Now, lngSeconds contains the seconds remaining
  ' after the hours and minutes have been subtracted

  Elapsed = LeadingZero(lngHours) & ":" & LeadingZero(lngMinutes) & ":" & LeadingZero(lngSeconds)
End Function

' Defragments the specified volume, with enhanced reporting; returns defrag's
' exit code; requires the Elapsed() function
Function DefragVolume(ByVal strVolume)
  Dim strTempFile               ' Write defrag's output to this file
  Dim strCommand                ' Command line to execute
  Dim lngExitCode               ' Defrag's exit code
  Dim dtmStartTime, dtmEndTime  ' Start and end times
  Dim objTextStream             ' TextStream object for reading defrag's output
  Dim strStdOut                 ' Defrag's standard output
  Dim strReport                 ' Finished defragmentation report

  strTempFile = GetTempFileName()

  ' Build the command line; note that we have to call cmd /c to be able to
  ' redirect defrag's output to the temporary file; using the environment
  ' variables increates script robustness in case the Path is not correct
  strCommand = g_objWshShell.ExpandEnvironmentStrings("%ComSpec%" _
    & " /c %SystemRoot%\system32\defrag.exe ")
  strCommand = strCommand & strVolume
  If g_blnAnalyze Then strCommand = strCommand & " -a"
  If g_blnForceDefrag Then strCommand = strCommand & " -f"
  If g_blnVerbose Then strCommand = strCommand & " -v"
  strCommand = strCommand & " > " & strTempFile

  dtmStartTime = Now()

  ' 0 = run invisibly; True = wait for completion
  lngExitCode = g_objWshShell.Run(strCommand, 0, True)

  dtmEndTime = Now()

  ' 1 = open the temp file in read-only mode
  Set objTextStream = g_objFSO.OpenTextFile(strTempFile, 1)

  ' Read the entire file into the string
  strStdOut = objTextStream.ReadAll()

  ' Close and delete the temporary file
  objTextStream.Close()
  g_objFSO.DeleteFile strTempFile

  ' Build report string; note that it uses the dictionary to retrieve the
  ' appropriate text description for the exit code
  strReport = SCRIPT_NAME & " report for volume " & strVolume & vbNewLine _
    & vbNewLine _
    & strStdOut _
    & vbNewLine _
    & "Started: " & CStr(dtmStartTime) & vbNewLine _
    & "Finished: " & CStr(dtmEndTime) & vbNewLine _
    & "Elapsed time: " & Elapsed(dtmStartTime, dtmEndTime) & vbNewLine _
    & "Defrag exit code: " & CStr(lngExitCode) & " (" & g_objErrors(lngExitCode) & ")"

  If g_blnEventLog Then
    If lngExitCode = 0 Then
      g_objWshShell.LogEvent 0, strReport  ' 0 = SUCCESS
    Else
      g_objWshShell.LogEvent 1, strReport  ' 1 = ERROR
    End If
  End If

  ' Place a line break a the top when writing to standard output; this way,
  ' if we defragment multiple volumes, there is a line break in between each
  ' volume's report
  Wscript.Echo vbNewLine & strReport

  DefragVolume = lngExitCode
End Function

' Returns an array containing local fixed drives
Function LocalFixedDrives()
  Dim objDrive   ' Iterates the FSO's Drives collection
  Dim strDrives  ' Semicolon-delimited list of local drives e.g. C:;D:;E:

  For Each objDrive In g_objFSO.Drives
    If objDrive.DriveType = 2 Then  ' 2 = fixed drive
      If IsEmpty(strDrives) Then
        strDrives = objDrive.Path   ' the Path property includes the ":"
      Else
        strDrives = strDrives & ";" & objDrive.Path
      End If
    End If
  Next
  ' Return an array
  LocalFixedDrives = Split(strDrives, ";")
End Function

' Main subroutine
Sub Main
  Dim colVolumes       ' Collection of volumes to be defragmented
  Dim strVolume        ' Current volume to defragment
  Dim lngCurrExitCode  ' Defrag's exit code (current volume)
  Dim lngMaxExitCode   ' Defrag's highest exit code; script exits with this

  If ScriptHost() <> "cscript.exe" Then
    Die "You must run this script using the CScript host.", 5
  End If

  ' Check for /?, /E, /A, /F, /V
  With Wscript.Arguments.Named
    If .Exists("?") Then Usage
    g_blnEventLog = .Exists("E")
    g_blnAnalyze = .Exists("A")
    g_blnForceDefrag = .Exists("F")
    g_blnVerbose = .Exists("V")
  End With

  ' Instantiate global objects
  Set g_objFSO = CreateObject("Scripting.FileSystemObject")
  Set g_objWshShell = CreateObject("Wscript.Shell")
  Set g_objErrors = CreateObject("Scripting.Dictionary")

  ' If /L, then use FSO's Drives collection to retrieve array of local fixed
  ' drives; otherwise, check if the .Unnamed collection contains anything; if
  ' it does, then assign the colVolumes object reference
  With Wscript.Arguments
    If .Named.Exists("L") Then
      colVolumes = LocalFixedDrives()
    ElseIf .Unnamed.Count > 0 Then
      Set colVolumes = .Unnamed
    End If
  End With

  ' No volume(s) specified
  If IsEmpty(colVolumes) Then
    Die "You must specify either /L or a list of volumes to defragment.", 2
  End If

  ' Populate the dictionary; see 294743 for more information
  With g_objErrors
    .Add 0, "successful"
    .Add 1, "canceled manually"
    .Add 2, "syntax error"
    .Add 3, "unknown error"
    .Add 4, "insufficient memory"
    .Add 5, "general error"
    .Add 6, "system, ACL, file mismatch, or system-wide error"
    .Add 7, "insufficient free space: 15% free space required"
  End With

  lngMaxExitCode = 0  ' No errors yet

  For Each strVolume In colVolumes
    lngCurrExitCode = DefragVolume(strVolume)
    If lngCurrExitCode > lngMaxExitCode Then lngMaxExitCode = lngCurrExitCode
  Next

  Wscript.Quit lngMaxExitCode
End Sub



Then create the following batch file  (call it defragjob.bat)

cscript c:\sysadmin\defrag.vbs /L /E


Then schedule a task to run defrag everynight at 1am (or to your choice)


The above will run defrag on all drives, and post an event log entry into the Application log of the system (WSH will be the source)

The entry will show all of the relavant defrag information.

Hope it helps

Bill

Avatar of Slator

ASKER

Bill,
2 questions:
     1)You mentioned Windows XP or later; I have a Small Business Server 2003 Premium.  Still OK?
     2)More specifically, my problem is that the built-in defrag program will not completely defrag
        the drive. To make it work I have to move files to create [more] space (even though I have 15%+)
        and run the defrag multiple times.
        Since the vbs scropt uses the same defrag program, how will it do a better job?

Thanks,
Slator

ALSO:
The [visual] result of the defrag analysis indicates to me there is not enough room to defrag completely even though there
          is 20% of free space.
Here is the defrag report after one of the [unsuccessful] defrags:
Fragments       File Size       Files that cannot be defragmented
       28             20 MB           \Program Files\Microsoft SQL Server\MSSQL$SBSMONITORING\Data\SBSMonitoring_log.LDF
     380             23 MB           \Documents and Settings\All Users\Application Data\Microsoft\Windows NT\NTBackup\catalogs51
                                               \3453B002.V01
       46             26 MB           \Program Files\SAV\vpdebug.log
     134             42 MB           \WINDOWS\system32\wbem\Logs\FrameWork.log
     992             63 MB           \WINDOWS\system32\config\SecEvent.Evt
13,223             88 MB           \Program Files\Microsoft Windows Small Business Server\Support\MSSBSSSR.log
    120            295 MB          \System Volume Information\{7454e90b-9e32-11da-ae7f-505054503030}{3808876b-c176-4e48-b7ae-
                                               04046e6cc752}
      52            500 MB          \System Volume Information\{7454e9d9-9e32-11da-ae7f-505054503030}{3808876b-c176-4e48-b7ae-
                                               04046e6cc752}
    290            619 MB          \System Volume Information\{7454e940-9e32-11da-ae7f-505054503030}{3808876b-c176-4e48-b7ae-
                                               04046e6cc752}
      49            793 MB          \Program Files\Microsoft SQL Server\MSSQL$SBSMONITORING\Data\SBSMonitoring.mdf

SOLUTION
Avatar of blohrer
blohrer
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
These entries are being used by the Shadow Copy Service....

20            295 MB          \System Volume Information\{7454e90b-9e32-11da-ae7f-505054503030}{3808876b-c176-4e48-b7ae-
                                               04046e6cc752}
      52            500 MB          \System Volume Information\{7454e9d9-9e32-11da-ae7f-505054503030}{3808876b-c176-4e48-b7ae-
                                               04046e6cc752}
    290            619 MB          \System Volume Information\{7454e940-9e32-11da-ae7f-505054503030}{3808876b-c176-4e48-b7ae-
                                               04046e6cc752}

Shadow copy service is where you can roll back files to an earlier date if they are over written by a user.  The apply to shares on your system.

You can view what is being stored by:
Right clicking on the C: drive
Properties
Shadow Copies Tab

The "Select a volume" area shows how much space is being used by shadow copies

And the "Shadow copies of selected Volume" area shows the actual shadow copy files (which will correspond to the ones above).  Deleting them will free up almost 1.4 GB of space.  They will get recreated over time.  That your call since I am not sure if you use the shadow copy function, or if you have shares on your c: drive that would need this function (aka user shares)

I just compressed my "Client Apps" share on my c: drive and freed up about 300mb.

Bill
Also you can control/reduce the size of the Shadow Copy service, especially if you dont have any important shares

Right click C: drive
Properties
Highlight C: in the "Select a volume" area
Settings Button
Maximum Size
Use Limit

and Set a limit.

Bill
ASKER CERTIFIED SOLUTION
Avatar of Jeffrey Kane - TechSoEasy
Jeffrey Kane - TechSoEasy
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Also, why are you running shadow copies on your C drive?  This is not the default setting.  If you have any items which you want to have shadowed it should be on another partition or drive.

You CAN move the client apps folder to another drive, but beware that if you haven't applied SP1 you will need to make an adjustment for this.  This will probably be true for SP2.  But I have many installations with the clientapps folder on another partition.

Jeff
TechSoEasy
Tech,

His main problem is an 88mb log file, and not the 1.4GB of Shadow copy or the 793MB monitoring file?

Talk about trying to steal thunder... :)

Bill
Yeah, the problem is that the 88mb log file is currently in over 13,000 different pieces.  It gets that way and causes the drive to fragment pretty quickly.

Go figure.

I did recommend moving the shadow copies as well.  The MSDE databases can be moved rather easily, but it's generally not necessary because the don't fragment much and are automatically defraged during the backup procedure.  As you can see, the 793MB file is only in 49 fragments... not much compared to the 13,000 of the log file.

Jeff
TechSoeasy
Ah yes...

I was attacking the problem more from the standpoint that he was below the 15% needed to adaquately defrag the drive.

I defrag my sbs 2003 server nightly using the script above and have never received a notice that those files could not be defragmented, leading me to belive that they are not locked, but that his lack of disk space is hindering the defrag.

Bill
I seem to recall that NTFS itself likes at least 10% free space in which to play.

16.9G is quite a lot of data on C. ( I have 7.5G )  So there must be a lot of data that can & should be moved to a new drive as suggested above.

need to use a disk space reporting tool to work out where all the space is being used.  I use an old version of Diskdata http://www.diskdata.com/   This will report all data , not just those fragmented.

http://www.freedownloadscenter.com/Best/disk-usage-free.html
http://www.foldersizes.com/disk-space-tour/
http://www.fileboost.net/directory/utilities/disk/disk_space_inspector/011825/review.html
Avatar of Slator

ASKER

Good Morning Everyone!

Thanks for all the information.
I will not be able to check out all the suggestions until Thursday, I am out of pocket all day Wednesday.

However, I did make 2 [easy/quick] changes and the difference is remarkable:
1)Deleted the ...MSSBSSSR.log file.
   Then I ran defrag about 5/6 times and [amazing], it did make a big difference.

2)Disabled the Shadow Copy on the Drive C:.  I have no idea why this was setup like this.
   I inherited the system from another person and I assumed (bad idea) the Shadow Copy was for the
   User Shares on Drive F:
   This made huge difference due to the file sizes.

The only file that I cannot defrag now is:
49            793 MB          \Program Files\Microsoft SQL Server\MSSQL$SBSMONITORING\Data\SBSMonitoring.mdf


Thanks again!
Slator





If you have SBS Premium with full SQL, you can register the MSDE instance in the Enterprise manager and defrag the database through there.  Otherwise, just stop the MSSQL$SBSMONITORING service before running your defrag, and then restart it afterwards so that the defrag can access the data file.  

HOWEVER, that seems to be rather large for that file... make sure that the SQLAgent$SBSMonitoring service is running and is set to AUTOMATIC because that will keep items older than 90 days out of the database.  

Also, you COULD move it over to another partition if you wanted as well.

Jeff
TechSoEasy
Avatar of Slator

ASKER

Venabili,

Thanks for reminding me to clean this up.
We did a "clean" install/configuration on one of our servers and I  lost track of this question.

The comments by Jeff/TechSoEasy and Bill/blohrer were great and completely solved my problem.
I wish I had set the question points at 500.

Slator