Tag Archives: do-while

Keep an Attached Drive Active

I recently received two drives sent via FedEx for a rather large data copy. Maybe I haven’t been looking, but I’ve never seen anything like these drives before, although it wasn’t too difficult to believe they existed. They each hold 6TB and have a 10-key keypad on the drive case where you have to punch in a PIN to unlock the drive. Neat, except that the drives also have a timeout period in which they automatically lock. To unlock each drive, providing there’s been no disk activity, as that’s what starts the timeout counter, is a trip to the data center to enter the PIN again.

keep-an-attached-drive-active01

A coworker and I quickly arrived at the same idea in order to keep the drives active. I bet you just thought of an idea, too. It’s extremely simplistic, but that’s typically the road on which I travel. In the simple Do-While loop below, we created a file on each of the attached drives. In my example, the loop slept for eight minutes after it created the file. Then it removed the files and slept for another 10 seconds before repeating.

Do {
    New-Item -Path E:\keepalivefile.txt,F:\keepalivefile.txt -ItemType File | Out-Null
    Start-Sleep -Seconds 480 # equal to 8 minutes
    Remove-Item -Path E:\keepalivefile.txt,F:\keepalivefile.txt
    Start-Sleep -Seconds 10
}
While ($true)

That’s all I’ve got tonight, other than to say, I have no idea what I would’ve done if I didn’t know Windows PowerShell. Seriously, how would I have been able to guarantee the drives wouldn’t lock, besides to manually create the disk activity? Keeping File Explorer open wasn’t enough, I tried. PowerShell to the rescue. Again.

Automate App Server (Non Visual) Website Test

This is part II of this post: http://tommymaynard.com/quick-learn-automate-app-server-visual-website-test-2016. It might be beneficial to read that first.

It was minutes before my family needed to leave the house and start our Saturday, when my desire to monitor eight of my application servers hit. In a quick moment, I wrote three commands in three PowerShell consoles and left the house.

Before I show you what was in console one, I have to show and mention a couple functions on which it relied. These functions are a bit of a continuation of the link above. The Watch-MyApp function below, will visually and textually display indicators so that I know if my app servers’ websites are responding, or not. The -Visual parameter will open an instance of Internet Explorer for each server URL, so I can visually check the app servers’ websites (see the link to view this function).  Not using the -Visual parameter, which is how it’s used here, uses Invoke-WebRequest to determine a webpage’s status code. A 200 status code (OK response) means our webpage is up, and responding. If it’s not up, it’ll indicate a timeout warning. It could also produce a different status code, if the page is up, but produces something other than a 200 status code. Other more well-known status codes are the dreaded 404 (page cannot be found), or a 5xx error which indicates a problem with the web server. It may also be helpful to know that the $MyAppServers variable contains the default properties for five servers, returned from the Get-ADComputer cmdlet.

Function Watch-MyApp {
    Param (
        [switch]$Visual
    )
    
    If ($Visual) {
        $MyAppServers.Name | ForEach-Object {
            Open-InternetExplorer -Url "$_.myapp.mydomain.com"
        }
    } Else {
        $MyAppServers.Name | ForEach-Object {
            try {
                $StatusCode = (Invoke-WebRequest -Uri "http://$_.myapp.mydomain.com" -TimeoutSec 10).StatusCode
                "$StatusCode`: $_"
            } catch {
                Write-Warning -Message "$_"
            }    
        }
    }
 }

The first of my three consoles wrapped the function above, Watch-MyApp, in a never ending loop ($true is always true). Every minute it would get the date and time and write it to a log file. Immediately after that, it would run the function to get the status code of each web server, and append it to the same log file. A minute later and it does the same thing. Here’s the command and a sample from the log file it created.

Do {
    (Get-Date).ToString() | Out-File -FilePath 'C:\MyApp.txt' -Append
    Watch-MyApp | Out-File -FilePath 'C:\MyApp.txt' -Append
    Start-Sleep -Seconds 60
} While ($true)
2/21/2016 10:48:29 PM
200: appsrv01
200: appsrv02
200: appsrv03
200: appsrv04
200: appsrv05
2/21/2016 10:49:29 PM
200: appsrv01
200: appsrv02
200: appsrv03
200: appsrv04
200: appsrv05

The second console ran another endless Do-While loop. The difference, is that this loop’s job was to copy the file that was being updated by the command in the first console, to my Dropbox folder every ten minutes. Genius, right? While I could have, I opted to not have my first command write/overwrite the file directly in my Dropbox folder. I didn’t feel it was necessary to update Dropbox each minute for hours on end. When I was back home later, I changed this from ten minutes to 30 minutes, or 1800 seconds, as it was even less important to update Dropbox then.

Do {
    (Get-Date).ToString() | Out-File -FilePath 'C:\MyApp.txt' -Append
    Copy-Item -Path 'C:\MyApp.txt' -Destination 'C:\Users\tommymaynard\Dropbox\MyApp.txt' -Force
    Start-Sleep -Seconds 600
} While ($true)

