Friday, 25 October 2013

Installing Harp on Debian Jessie

I recently came across the new open source web server called Harp.
Here is the description from the Harp website;


What is Harp?

Harp is a zero-configuration web server that is used to serve static assets. It has a built in asset pipeline for serving .jade, .markdown, .ejs, .coffee, .less, .styl as .html, .css, and .js. Harp supports a template agnostic layout/partial system and metadata for dynamically building files.


I thought I would take Harp for a drive around the block and decided to install it on a Debian Jessie virtual machine.
The installation process is rather easy except for one issue due to the Node.js package.

Here is the process to install Harp.

Firstly there are some prerequisites to get Harp installed being Node.js and npm, the package manager for Node.   I decided to install Node and npm using the Debian package repositories with these commands.

apt-get update
apt-get install nodejs npm

Once Node is installed, you can install Harp using the Node package manager.

npm install harp -g

The -g switch in the above command tells the package manager to make the Harp install global rather than a local directory install.

Harp is now installed and everything should be ready to go!   There is a problem though.   If you run the following command.

harp --version

You will get an error which is very misleading.

/usr/bin/env: node: No such file or directory

You can be forgiven for thinking that the harp binary was not found.   This is not the case.   The problem here is Harp is trying to call Node.js by using the command 'node' while on a Debian system the Node command is 'nodejs'.

This is easy to fix with the following symbolic link.   Simply run this command.

ln -s /usr/bin/nodejs /usr/bin/node

Now if you run Harp everything works as expected.

harp --version
0.9.4

All that is left is to follow the instructions on getting started to use the Harp web server.


Wednesday, 16 October 2013

A PowerShell Script to Warm Up or Wake Up SharePoint 2013

I was discussing SharePoint warm up solutions with some colleagues today and reviewed some of the solutions on the web.

The reason SharePoint needs warming up is because the first time a page is accessed in SharePoint the Just-In-Time compiler creates native images of the ASP.NET code within SharePoint.   Unfortunately this compilation needs to be carried out once a day due to the recycling of the Internet Information Services (IIS) World Wide Web Worker Processes (w3wp.exe) that host the SharePoint applications.

I decided to try my hand at writing one in PowerShell. Here is a simple solution.

Access the Gist here: https://gist.github.com/grantcarthew/7000687

<#
.Synopsis
Invokes a standard web request against all the sites in SharePoint.
.Description
There are some dependencies to run this script as follows;
The account used to run this script will need read access to all
sites for the initialization to fully succeed.
This script is required to be run on a SharePoint server or a
machine with the Microsoft.SharePoint.PowerShell dll registered.
Requires PowerShell v3.0.
#>
[CmdletBinding()]
Param
()
"Importing the PowerShell cmdlets."
$ver = $host | select version
if ($ver.Version.Major -gt 1) {$Host.Runspace.ThreadOptions = "ReuseThread"}
Add-PsSnapin Microsoft.SharePoint.PowerShell
"Creating an Internet Explorer object for navigation."
$ie = New-Object -ComObject InternetExplorer.Application
"Enumerate the SharePoint sites."
$Webs = Get-SPWebApplication -IncludeCentralAdministration | Get-SPSite | Get-SPWeb
"Navigating to all $($Webs.Count) sites."
foreach ($Web in $Webs)
{
"Initializing $($Web.URL)"
try
{
$ie.Navigate($Web.URL)
while ($ie.Busy)
{
Start-Sleep -Seconds 1
}
"Title: $($ie.Document.title)"
}
catch
{
Write-Host -Object ("Status: " + $Error[0].Exception.Message) -ForegroundColor Yellow
}
}
$ie.Quit()
"SPWeb Initialization Complete."

Tuesday, 15 October 2013

A Telnet Client written in PowerShell

A little while ago I started writing a telnet client in Microsoft's PowerShell.   After it sat unfinished for a time I finally got around to improving it with multiple threads and cleaning it up.   It now works well so I decided to post about it.

Why would I write a telnet client in PowerShell?   Just for fun mainly.   It has been a good project to learn some more about PowerShell and may be of use for automating the configuration of Cisco routers and switches or running scripts on other servers.

The most interesting thing I learned as I worked through the project was about how to get PowerShell to support multiple threads.   Using the low level .NET Framework System.Net.Sockets.Socket class added to the complexity.

