Executing PowerShell Scripts via Cygwin SSH on Windows Server: A Comprehensive Guide


2 views

When working with legacy Windows Server 2003 systems running CopSSH (Cygwin + SSHD), executing PowerShell scripts through SSH sessions presents unique technical hurdles. The fundamental issue stems from the environment pathing and shell interpretation differences between Cygwin's Unix-like environment and Windows' native PowerShell.

To bridge these environments, we need a three-part approach:

  1. Proper PATH configuration in Cygwin
  2. PowerShell execution wrapper
  3. Output handling mechanism

First, verify PowerShell is accessible from Cygwin:

# Test basic PowerShell accessibility
$ /cygdrive/c/WINDOWS/system32/WindowsPowerShell/v1.0/powershell.exe -Command "Get-Host"

Create a helper script runps.ps1:

# PowerShell script to handle input/output properly
param(
    [string]$scriptPath,
    [string]$arguments
)

$ErrorActionPreference = "Stop"
try {
    $scriptContent = Get-Content -Path $scriptPath -Raw
    $scriptBlock = [scriptblock]::Create($scriptContent)
    & $scriptBlock @arguments
} catch {
    Write-Error $_.Exception.Message
    exit 1
}

For direct SSH command execution:

ssh username@server '/cygdrive/c/WINDOWS/system32/WindowsPowerShell/v1.0/powershell.exe -File "C:/path/to/runps.ps1" -scriptPath "C:/scripts/myscript.ps1"'

For complex scenarios, create a Cygwin wrapper script ps-wrapper.sh:

#!/bin/bash
POWERSHELL="/cygdrive/c/WINDOWS/system32/WindowsPowerShell/v1.0/powershell.exe"
SCRIPT_PATH=$(cygpath -w "$1")
shift

"$POWERSHELL" -NonInteractive -NoProfile -ExecutionPolicy Bypass -Command "& { . \"$SCRIPT_PATH\"; $@ }"
  • Path Translation: Always use cygpath to convert between Unix and Windows paths
  • Encoding Problems: Set $OutputEncoding in PowerShell to UTF-8
  • Permission Errors: Verify execute permissions on both Cygwin and Windows sides

For frequent executions, consider these optimizations:

# Persistent PowerShell session using Named Pipes
ssh username@server 'mkfifo /tmp/pspipe; /cygdrive/c/WINDOWS/system32/WindowsPowerShell/v1.0/powershell.exe -Command "& { while($true) { $cmd = Get-Content /tmp/pspipe; if($cmd -eq \'exit\') { break }; Invoke-Expression $cmd | Out-String } }"'

When working with legacy Windows Server 2003 systems using CopSSH (Cygwin + SSHD), running PowerShell scripts remotely presents unique challenges. The core issue involves bridging the Unix-like Cygwin environment with Windows-native PowerShell execution.

First, verify your system configuration:


# Check PowerShell availability
which powershell
# Or for Windows Server 2003 (PS 1.0):
which powershell.exe

The most straightforward approach uses the PowerShell CLI:


ssh user@server 'powershell.exe -ExecutionPolicy Bypass -File C:\\path\\to\\script.ps1'

Key parameters to note:

  • -ExecutionPolicy Bypass - Overrides default restrictions
  • Double backslashes in Windows paths
  • Single quotes around the entire command

To properly capture output streams:


ssh user@server 'powershell.exe -NonInteractive -NoProfile -Command "& { C:\\script.ps1 *>&1 }"'

This redirects all streams (output, errors, warnings) through stdout.

Create a Cygwin bash wrapper (runps.sh):


#!/bin/bash
WINPATH=$(cygpath -w "$1")
powershell.exe -NonInteractive -NoProfile -ExecutionPolicy Bypass -Command "& { $WINPATH }"

Usage example:


ssh user@server '/path/to/runps.sh /cygdrive/c/scripts/test.ps1'

For authentication problems, check:


# Verify SSH service account has execute rights
icacls C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe

Path translation problems? Use Cygwin's path conversion:


ssh user@server 'powershell.exe -Command "& { $(cygpath -w /cygdrive/c/scripts/test.ps1) }"'

For frequent executions, consider:


# Keep a persistent PowerShell session
ssh -t user@server 'powershell.exe -NoExit -Command "& { C:\\script.ps1 }"'

The -t flag allocates a pseudo-terminal for interactive sessions.