What this meant is that while I was away, I was able to check Dropbox on my phone and quickly determine if there were any status codes other than a 200. Every ten minutes and there would be an update to my file that would include the status code results for each minute in the last ten.

The final console didn’t do much other than allow me to manually check the file in Dropbox, for something other than a date entry, and status code of 200. So far so good: None of the web apps returned anything more than a 200 status code. Maybe the change at the end of the day on Friday really did fixed things. Here’s the command I used to read the file and exclude lines that had a date and a 200 status code (all the lines unless there was a problem).

Get-Content -Path 'C:\MyApp.txt' | Where-Object {($_ -notlike '*2016*') -and ($_ -notlike '200*')}

But why visually scan the file myself, when PowerShell can do that too!? This third command could’ve also been an endless loop. It could’ve automated scanning the file for me, like I was doing already, and then could’ve been set up to send me an email using the Send-MailMessage cmdlet if it found something, other than the 200 status code. I could’ve avoided looking at the file in Dropbox and just watched my email. One better, and I could’ve had my command do email to text with a specially crafted email address. Here’s what I mean for US Verizon customers: http://www.verizonwireless.com/news/article/2013/06/computer-to-phone-text-messaging.html. Many days, it feels like PowerShell is only limited by what you can think do with it.

There have been times in my life where my wife will ask me, “How would people that don’t know computers, know how to do this?” I usually answer by saying, that “They wouldn’t,” or “I don’t know, I’m not that person.” The same thing applies here: “How would a Windows System Administrator know what to do if they hadn’t already learned PowerShell?” Those three commands might take someone new with PowerShell half a day to consider, and then write. Learn it while you don’t think you need it, because one day you will.

So, to recap, while I was away doing the family thing, my computer sat on the kitchen table at home, checked on eight app servers for me and updated a file in Dropbox, that I was able to check at times while we were away. PowerShell has a purpose, and without it, you’re losing yours.

Formatting Decimal and Whole Numbers

This post will show how to use some simple logic and formatting to display only two decimal places with decimal numbers, and no decimal places with whole numbers.

I recently updated a game I wrote in Windows PowerShell called, “The 1 to 100 Game.” In this game, a person tries to guess a number between 1 and 100 that has been chosen by the computer (or rather, the advanced function). The computer will offer hints, as to whether the number it has chosen, is higher or lower than what was last guessed by the person playing the game. This person continues to guess until they correctly match the number. You can find the advanced function on the Microsoft TechNet Gallery here: http://gallery.technet.microsoft.com/The-1-to-100-Game-5288e279. While it’s not my most popular advanced function, I enjoyed the project, and especially when I shared it with my son as the 1 to 100 Game is one of the many games we play during our longer car rides. Oh, and if you’re looking for an example of nested do-while language constructs, then look no further – it’s up to three now.

During the rewrite to version 2.0, I decided to add something new. The game records the number of attempts it takes to guess the correct number, and how many games you’ve played. With that type of information, it can easily calculate the average number of attempts per game. This won’t always be a whole number and so I needed a way to only use two decimal places when decimal numbers were returned, and to use no decimal places when whole numbers were returned.

We can format our decimal numbers to only use two decimal places by using the -f Format operator. In the example below, we take a number that has four decimal places and specify that it is formatted to only use two decimal places.

PS C:\> $x = 100.9851
PS C:\> $x
100.9851
PS C:\> '{0:N2}' -f $x
100.99 #We want this, and notice the rounding!

In the next example, we have a whole number. If we use the -f Format operator on this number it will also show two decimal places. This isn’t what we want – we want to leave whole numbers the way they are and not add any decimal places.

PS C:\> $x = 150
PS C:\> $x
150
PS C:\> '{0:N2}' -f $x
150.00 #We don't want this!

Formatting decimal numbers, and leaving whole numbers alone, is going to require some conditional logic (If-Else statement) along with modulus division. Modulus division returns the remainder of a division operation. Here are some examples using the division operator (/) and the modulus operator (%).

PS C:\> 10 / 2
5
PS C:\> 10 % 2
0
PS C:\> 10 / 3
3.33333333333333
PS C:\> 10 % 3
1
PS C:\> 10 / 7
1.42857142857143
PS C:\> 10 % 7
3

When zero is returned from a modulus division operation, it means that the division operation did not result in a remainder. This is a great way to handle whether or not a number should or should not be formatted. In the example below, the modulus division operation on line 3 returns zero. Since zero is equal (-eq) to zero, then $a is divided by $b on line 4.

$a = 10
$b = 2
If ($a % $b -eq 0) {
    $a / $b
} Else {
    '{0:N2}' -f ($a / $b)
}
5

In this example, the modulus division operation does not return zero. Therefore, the else statement is called on line 5. On line 6, $a is divided by $b and then formatted to two decimal places. The parenthesis around ($a / $b)  indicates to PowerShell to divide first, and then do the formatting.

$a = 10
$b = 3
If ($a % $b -eq 0) {
    $a / $b
} Else {
    '{0:N2}' -f ($a / $b)
}
3.33