To start off with I created the telnet client using a "while" loop that ran continuously and caused the script to use up 20% of the CPU while doing nothing.   I couldn't fix this with a sleep timer because it made the client unresponsive.   The problem was I needed to respond asynchronously to reception of data through the TCP connection, and respond to user input at the console.   Very easy to do with C#, but in PowerShell?

To implement the reception and transmission of data at the same time asynchronously I started by trying to use the Asynchronous Programming Model used in the .NET Framework.   This is a little tricky because the tread pool used in PowerShell is different to the thread pool used in .NET.   I did find a way of using the async callback methods with PowerShell from a blog post by Oisin Greham.   I still had issues trying to get this to work though.

I gave up on using the async methods of the Socket class and started looking for alternatives.   It would have been nice to use the Register-ObjectEvent cmdlet and other event cmdlets but the Socket class does not have any publicly visible events to consume.

I briefly looked at the PowerShell Jobs cmdlets, but they didn't work well for this application because they use the remoting subsystem which serializes objects when they are passed between jobs.   This means passing an object by reference is not possible and I need a reference to the connected Socket.   That's when I came across the concept of creating a new PowerShell object using [PowerShell]::Create().

When [PowerShell]::Create() is called from a PowerShell script or console, a new instance of PowerShell with an empty pipeline is returned for you to make dance and sing any way you like.   The beauty of this new PowerShell object is you can pass objects by reference meaning I could pass the connected Socket.

So now I have two threads to use in my PowerShell telnet client.   The main PowerShell process creates a child PowerShell process and initiates it with a script to receive data from the socket.   After initiating the child a "while" loop is used with a blocking call to the $Host.UI.RawUI.ReadKey() method to wait for user input.

Rather than explain the code in any more detail, I will let the code do the talking.   If you want to use this code use the Gist link: https://gist.github.com/grantcarthew/6985142

