前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Golang】使用Golang编写Hugo发布器

【Golang】使用Golang编写Hugo发布器

作者头像
DDGarfield
发布2022-06-23 19:15:21
8390
发布2022-06-23 19:15:21
举报
文章被收录于专栏:加菲的博客加菲的博客

有这么一种说法,懒人创造了世界。他们懒得走路,所以发明了汽车;懒得爬楼梯,所以发明了电梯;懒得扇扇子,所以发明了电风扇、空调。懒说明了怕麻烦,博主其实就是一个怕麻烦的人。博主的博客Garfield-加菲的博客就是通过Hugo自动生成的静态网站,首先强调一点,我喜欢Hugo,它使我能够专注于markdown的编写,其他一切事情都交给Hugo,这也符合我懒的特点。

Hugo 是 Golang 编写的静态网站生成器,速度快,易用,可配置,我也是通过golang的学习,发现了Hugo,它不用依赖一大堆东西,一个二进制文件就可以搞定,简洁。

The world’s fastest framework for building websites. Hugo 是一个非常受欢迎的、开源的静态网站生成工具。它速度快,扩展性强。

1.为什么要写一个 Hugo 发布器

事情的起因

我最初使用的是maupassant主题作为博客网站的主题,但是偶然间发现了其在移动端的适配效果不太理想,然后就想着去找一款能够完美适配移动设备的主题,最后通过配置服务器去判断用户使用的设备,不同端的设备返回给用户不同端的页面。说干就干,经过一个周末的主题筛选,与魔改(语言翻译,添加谷歌广告单元)等等。

新的问题

新的问题出现了,以前一个主题,我可以执行命令:hugo,然后把生成的包含静态文件的public文件夹的内容拷贝至服务器。现在两个主题:

  • 需要两个配置文件config.toml,使用时都得更名为这个config.toml
  • 需要两次执行hugo命令生成静态页面,并分别保存
  • 需要两次不同路径的拷贝

思来想去,**我决定编写一个hugo发布器用于我一键生成与发布的工具。**为了延续Hugogolang血统,所以继续选择go

2.包

2.1 os/exec

主要用于验证hugo命令是否存在于系统环境中

代码语言:javascript
复制
func checkHugo() error {
    //验证hugo命令
    hugpath, err := exec.LookPath("hugo")
    if err != nil {
        return err
    }
    fmt.Printf("hugo is available at %s\n", hugpath)
    fmt.Println()
    return nil
}

以及执行hugo命令

代码语言:javascript
复制
func execHugo() error {
 cmd := exec.Command("hugo")
 cmd.Dir = "."
 outinfo := bytes.Buffer{}
 //command.Stdout is interfacse
 cmd.Stdout = &outinfo
 err := cmd.Start()
 if err != nil {
  return err
 }
 if err = cmd.Wait(); err != nil {
  return err
 }
 fmt.Println(cmd.ProcessState.Pid())
 fmt.Println(cmd.ProcessState.Sys().(syscall.WaitStatus).ExitCode)
 fmt.Println(outinfo.String())

 return nil
}

2.2 os

主要用于在生成之前,对上一次生成的文件进行删除

代码语言:javascript
复制
// 删除mobile
err = os.RemoveAll("mobile")
if err != nil {
    fmt.Println(err.Error())
    log.Fatal(err)
}

// 删除public
err = os.RemoveAll("public")
if err != nil {
    fmt.Println(err.Error())
    log.Fatal(err)
}

对生成的不同端的文件夹进行重命名以及配置文件重命名

代码语言:javascript
复制
// 重命名 config-hello.toml  --config.toml
err = os.Rename("config-hello.toml", "config.toml")
if err != nil {
    fmt.Println(err.Error())
    log.Fatal(err)
}

// 执行命令
err = execHugo()
if err != nil {
    fmt.Println(err.Error())
    log.Fatal(err)
}
fmt.Println("mobile pages generated...")

// 重命名 还原 config.toml  --config-hello.toml
err = os.Rename("config.toml", "config-hello.toml")
if err != nil {
    fmt.Println(err.Error())
    log.Fatal(err)
}

// 重命名 config-maupassant.toml  --config.toml
err = os.Rename("config-maupassant.toml", "config.toml")
if err != nil {
    fmt.Println(err.Error())
    log.Fatal(err)
}

// 重命名

err = os.Rename("public", "mobile")
if err != nil {
    fmt.Println(err.Error())
    log.Fatal(err)
}

// 执行命令
err = execHugo()
if err != nil {
    fmt.Println(err.Error())
    log.Fatal(err)
}
fmt.Println("Web pages generated...")

