#windows #go #cmd
# #Windows #Вперед #cmd
Вопрос:
go версия go1.15.6 windows / amd64 dev ОС Windows [Версия 10.0.19041.630]
У меня есть приложение Go, в котором я запускаю AWS CLI с помощью exec.Cmd.Run(). Я создаю класс Cmd и заполняю аргументы.
Перед запуском Cmd я использую метод .String() для просмотра команды, которую нужно запустить. Если я беру это значение, копирую его в оболочку, команда выполняется без каких-либо изменений в выходных данных, предоставленных мне, без каких-либо сообщений о проблемах.
Однако, когда я запускаю команду, она не возвращает сообщение об ошибке. Когда я отлаживаю скрипт, он терпит неудачу, потому что он говорит, что AWS CLI сообщает, что параметр неверен.
Вопросы:
- Можно ли увидеть 100% необработанное представление того, что выполняется? Он не соответствует возвращаемому значению .String()
- Есть ли лучший способ вызвать команду уровня операционной системы, которую мне не хватает?
Реальный Пример:
cmd := amp;exec.Cmd{
Path: awsPath,
Args: args,
Stdout: amp;stdout,
Stderr: amp;stderr,
}
fmt.Printf("Command: %sn", cmd.String())
// c:PROGRA~1AmazonAWSCLIV2aws.exe --profile testprofile --region us-east-1 --output json ec2 describe-network-interfaces --filters Name=group-id,Values=sg-abc123
// Running above works 100% of the time if ran from a shell window
err := cmd.Run()
// always errors out saying the format is incorrect
Репликация проблемы на GoPlayground
https://play.golang.org/p/mvV9VG8F0oz
Комментарии:
1. Обратитесь к pkg.go.dev/os/exec#Cmd
2. Мы не можем понять, что неверно в вашем формате
args
иawsPath
когда вы не показываете, каковы они.3. Не могли бы вы, пожалуйста, показать немного больше кода, чтобы я мог воспроизвести и разобраться в вашей ситуации? И какова ошибка, выводимая в вашей консоли?
4. @JimB, я предполагаю, что вы имеете в виду «Мы не можем определить, что неверно»? Это была моя ошибка, я думал, что предоставление выходных данных было ясным в отношении того, каковы значения. Я отредактировал свой ответ, включив в него игровую площадку go, которая демонстрирует проблемы. Однако обратите внимание, что она не может быть полностью запущена онлайн.
Ответ №1:
Из источника cmd.String:
// String returns a human-readable description of c.
// It is intended only for debugging.
// In particular, it is not suitable for use as input to a shell.
// The output of String may vary across Go releases.
Вы видите обратное, но проблема та же: при просмотре печатной командной строки не отображается точный путь к исполняемому файлу (есть ли посторонний пробел или непечатаемый символ?), То же самое с аргументами (посторонние символы?).
Используется fmt.Printf("cmd : %qn", cmd.Path)
для отображения любых скрытых символов Юникода и т.д. И используйте ту же технику с каждым из аргументов.
Ответ №2:
РЕДАКТИРОВАТЬ: я нашел основную причину вашей проблемы, с которой вы столкнулись: os / exec
// Path is the path of the command to run. // // This is the only field that must be set to a non-zero // value. If Path is relative, it is evaluated relative // to Dir. Path string // Args holds command line arguments, including the command as **Args[0]**. // If the Args field is empty or nil, Run uses {Path}. // // In typical use, both Path and Args are set by calling Command. Args []string
Поэтому, если у вас есть объявление Cmd.Path := "/usr/local/bin/aws"
, вы должны объявить Cmd. Args
так: Args: []string{"", "s3", "help"},
потому Args
что включает команду, как Args[0]
в приведенной выше ссылке на документ.
Наконец, я думаю, вы можете выполнить команду, подобную этой, для простого и эффективного:
package main
import (
"bytes"
"fmt"
"os/exec"
)
func main() {
stdout := amp;bytes.Buffer{}
stderr := amp;bytes.Buffer{}
name := "/usr/local/bin/aws"
arg := []string{"s3", "help"}
cmd := exec.Command(name, arg...)
cmd.Stderr = stderr
cmd.Stdout = stdout
fmt.Printf("Command: %qn", cmd.String())
err := cmd.Run()
if err != nil {
fmt.Println("Error: ", stderr.String())
}
fmt.Println("Output: ", stdout.String())
}
=========
$ go run main.go
Command: "/usr/local/bin/aws s3 help"
Выполнено.
Комментарии:
1. могу ли я предложить использовать
%q
, напримерfmt.Printf("Command: %qn", cmd.String())
. При этом строка будет заключена в кавычки, но также будут показаны любые непечатаемые и / или неправильные символы юникода, которые могут привести к сбою API, но останутся незамеченными, если%s
они используются.2. Tks @colm.anseo, я отредактировал свой ответ и использую ваше предложение для улучшения, Tks
3. @colm.anseo Я очень ценю это! Я отметил это и буду делать это в будущем!
4. @ThoQuach Я попробую это утром и посмотрю, к чему это приведет. Я ценю вашу помощь.