Как выполнить несколько команд в интерактивной оболочке - PullRequest
0 голосов
/ 02 апреля 2019

Мое приложение работает со всеми видами команд оболочки, предоставляемых из консоли (curl, date, ping, что угодно). Теперь я хотел бы охватить случай интерактивными командами оболочки (такими как mongo shell), используя os/exec.

  • например. в качестве первого шага подключитесь к mongodb: mongo --quiet --host=localhost blog

  • затем выполните произвольное число команд, получая результат на каждом шаге db.getCollection('posts').find({status:'INACTIVE'})

  • , а затем exit

Я попробовал следующее, но это позволяет мне выполнять только одну команду для каждого подключения монго:

func main() {

    cmd := exec.Command("sh", "-c", "mongo --quiet --host=localhost blog")

    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr

    stdin, _ := cmd.StdinPipe()

    go func() {
        defer stdin.Close()
        io.WriteString(stdin, "db.getCollection('posts').find({status:'INACTIVE'}).itcount()")
        // fails, if I'll do one more here
    }()

    cmd.Run()
    cmd.Wait()
}

Есть ли способ запустить несколько команд, получая результат stdout за выполненную команду?

1 Ответ

1 голос
/ 02 апреля 2019

Как заметил Флимзи, вы должны обязательно использовать драйвер монго для работы с монго, а не пытаться взаимодействовать с ним через shell exec.

Однако, чтобы ответить на корневой вопрос, конечно, вы можете выполнить несколькоКоманды - нет причин, по которым ты не можешь.Каждый раз, когда вы пишете в процесс 'stdin', вы как будто набираете терминал.В этом нет никаких секретных ограничений, кроме процессов, которые специально обнаруживают, подключены ли они к TTY.

Однако у вашего кода есть несколько проблем - вам определенно следует просмотреть документацию пакета os/exec .Вы звоните cmd.Run, который:

запускает указанную команду и ожидает ее завершения.

А затем вызывает cmd.Wait, что ...также ожидает завершения команды.Вы пишете в канал stdin в программе, даже если это очень сериализованный процесс: вы хотите записать в канал для выполнения команды, получить результат, написать другую команду, получить другой результат ... параллелизм только мешаетимеет значение и не должен использоваться здесь.И вы не отправляете новые строки, чтобы сообщить Mongo, что вы закончили писать команду (точно так же, как вы это делали в оболочке - Mongo не просто начнет выполняться, как только вы войдете в закрывающую парен, вы должны нажать enter).

Что бы вы хотели сделать, чтобы взаимодействовать с процессом через stdin / stdout (опять же, отметив, что это абсолютно не способ взаимодействия с базой данных , но может действителен для других внешних команд):

cmd := exec.Command("sh", "-c", "mongo --quiet --host=localhost blog")

cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr

stdin, _ := cmd.StdinPipe()

// Start command but don't wait for it to exit (yet) so we can interact with it
cmd.Start()

// Newlines, like hitting enter in a terminal, tell Mongo you're done writing a command
io.WriteString(stdin, "db.getCollection('posts').find({status:'INACTIVE'}).itcount()\n")
io.WriteString(stdin, "db.getCollection('posts').find({status:'ACTIVE'}).itcount()\n")

// Quit tells it you're done interacting with it, otherwise it won't exit
io.WriteString(stdin, "quit()\n")

stdin.Close()

// Lastly, wait for the process to exit
cmd.Wait()
...