起因

最近还是有一些小伙伴反馈加载速度有点慢,那行吧,部署一个距离中国近一点的节点,且关闭 cf 保护来提速好了。

那么涉及到一个问题就是怎么部署比较方便,考虑了 rsync 等等后来还是决定写一个小工具来当作 webhook 部署。

部署流程

流程很简单就不画图了:

  1. github 完成构建
  2. 打包
  3. 使用 webhook 上传到服务器
  4. 服务器上解压缩,并部署到指定目录

部署工具

先讲部署工具,因为要跑到服务器上用,我希望打包完小一点,同时可以理解执行,考虑了一下用 go 是个不错的选择,估计 100 行内就可以解决。

package main  
  
import (  
    "archive/zip"  
    "flag"    "fmt"    "github.com/google/uuid"    "io"    "net/http"    "os"    "path/filepath"    "strings")  
  
var (  
    uploadPath  string  
    extractPath string  
    password    string  
    uploadUrl   string  
    port        string  
    maxSize     int64 = 30 // 30 MB  
)  
  
func main() {  
    flag.StringVar(&uploadPath, "uploadPath", "./uploads", "Directory to save uploaded files")  
    flag.StringVar(&extractPath, "extractPath", "./extracted", "Directory to extract files")  
    flag.StringVar(&password, "password", "123456", "Password to upload")  
    flag.StringVar(&uploadUrl, "uploadUrl", "/upload-url", "URL to upload file")  
    flag.StringVar(&port, "port", "1234", "Port to listen")  
    flag.Parse()  
  
    http.HandleFunc(uploadUrl, uploadHandler)  
    fmt.Println("Server started at :" + port + " and listening...")  
    err := http.ListenAndServe(":"+port, nil)  
    if err != nil {  
       return  
    }  
}  
  
func uploadHandler(w http.ResponseWriter, r *http.Request) {  
    if r.Method != http.MethodPost {  
       http.Error(w, "Invalid request method", http.StatusMethodNotAllowed)  
       return  
    }  
  
    // 解析表单数据  
    // 验证密码  
    if r.FormValue("password") != password {  
       http.Error(w, "Invalid password", http.StatusUnauthorized)  
       return  
    }  
    err := r.ParseMultipartForm(maxSize << 20) // 30 MB  
    if err != nil {  
       http.Error(w, err.Error(), http.StatusInternalServerError)  
       return  
    }  
  
    // 获取上传文件  
    file, _, err := r.FormFile("file")  
    if err != nil {  
       http.Error(w, err.Error(), http.StatusInternalServerError)  
       return  
    }  
    defer file.Close()  
  
    // 创建上传目录  
    err = os.MkdirAll(uploadPath, os.ModePerm)  
    // 文件名需要保证唯一性  
    id := uuid.New().String()  
    tempFilePath := filepath.Join(uploadPath, id+".zip")  
    tempFile, err := os.Create(tempFilePath)  
    if err != nil {  
       http.Error(w, err.Error(), http.StatusInternalServerError)  
       return  
    }  
    defer tempFile.Close()  
  
    // 保存上传文件到临时文件  
    _, err = io.Copy(tempFile, file)  
    if err != nil {  
       http.Error(w, err.Error(), http.StatusInternalServerError)  
       return  
    }  
  
    // 解压文件  
    err = unzip(tempFilePath, extractPath)  
    if err != nil {  
       http.Error(w, err.Error(), http.StatusInternalServerError)  
       return  
    }  
  
    w.Write([]byte("File uploaded and extracted successfully"))  
    // 完成后删除上传文件  
    err = os.Remove(tempFilePath)  
    if err != nil {  
       return  
    }  
}  
  
func unzip(src, dest string) error {  
    r, err := zip.OpenReader(src)  
    if err != nil {  
       return err  
    }  
    defer r.Close()  
  
    for _, f := range r.File {  
       fpath := filepath.Join(dest, f.Name)  
  
       if !strings.HasPrefix(fpath, filepath.Clean(dest)+string(os.PathSeparator)) {  
          return fmt.Errorf("illegal file path: %s", fpath)  
       }  
       if f.FileInfo().IsDir() {  
          os.MkdirAll(fpath, os.ModePerm)  
          continue  
       }  
  
       if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {  
          return err  
       }  
  
       outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())  
       if err != nil {  
          return err  
       }  
  
       rc, err := f.Open()  
       if err != nil {  
          return err  
       }  
  
       _, err = io.Copy(outFile, rc)  
  
       outFile.Close()  
       rc.Close()  
  
       if err != nil {  
          return err  
       }  
    }    return nil  
}

在构建一下

GOOS=linux GOARCH=amd64 go build node-static-server-linux-amd64 ./cmd/server.go

随后拷贝到服务器用 screen 运行即可

node-static-server-linux-amd64 -port=123 -password=123 -uploadUrl=123456

本文标题:静态部署工具

永久链接:https://iceprosurface.com/2024/static-deploy-tool/

作者授权:本文由 icepro 原创编译并授权刊载发布。

版权声明:本文使用「署名-非商业性使用-相同方式共享 4.0 国际」创作共享协议,转载或使用请遵守署名协议。

查看源码: