Grofit
Grofit

Reputation: 18465

Teamcity powershell runner to remotely run commands on server

I have a strange issue where TeamCity just hangs whenever i try to do a remote call to one of our test servers.

Currently the build steps are:

  • Template files for
  • Compile code in
  • Package project
  • Send package to test servers
  • Unzip package on test servers

Now it all works fine up until the last stage, unzipping the package on the remote server. Now I wanted to just run a powershell command to connect up and run the commands then exit. This all works fine if I were using powershell from remote desktop, and the user credentials provided are correct.

An example of what is being run is below:

$password = ConvertTo-SecureString "%PasswordVar%" -AsPlainText -Force
$credentials = New-Object System.Manager.Automation.PsCredential("%UsernameVar%", $password)
etsn -computername %TestServer1Var% -Credential $credentials

When this is called TeamCity just hangs, it has to be manually stopped or it will stay on this step on the agent forever. I have tried not using credentials, I have tried not using etsn and using the full command name, also tried other remote command methods, nothing seems to work.

So is there a way to get TeamCity to actually run the commands? or find out what is causing it to process this step indefinately?

Upvotes: 6

Views: 16397

Answers (3)

Mykhaylo Adamovych
Mykhaylo Adamovych

Reputation: 20986

Just an addition to accepted answer

$scriptBlock = [Scriptblock]::Create(@'
  echo 'before'
  ipconfig /all
  echo 'after'
'@)

Invoke-Command -ComputerName AD01 -ScriptBlock $scriptBlock

source
don't use backquote

Previous makes possible to define %PowerShell.header% and %PowerShell.footer% parameters not to write boilerplate code in TC steps

Upvotes: 0

Ocelot
Ocelot

Reputation: 1753

Invoke-Command works well if the script you have to run on the server is short and you have to wait for it to finish execution.

My issue was that I wanted to start a service on the remote server and just log the stuff within the server and let teamcity build to continue execution. With Invoke-Command, teamcity did execute the process remotely, but kept waiting for that process to finish n return. If you're looking for something that just invokes a long running process on the server and forgets about it, try this:

This solution worked best for me:

1) Place the script to be executed remotely, in a file within the server.. lets say startup.bat

call Powershell.exe -executionpolicy remotesigned -File %1\bin\startup.ps1 

This basically executes another powershell script located in the web server.

Start-Process -WindowStyle hidden java -ArgumentList '-jar', "$APP_HOME\bin\test-api.jar" -PassThru

Make sure that there's a teamcity Build step to deploy these files to the Web server.

2) Create a teamcity Build Step to execute a powershell script file

Sample Powershell Command to be executed by Teamcity:

$SERVER = (Get-Item env:SERVER_NAME).Value
$APP_HOME = (Get-Item env:APP_HOME).Value
$STARTUP_SCRIPT_PATH = "$APP_HOME\bin\startup.bat"

Function Remote-Process {
  param(
    [string]$ComputerName,
    [string]$Cmd
  )

  echo "Invoking Remote Script.."
  $RETURNVAL = ([WMICLASS]"\\$ComputerName\ROOT\CIMV2:win32_process").Create($Cmd)
  echo $RETURNVAL
}

$COMMAND = "$STARTUP_SCRIPT_PATH $APP_HOME"
$output = Remote-Process $SERVER $COMMAND

echo $OUTPUT

Where APP_HOME is the Absolute path to the folder (on remote serer) where your web app is deployed.

That's about it. This way, you can even execute services and the remote process will not be killed and lets you continue with the build chain.

Upvotes: 0

Grofit
Grofit

Reputation: 18465

This was a mix of small issues, for 1 the user when queried via team city was not resolving the domain correctly so this needed to be added to the username some-user@some-domain. There was also an issue in that the there was some sort of connection limit which was being hit when doing the PSSESSION connection, however if I changed over to Invoke-Command with a script block it worked fine.

If it helps anyone here is the command I ended up with to unzip a remote file, using 7zip command line as the native solution never seemed to work.

$password = ConvertTo-SecureString "%TestServer.Password%" -AsPlainText -Force
$credentials = New-Object System.Management.Automation.PsCredential("%TestServer.Username%",$password)

$scriptBlock1 = {`
`
    $sevenZip = "%TestServer.ReleasePath%\7za.exe"; `
    &$sevenZip x %TestServer.ReleasePath%\web-package.zip -o%TestServer.WebPath% * -aoa; `
}
Invoke-Command -computername %TestServer.Server% -Credential $credentials -scriptblock $scriptBlock1

One thing to remember is that the username contains the domain as listed above, also the magic quotes are needed to allow the script block to be spread over lines as well as the semi colon to indicate the tasks should be run together.

Upvotes: 8

Related Questions