// 重命名  还原 config.toml  --config-maupassant.toml
err = os.Rename("config.toml", "config-maupassant.toml")
if err != nil {
    fmt.Println(err.Error())
    log.Fatal(err)
}

2.3 golang.org/x/crypto/ssh

主要用于创建ssh连接

代码语言:javascript
复制
func sshConnect() (sshClient *ssh.Client, err error) {
 config := &ssh.ClientConfig{
  User: "root",
  Auth: []ssh.AuthMethod{
   ssh.Password("admin123456!"),
  },
  HostKeyCallback: ssh.InsecureIgnoreHostKey(),
  //ssh.FixedHostKey(hostKey),
 }
 sshClient, err = ssh.Dial("tcp", "47.98.184.99:22", config)
 return
}

2.4 github.com/pkg/sftp

主要在ssh会话的基础上创建sftp连接

代码语言:javascript
复制
// ssh连接
sshClient, err := sshConnect()
if err != nil {
    fmt.Println(err.Error())
    log.Fatal(err)
}
defer sshClient.Close()

// sftp
client, err := sftp.NewClient(sshClient)
if err != nil {
    fmt.Println(err.Error())
    log.Fatal(err)
}

defer client.Close()

在远程服务器上创建文件夹与文件(上传)

代码语言:javascript
复制
func upload(client *sftp.Client, localRoot string, remoteRoot string) error {
 error := filepath.Walk(localRoot, func(fp string, info os.FileInfo, err error) error {
  if info == nil {
   return nil
  }
  var temppath string
  if info.IsDir() {
   temppath = path.Join(remoteRoot, strings.ReplaceAll(fp, "\\", "/"))
   // test := info.Name()
   // fmt.Println(test)
   // hugo/public /usr/hugo/public
   // /public  /uer/public
   err = client.MkdirAll(temppath)
   if err != nil {
    log.Fatal(err)
   }
   fmt.Printf(" %s copy file to remote server finished! path:%s \n", fp, temppath)
   return nil
  }
  srcFile, err := os.Open(fp)
  if err != nil {
   log.Fatal(err)
  }
  defer srcFile.Close()
  temppath = path.Join(remoteRoot, strings.ReplaceAll(fp, "\\", "/"))
  dstFile, err := client.Create(temppath)
  if err != nil {
   log.Fatal(err)
  }
  defer dstFile.Close()
  ff, err := ioutil.ReadAll(srcFile)
  if err != nil {
   log.Fatal(err)
  }
  dstFile.Write(ff)
  fmt.Printf(" %s copy file to remote server finished! path:%s \n", fp, temppath)
  return nil
 })
 wg.Done()
 return error
}

2.5 sync

由于是两个不同端的静态文件上传,采用goroutine,使用sync包进行goroutine同步

代码语言:javascript
复制
var wg sync.WaitGroup
func main() {
    //ommit some code
    wg.Add(2)
    go upload(client, "mobile", "/usr")
    go upload(client, "public", "/usr")
    wg.Wait()
    fmt.Println("Congratulations! uploaded successfully. ")
}

3.编写命令行工具

由于上面的代码是针对我个人的特殊情况,不具有一定的通用性,属于定制化工具。使用效果如下:

这里我通过github.com/urfave/cli包编写了一个命令行工具hugop

代码语言:javascript
复制
hugop --lpath "hugo" --server "47.98.184.88:22" --username "root" --pwd "admin123456!" --rpath "/usr/wwwroot"
  • --lpath hugo项目路径(绝对路径或相对路径)
  • --server 远程服务器地址(包括 22 端口)
  • --username ssh登录用户名
  • --pwd ssh登录密码
  • --rpath 需上传的路径,所有public里面的文件都将上传至此目录

3.1 源代码

欢迎下载使用:https://gitee.com/RandyField/hugo-publish

3.2 Releases

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-03-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 加菲的博客 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.为什么要写一个 Hugo 发布器
    • 事情的起因
      • 新的问题
      • 2.包
        • 2.1 os/exec
          • 2.2 os
            • 2.3 golang.org/x/crypto/ssh
              • 2.4 github.com/pkg/sftp
                • 2.5 sync
                • 3.编写命令行工具
                  • 3.1 源代码
                    • 3.2 Releases
                    相关产品与服务
                    命令行工具
                    腾讯云命令行工具 TCCLI 是管理腾讯云资源的统一工具。使用腾讯云命令行工具,您可以快速调用腾讯云 API 来管理您的腾讯云资源。此外,您还可以基于腾讯云的命令行工具来做自动化和脚本处理,以更多样的方式进行组合和重用。
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档