On remote machine I just used psexec.exe to run specific command, the output of the cmd is intact while testing in shell.
Only the first line was printed out when submitting the cmd in Golang.
I tried to use winexe on linux platform, but the Symantec anti-virus treats it as PUA, then I turned back to windows platform.
func main() {
cmd := exec.Command("C:\\Users\\v\\go\\src\\asys\\ss\\psexec.exe", "\\\\192.168.0.64", "-nobanner", "-accepteula", "-u", "vz", "-p", "1", "-s", "cmd", "/c", "ipconfig")
var out bytes.Buffer
multi := io.MultiWriter(os.Stdout, &out)
cmd.Stdout = multi
if err := cmd.Run(); err != nil {
log.Fatalln(err)
}
fmt.Printf("
*** FULL OUTPUT *** %s
", out.String())
}
output:
Windows IP Configuration
*** FULL OUTPUT ***
Windows IP Configuration
Process finished with exit code 0
Not to answer your question directly, but I'm afraid you might be falling victim of the so-called XY Problem: there's no point in jumping through that many hoops to merely collect an information about the configuration of the IP stack of the target host—Windows provides special means, called WMI, to carry out such tasks.
So, instead of calling psexec.exe
to call—on the target host—cmd.exe
to call ipconfig.exe
, you may just defer this task to one of the queries supported by WMI.
I'd suggest using either Win32_NetworkAdapter
or Win32_IP4RouteTable
(or both)—depending on which kind of data you actually need (configuration of NICs or routing data).
A working sample, using github.com/StackExchange/wmi
is:
package main
import (
"log"
"os"
"time"
"github.com/StackExchange/wmi"
)
type win32_NetworkAdapter struct {
AdapterType string
AdapterTypeID uint16
AutoSense bool
Availability uint16
Caption string
ConfigManagerErrorCode uint32
ConfigManagerUserConfig bool
CreationClassName string
Description string
DeviceID string
ErrorCleared bool
ErrorDescription string
GUID string
Index uint32
InstallDate time.Time
Installed bool
InterfaceIndex uint32
LastErrorCode uint32
MACAddress string
Manufacturer string
MaxNumberControlled uint32
MaxSpeed uint64
Name string
NetConnectionID string
NetConnectionStatus uint16
NetEnabled bool
NetworkAddresses []string
PermanentAddress string
PhysicalAdapter bool
PNPDeviceID string
PowerManagementCapabilities []uint16
PowerManagementSupported bool
ProductName string
ServiceName string
Speed uint64
Status string
StatusInfo uint16
SystemCreationClassName string
SystemName string
TimeOfLastReset time.Time
}
type win32_IP4RouteTable struct {
Age int32
Caption string
Description string
Destination string
Information string
InstallDate time.Time
InterfaceIndex int32
Mask string
Metric1 int32
Metric2 int32
Metric3 int32
Metric4 int32
Metric5 int32
Name string
NextHop string
Protocol uint32
Status string
Type uint32
}
func main() {
var compName string
switch len(os.Args) {
case 1:
compName = "."
case 2:
compName = os.Args[1]
default:
log.Fatalf("usage: %s [COMPUTER]", os.Args[0])
}
var dst []win32_NetworkAdapter
//var dst []win32_IP4RouteTable
q := wmi.CreateQuery(&dst, "")
err := wmi.Query(q, &dst, compName)
if err != nil {
log.Fatalf("%#v
", err)
}
for _, v := range dst {
log.Printf("%#v
", v)
}
}
As presented, it queries the host whose name is passed on the command line (or, missing that, localhost) for the NIC config.
To get routing data instead, comment out the first var dst ...
statement and uncomment the second one. Hope you'll get the idea.