Запуск sqlite3 .backup с помощью exec.Command - PullRequest
0 голосов
/ 26 марта 2019

Я пытаюсь создать резервную копию базы данных из Go, используя команду sqlite3 .backup в порядке, указанном в этом ответе SO https://stackoverflow.com/a/25684912/426853.

Следующее всегда работает из командной строки:

sqlite3 /home/pi/pgclogs/smartlog.db ".backup '/home/pi/pgcdata/smartlog.db.bak'"

Я кодировал его в Go следующим образом:

func DbBackup() (err error) {
    dbpath := "/home/pi/pgclogs/smartlog.db"
    bakpath := "/home/pi/pgcdata/smartlog.db.bak"
    cmd := exec.Command("sqlite3", dbpath, fmt.Sprintf("\".backup '%s'\"", bakpath))
    out, err := cmd.CombinedOutput()
    if err != nil {
        return fmt.Errorf("dbBackup failed : %s : %v", string(out), err)
    }
    return
} 

и у меня есть тестовый файл, который вызывает его так:

func TestDbBackup(t *testing.T) {
    var err error
    err = DbBackup()
    if err != nil {
        t.Errorf("backup failed : %v", err)
    }
} 

Тест сообщает об синтаксической ошибке из sqlite3.

--- FAIL: TestDbBackup (0.01s)
    db_backup_test.go:22: backup failed : dbBackup failed : Error: near "".backup '/home/pi/pgcdata/smartlog.db.bak'"": syntax error
         : exit status 1

Я подозреваю, что проблема в том, как cmd.CombinedOutput передает аргументы в оболочку, и что проблема заключается в кавычках в вызове fmt.Sprintf. Я пытался изменить его на

fmt.Sprintf(`".backup '%s'"`, bakpath)

но результат тот же. Я также попытался поставить echo перед командой, то есть exec.Command("echo", "sqlite3", dbpath, ... и распечатать вывод. Вывод выглядит абсолютно корректно

sqlite3 /home/pi/pgclogs/smartlog.db ".backup '/home/pi/pgcdata/smartlog.db.bak'"

и работает правильно при вставке в командную строку. Я уверен, что пропускаю что-то простое, но я потратил больше часа и до сих пор не вижу этого.

1 Ответ

1 голос
/ 26 марта 2019

Вам вообще не нужны дополнительные кавычки, так что это должно сделать:

exec.Command("sqlite3", dbpath, fmt.Sprintf(".backup '%s'", bakpath))

Кавычки анализируются оболочкой, так что .backup 'somefile' передается sqlite3 как один аргумент,При использовании exec.Command оболочка не используется, поэтому вы также передаете команду, разделенную на несколько параметров.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...