Я пытаюсь создать резервную копию базы данных из 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'"
и работает правильно при вставке в командную строку. Я уверен, что пропускаю что-то простое, но я потратил больше часа и до сих пор не вижу этого.