<#
.SYNOPSIS
A full graceful telnet client using PowerShell and the .NET Framework.
.DESCRIPTION
This script was made with a view of using it to have full control over the text
stream for automating Cisco router and switch configurations.
.PARAMETER TelnetHost
The address of the server or router hosting the telnet service.
.PARAMETER Port
The TCP port number of the Telnet service running on the Telnet host.
#>
param
(
[parameter(Mandatory)]
[String]
$TelnetHost,
[Int]
$Port = 23
)
# Initialize variables
[System.Text.ASCIIEncoding]$ASCIIEncoding = [System.Text.Encoding]::ASCII
[System.Net.Sockets.Socket]$Socket = $null
# Checking host address and port.
if ($TelnetHost -match ":")
{
$hostBytes = $TelnetHost.Split(':')
$TelnetHost = $hostBytes[0]
$Port = $hostBytes[1]
}
if ([String]::IsNullOrEmpty($TelnetHost))
{
Write-Host -Object "Error: Invalid host address (null or empty)." -ForegroundColor Red
return
}
# Setup and connect the TCP Socket.
$Socket = New-Object -TypeName System.Net.Sockets.Socket(
[System.Net.Sockets.AddressFamily]::InterNetwork,
[System.Net.Sockets.SocketType]::Stream,
[System.Net.Sockets.ProtocolType]::Tcp)
$Socket.NoDelay = $true
try
{
$Socket.Connect($TelnetHost, $Port)
}
catch
{
"Unable to connect to host {0}:{1}" -f $TelnetHost,$Port
return
}
# This state object is used to pass the connected Socket and the
# PowerShell parent Host reference to the child PowerShell object.
$State = [PSCustomObject]@{"Socket"=$Socket;"Host"=$Host;"Exception"=$null}
# This script block is used as the receive code for the Socket
# from within the child PowerShell object.
$Script = {
param($state)
# This encoding object is used to decode the return string.
[System.Text.ASCIIEncoding]$ASCIIEncoding = [System.Text.Encoding]::ASCII
# TELNET commands
[Byte]$GA = 249 # Go Ahead
[Byte]$WILL = 251 # Desire to begin
[Byte]$WONT = 252 # Refusal to perform
[Byte]$DO = 253 # Request that the other party perform
[Byte]$DONT = 254 # Demand that the other party stop performing
[Byte]$IAC = 255 # Interpret as Command
# TELNET options
[Byte]$ECHO = 1 # Used to check the echo mode
[Byte]$SUPP = 3 # Suppress go ahead
# Used to hold the number of bytes returned from the network stream.
[Int]$bytes = 0
# Buffer to hold the returned Bytes.
[Byte[]]$buffer = New-Object -TypeName Byte[]($state.Socket.ReceiveBufferSize)
# This is the main receive loop.
while ($state.Socket.Connected)
{
try
{
# The following statement will block the thread until data is received.
$bytes = $state.Socket.Receive($buffer)
}
catch
{
# This exception reference is used to pass the error back to the
# parent PowerShell process.
$state.Exception = $Error[0]
break
}
if ($bytes -gt 0)
{
$index = 0
$responseLen = 0
# The index is used to move through the buffer to analyze the received data
# looking for Telnet commands and options.
while ($index -lt $bytes)
{
if ($buffer[$index] -eq $IAC)
{
try
{
switch ($buffer[$index + 1])
{
# If two IACs are together they represent one data byte 255
$IAC
{
$buffer[$responseLen++] = $buffer[$index]
$index += 2
break
}
# Ignore the Go-Ahead command
$GA
{
$index += 2
break
}
# Respond WONT to all DOs and DONTs
{($_ -eq $DO) -or ($_ -eq $DONT)}
{
$buffer[$index + 1] = $WONT
$state.Socket.Send($buffer, $index, 3,
[System.Net.Sockets.SocketFlags]::None) | Out-Null
$index += 3
break
}
# Respond DONT to all WONTs
$WONT
{
$buffer[$index + 1] = $DONT
$state.Socket.Send($buffer, $index, 3,
[System.Net.Sockets.SocketFlags]::None) | Out-Null
$index += 3
break
}
# Respond DO to WILL ECHO and WILL SUPPRESS GO-AHEAD
# Respond DONT to all other WILLs
$WILL
{
[Byte]$action = $DONT
if ($buffer[$index + 2] -eq $ECHO)
{
$action = $DO
}
elseif ($buffer[$index + 2] -eq $SUPP)
{
$action = $DO
}
$buffer[$index + 1] = $action
$state.Socket.Send($buffer, $index, 3,
[System.Net.Sockets.SocketFlags]::None) | Out-Null
$index += 3;
break;
}
}
}
catch
{
# If there aren't enough bytes to form a command, terminate the loop.
$index = $bytes
}
}
else
{
if ($buffer[$index] -ne 0)
{
$buffer[$responseLen++] = $buffer[$index]
}
$index++
}
}
# Displays the response with no command codes on the parent PowerShell object.
$returnString = $ASCIIEncoding.GetString($buffer, 0, $responseLen)
$state.Host.UI.Write($returnString)
}
}
} # End of the child PowerShell script definition.
# Create a child PowerShell object to run the background Socket receive method.
$PS = [PowerShell]::Create()
$PS.AddScript($Script).AddArgument($State) | Out-Null
[System.IAsyncResult]$AsyncJobResult = $null
try
{
# The receive job is started asynchronously.
$AsyncJobResult = $PS.BeginInvoke()
while ($Socket.Connected)
{
# Wait for keys to be pressed in the parent PowerShell console window.
# This is a blocking call so the telnet session may get disconnected
# while waiting for a key to be pressed.
$Key = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyUp").Character
# Check the socket and see if it is still active.
$PollCheck1 = $Socket.Poll(5000,[System.Net.Sockets.SelectMode]::SelectRead)
$PollCheck2 = ($Socket.Available -eq 0)
if (($PollCheck1 -and $PollCheck2) -or ($State.Exception -ne $null)) { break }
# Socket seems good, send the data.
$Data = $ASCIIEncoding.GetBytes($key)
$Socket.Send($Data) | Out-Null
}
}
finally
{
# Cleanup the socket and child PowerShell process.
if ($Socket -ne $null)
{
$Socket.Close()
$Socket.Dispose()
$Socket = $null
}
if ($PS -ne $null -and $AsyncJobResult -ne $null)
{
$PS.EndInvoke($AsyncJobResult)
$PS.Dispose()
}
}