使用exec.Command运行sqlite3 .backup

时间:2019-03-26 15:05:51

标签: go sqlite

我正在尝试使用sqlite3 .backup命令以这种SO答案https://stackoverflow.com/a/25684912/426853给出的方式从Go备份数据库。

以下内容始终可以从命令行使用:

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将参数传递给Shell的方式,并且问题出在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 个答案:

答案 0 :(得分:1)

您根本不需要额外的引号,因此应该这样做:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>localhost</key>
        <dict>
            <key>NSTemporaryExceptionAllowsInsecureHTTPSLoads</key>
            <false/>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <key>NSTemporaryExceptionMinimumTLSVersion</key>
            <string>1.0</string>
            <key>NSTemporaryExceptionRequiresForwardSecrecy</key>
            <false/>
        </dict>
    </dict>
</dict>

引号由shell解析,以便将@WebServlet({"/RegistrationServlet"}) public class RegistrationServlet extends HttpServlet { Statement st = null; private static final long serialVersionUID = 1L; public RegistrationServlet() {} UserData ud = new UserData(); String email99 = ud.getEmail(); protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {} protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { PrintWriter out = response.getWriter(); ud.setFirst_name(request.getParameter("f1")); ud.setLast_name(request.getParameter("l1")); ud.setUname(request.getParameter("uname")); ud.setPhone(request.getParameter("p1")); ud.setEmail(request.getParameter("e1")); ud.setUser_dob(request.getParameter("udate")); ud.setPassword(request.getParameter("pwd")); ud.setConfirm_password(request.getParameter("cpwd")); if (ud.getConfirm_password().equals(ud.getPassword())) { try { Class.forName("com.mysql.cj.jdbc.Driver"); Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/dbname?autoReconnect=true&useSSL=FALSE", "root", "password"); st = con.createStatement(); String query1 = "select email from users"; ResultSet rs = st.executeQuery(query1); while(rs.next()) { String ename = rs.getString("email"); System.out.println("DB Email IDs:- "+ename); if(ename.equals(email99)) { response.sendRedirect("Register.jsp"); } else { writeData(); } con.close(); rs.close(); } } catch (Exception e) { // TODO Auto-generated catch block System.out.println(e.getMessage()); } 作为单个参数传递给exec.Command("sqlite3", dbpath, fmt.Sprintf(".backup '%s'", bakpath)) 。使用.backup 'somefile'时,不涉及任何外壳程序,这也是将命令传递为多个参数的原因。