代码拉取完成,页面将自动刷新
/*
Nging is a toolbox for webmasters
Copyright (C) 2019-present Wenhui Shen <swh@admpub.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package utils
import (
"context"
"fmt"
"io"
"io/ioutil"
"log"
"os"
"os/exec"
"path/filepath"
"regexp"
"strings"
"github.com/admpub/errors"
"github.com/admpub/nging/application/library/cron"
"github.com/admpub/nging/application/library/dbmanager/driver"
"github.com/webx-top/com"
"github.com/webx-top/db"
)
/*
mysqldump 参数说明:
-d 结构(--no-data:不导出任何数据,只导出数据库表结构)
-t 数据(--no-create-info:只导出数据,而不添加CREATE TABLE 语句)
-n (--no-create-db:只导出数据,而不添加CREATE DATABASE 语句)
-R (--routines:导出存储过程以及自定义函数)
-E (--events:导出事件)
--triggers (默认导出触发器,使用--skip-triggers屏蔽导出)
-B (--databases:导出数据库列表,单个库时可省略)
--tables 表列表(单个表时可省略)
*/
var (
cleanRegExp = regexp.MustCompile(` AUTO_INCREMENT=[0-9]*\s*`)
)
// Export 导出SQL文件
func Export(ctx context.Context, cfg *driver.DbAuth, tables []string, structWriter, dataWriter interface{}, resetAutoIncrements ...bool) error {
if len(tables) == 0 {
return errors.New(`No table selected for export`)
}
log.Println(`Starting backup:`, tables)
var (
port, host string
resetAutoIncrement bool
)
if len(resetAutoIncrements) > 0 {
resetAutoIncrement = resetAutoIncrements[0]
}
if p := strings.LastIndex(cfg.Host, `:`); p > 0 {
host = cfg.Host[0:p]
port = cfg.Host[p+1:]
} else {
host = cfg.Host
}
if len(port) == 0 {
port = `3306`
}
if !com.InSlice(cfg.Charset, Charsets) {
return errors.New(`字符集charset值无效`)
}
args := []string{
"--default-character-set=" + cfg.Charset,
"--single-transaction",
//"--column-statistics=0",//低版本不支持
"--set-gtid-purged=OFF",
"--no-autocommit",
//"--ignore-table="+cfg.Db+".details",
//"--ignore-table="+cfg.Db+".large_table2",
"--opt",
"-d", //加上此参数代表只导出表结构,不导出数据
"-h" + host,
"-P" + port,
"-u" + cfg.Username,
"-p" + cfg.Password,
cfg.Db,
//"--result-file=/root/backup.sql",
}
clean := func(w io.Writer, r io.ReadCloser) {
r.Close()
if c, y := w.(io.Closer); y {
c.Close()
}
}
var typeOptIndex int
for index, value := range args {
if value == `-d` {
typeOptIndex = index
break
}
}
//args = append(args, `--tables`)
args = append(args, tables...)
rec := cron.NewCmdRec(1000)
for index, writer := range []interface{}{structWriter, dataWriter} {
if writer == nil {
continue
}
if index > 0 {
args[typeOptIndex] = `-t` //导出数据
}
//log.Println(`mysqldump`, strings.Join(args, ` `))
cmd := exec.CommandContext(ctx, "mysqldump", args...)
cmd.Stderr = rec
var (
w io.Writer
err error
onFinish func() error
)
switch v := writer.(type) {
case io.Writer:
w = v
case string:
dir := filepath.Dir(v)
if _, err := os.Stat(dir); os.IsNotExist(err) {
err = os.MkdirAll(dir, os.ModePerm)
if err != nil {
return fmt.Errorf(`Failed to backup: %v`, err)
}
}
w, err = os.Create(v)
if err != nil {
return fmt.Errorf(`Failed to backup: %v`, err)
}
onFinish = func() error {
if index > 0 {
return nil
}
if resetAutoIncrement {
return ResetAutoIncrement(v)
}
return nil
}
default:
return errors.Wrapf(db.ErrUnsupported, `SQL Writer Error: %T`, v)
}
stdout, err := cmd.StdoutPipe()
if err != nil {
clean(w, stdout)
return fmt.Errorf(`Failed to backup: %v`, err)
}
if err := cmd.Start(); err != nil {
clean(w, stdout)
return fmt.Errorf(`Failed to backup: %v`, err)
}
if _, err := io.Copy(w, stdout); err != nil {
clean(w, stdout)
return fmt.Errorf(`Failed to backup: %v`, err)
}
if err := cmd.Wait(); err != nil {
clean(w, stdout)
return errors.New(err.Error() + `: ` + rec.String())
}
if err := cmd.Wait(); err != nil {
clean(w, stdout)
return errors.New(err.Error() + `: ` + rec.String())
}
clean(w, stdout)
if onFinish != nil {
if err = onFinish(); err != nil {
return err
}
}
}
return nil
}
// ResetAutoIncrement 重置AUTO_INCREMENT值为0
func ResetAutoIncrement(sqlStructFile string) error {
b, err := ioutil.ReadFile(sqlStructFile)
if err != nil {
return err
}
b = cleanRegExp.ReplaceAll(b, []byte(` `))
return ioutil.WriteFile(sqlStructFile, b, 0666)
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。