## Forums/Go Community & Support/Knowledge Base

### Go's custom command

Sriram Narayan
posted this on January 6, 2013, 20:50

Update: March 2013

Custom command is now enhanced to lookup from a command repository.

==========================================================

Go’s custom command may be used to run any command-line tool available on the Go Agent. Typically authored through the custom command dialog, it looks like this when saved in Go’s config file.

<exec command="echo">

<arg>hello</arg>

</exec>

The agent simply execs this at runtime. Note that this is a plain exec, not a shell exec, so the following won’t have the desired effect (it will simply print “$HOME”): <exec command="echo"> <arg>$HOME</arg>

</exec>

There are two ways to make this work. One is to put the command into a script file, say myecho.sh:

#!/bin/bash

echo $HOME or myecho.bat: echo %HOME% and then write the Go custom command task as: <exec command="myecho.sh"> </exec> or <exec command="myecho.bat"> </exec> The other option is to provide an explicit shell context to the custom command like this: <exec command="/bin/bash"> <arg>-c</arg> <arg>echo$HOME</arg>

</exec>

or

<exec command="cmd">

<arg>/c</arg>

<arg>echo %HOME%</arg>

</exec>

In the above examples, HOME is assumed to defined on the agent (via .bash_profile etc). But the above examples are also valid for environment variables defined via Go (built-in or otherwise). So, for example:

<exec command="/bin/bash">

<arg>-c</arg>

<arg>echo $GO_PIPELINE_LABEL</arg> </exec> Finally, let’s consider cases where quoting is needed. Suppose you need to send an email from the command-line. You might do something like this: <exec command="/bin/bash"> <arg>-c</arg> <arg>echo hello there | mail -s "subject line" blah@gmail.com</arg> </exec> Without the double quotes, the subject part of that mail could not have more than one word. Single-quotes could replace double-quotes here. Most times, you’ll need single-quotes when you need to nest quotes. Say you need to send that email from a remote box (maybe only it has SMTP settings set properly). You could do something like this: <exec command="/bin/bash"> <arg>-c</arg> <arg>ssh remotehost 'echo hello there | mail -s "subject line" blah@gmail.com'</arg> </exec> You need the single quotes here so that the whole “echo … | mail …” part is sent to the remote host. ### Windows tips Go considers the task as successful if the custom command exits with zero, else the task (and it's job) are failed. Some windows commands don't follow this convention. Given robocopy's behaviour, the following task fails even if robocopy doesn't. <exec command="robocopy"> <arg>src-folder</arg> <arg>\\remote-node\target-folder</arg> <arg>*.exe</arg> </exec> To make it work with Go, we re-write it as: <exec command="cmd"> <arg>/c</arg> <arg>robocopy src-folder \\remote-node\target-folder *.exe & rundll32</arg> </exec> rundll32 without any arguments is effectively a no-op. This sets the overall errorlevel to zero. Of course, this means the task won't fail even if there is a genuine robocopy failure so use with care. ### Powershell In case of Powershell script-blocks, the exit code is non-zero if any of the cmdlets in the script block writes to the error-stream. Writing status to error stream is common practice for utils like curl and git. To handle this in powershell V2, we manually clear the$error variable in the following command that executes a git pull remotely using powershell and winrm. V3 claims to have -ErrorAction:Ignore option for this.

<exec command="cmd">
<arg>/c</arg>
<arg>powershell $pass = convertto-securestring %password% -asplaintext -force;$mycred = new-object -typename   System.Management.Automation.PSCredential -argumentlist "DOMAIN\%userid%",$pass; invoke-command -computername %remote-computer% -ScriptBlock {cd c:\path\to\git-repo;git pull;$error.clear()} -credential \$mycred</arg>
</exec>

### Prefer version controlled scripts over fully inline commands

The above powershell hack is a limited workaround to make it work as a fully inline custom command. Fully inline commands are useful to quickly iterate and get the command working. It is better to move long complicated commands into version controlled script files (make them part of the material for the pipeline) and simply run the script from inside a Go custom command.

<exec command="powershell">

<arg>remote-git-pull.ps1</arg>

</exec>