hexo windows 环境下使用 rsync 发布踩坑指南

背景

最近在windows上写博客,使用hexo 发布到linux服务器时,出现异常,此文记录踩坑指南。

过程

‘rsync’ �����ڲ����ⲿ���Ҳ���ǿ����еij����������ļ�

首先出现的问题是rsync,然后一堆乱码,具体的异常日志如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
'rsync' �����ڲ����ⲿ���Ҳ���ǿ����еij���
�������ļ�
FATAL {
err: Error: spawn rsync ENOENT
at notFoundError (D:\git\personal\test_blog\node_modules\cross-spawn\lib\enoent.js:6:26)
at verifyENOENT (D:\git\personal\test_blog\node_modules\cross-spawn\lib\enoent.js:40:16)
at cp.emit (D:\git\personal\test_blog\node_modules\cross-spawn\lib\enoent.js:27:25)
at ChildProcess._handle.onexit (node:internal/child_process:291:12) {
code: 'ENOENT',
errno: 'ENOENT',
syscall: 'spawn rsync',
path: 'rsync',
spawnargs: [
'--delete',
'--ignore-errors',
'-v',
'-az',
'-e',
'ssh -p 22',
'public/',
'root@xxxxx:/path'
]
}
} Something's wrong. Maybe you can find the solution here: %s https://hexo.io/docs/troubleshooting.html
PS D:\git\personal\test_blog>

关键的错误信息乱码了。。。
第一步需要解决的就是将错误信息以正确的结果进行展示。

由于本人使用vscode,默认使用powershell进行,因此直接搜索windows powbershell 修改查看编码,得到了解决windowspowershell中文显示问号及乱码问题这篇文章,在重启后确实有用,而且将整个系统编码默认设置为utf-8编码,可以减少很多问题,因此果断采用。

具体操作如下
打开 控制面板—>区域—>管理—>更改系统区域设置
勾选:使用Unicode UTF-8提供全球语音支持

设置完成后重启电脑生效,再次尝试hexo g -d编译并部署,错误编码显示正常,得到以下错误

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
INFO  Start processing
INFO Files loaded in 2.58 s
INFO 0 files generated in 3.25 s
INFO Deploying: rsync
'rsync' is not recognized as an internal or external command,
operable program or batch file.
FATAL {
err: Error: spawn rsync ENOENT
at notFoundError (D:\git\personal\test_blog\node_modules\cross-spawn\lib\enoent.js:6:26)
at verifyENOENT (D:\git\personal\test_blog\node_modules\cross-spawn\lib\enoent.js:40:16)
at cp.emit (D:\git\personal\test_blog\node_modules\cross-spawn\lib\enoent.js:27:25)
at ChildProcess._handle.onexit (node:internal/child_process:291:12) {
code: 'ENOENT',
errno: 'ENOENT',
syscall: 'spawn rsync',
path: 'rsync',
spawnargs: [
'--delete',
'--ignore-errors',
'-v',
'-az',
'-e',
'D:\\soft\\install\\cwrsync_6.2.8_x64_free\\bin\\ssh -p 22',
'public/',
'root@www.test.com:/www/test_blog'
]
}
} Something's wrong. Maybe you can find the solution here: %s https://hexo.io/docs/troubleshooting.html

‘rsync’ is not recognized as an internal or external command

其实这个错误说的挺明显的了,rsync无法识别,于是搜索windows hexo 'rsync' is not recognized as an internal or external command,得到了使用Hexo发布博客(Windows环境),了解到windows系统默认没有rsync,因此需要下载安装。

rsync下载的官网地址为: https://www.itefix.net/cwrsync
该网址可能需要梯子,没有的就自行从网上搜索啥的第三方下载吧.

进入官网的具体下载路径为free/free software/cwrsync-rsync client for windows

之后进入下载页面,选择download下载需要的版本.

本人直接下载了最新版本,之后直接解压,配置对应的环境变量,将rysnc/bin添加到path环境变量中

最后再次尝试,你讲得到以下错误

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
INFO  Start processing
INFO Files loaded in 2.19 s
INFO 0 files generated in 3.11 s
INFO Deploying: rsync
root@www.test.com's password:
rsync: connection unexpectedly closed (0 bytes received so far) [Receiver]
rsync error: error in rsync protocol data stream (code 12) at io.c(226) [Receiver=3.1.2]
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: error in rsync protocol data stream (code 12) at io.c(231) [sender=3.2.7]
FATAL {
err: Error: rsync: connection unexpectedly closed (0 bytes received so far) [Receiver]
rsync error: error in rsync protocol data stream (code 12) at io.c(226) [Receiver=3.1.2]
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: error in rsync protocol data stream (code 12) at io.c(231) [sender=3.2.7]

at ChildProcess.<anonymous> (D:\git\personal\test_blog\node_modules\hexo-deployer-rsync\node_modules\hexo-util\lib\spawn.js:36:19)
at ChildProcess.emit (node:events:513:28)
at cp.emit (D:\git\personal\test_blog\node_modules\cross-spawn\lib\enoent.js:34:29)
at maybeClose (node:internal/child_process:1091:16)
at ChildProcess._handle.onexit (node:internal/child_process:302:5) {
code: 12
}
} Something's wrong. Maybe you can find the solution here: %s https://hexo.io/docs/troubleshooting.html

err: Error: rsync: connection unexpectedly closed (0 bytes received so far) [Receiver]

于是网上搜索 hexo windows err: Error: rsync: connection unexpectedly closed (0 bytes received so far) [Receiver] 搜到了Cygwin 使用rsync 报错解决这篇文章,经过验证后,确认是因为rsync 的ssh和系统默认的ssh冲突导致的,具体原因这里就不深入了。

验证

首先打开cmd,查看输入where rsync查看位置,显示如下

1
2
C:\Users\ivan>where rsync
D:\soft\install\cwrsync_6.2.8_x64_free\bin\rsync.exe

可以看到rsync使用的是我们之前系统环境变量设置的rsync

接着输入where ssh查看,显示如下

1
2
3
C:\Users\ivan>where ssh
C:\Windows\System32\OpenSSH\ssh.exe
D:\soft\install\cwrsync_6.2.8_x64_free\bin\ssh.exe

可以看到ssh默认有两个,系统自带的openssh下的ssh和rsync自带的ssh。

由于rsync实际要调用ssh,而在调用ssh时,系统的open ssh优先,实际调用了open ssh,没有调用到rsync自带的ssh,导致版本错配,进而发生了rsync error: error in rsync protocol data stream (code 12) at io.c(231)这个异常。

解决方案

此时解决思路有以下几种

  1. 修改环境变量,删除openssh的环境变量,这样就不会错配
  2. 在hexo deploy调用rsync命令时,将ssh路径写死。

由于openssh影响较大,不敢删除这个环境变量,因此采用了方案2.

hexo deploy的rsync是通过 node_modules/hexo-deployer-rsync来实现的,查看lib/deployer.js,发现有ssh关键字,将这个改为绝对路径即可。

将相对ssh修改为绝对ssh

1
2
3
4
5
6
7
8
9
10
11

if (args.port && args.port > 0 && args.port < 65536) {
params.splice(params.length - 2, 0, '-e');
params.splice(params.length - 2, 0, 'ssh -p ' + args.port);
}
修改为
if (args.port && args.port > 0 && args.port < 65536) {
params.splice(params.length - 2, 0, '-e');
params.splice(params.length - 2, 0, 'D:\\soft\\install\\cwrsync_6.2.8_x64_free\\bin\\ssh -p ' + args.port);
}

效果

最后再来尝试,那么你将得到以下错误

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
INFO  Start processing
INFO Files loaded in 2.58 s
INFO 0 files generated in 3.9 s
INFO Deploying: rsync
Host key verification failed.
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: error in rsync protocol data stream (code 12) at io.c(231) [sender=3.2.7]
FATAL {
err: Error: Host key verification failed.
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: error in rsync protocol data stream (code 12) at io.c(231) [sender=3.2.7]

at ChildProcess.<anonymous> (D:\git\personal\test_blog\node_modules\hexo-deployer-rsync\node_modules\hexo-util\lib\spawn.js:36:19)
at ChildProcess.emit (node:events:513:28)
at cp.emit (D:\git\personal\test_blog\node_modules\cross-spawn\lib\enoent.js:34:29)
at maybeClose (node:internal/child_process:1091:16)
at ChildProcess._handle.onexit (node:internal/child_process:302:5) {
code: 12
}
} Something's wrong. Maybe you can find the solution here: %s https://hexo.io/docs/troubleshooting.html

Error: Host key verification failed.

这个错误其实就想对简单了,host不被信任,直接进入rsync安装的bin目录下
输入

1
ssh root@xxxx

然后认证yes就可以了。

之后再次尝试,你将得到如下入错……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
INFO  Start processing
INFO Files loaded in 2.1 s
INFO 0 files generated in 3.04 s
INFO Deploying: rsync
Permission denied, please try again.
Permission denied, please try again.
root@www.test.com: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: error in rsync protocol data stream (code 12) at io.c(231) [sender=3.2.7]
FATAL {
err: Error: Permission denied, please try again.
Permission denied, please try again.
root@www.test.com: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: error in rsync protocol data stream (code 12) at io.c(231) [sender=3.2.7]

at ChildProcess.<anonymous> (D:\git\personal\test_blog\node_modules\hexo-deployer-rsync\node_modules\hexo-util\lib\spawn.js:36:19)
at ChildProcess.emit (node:events:513:28)
at cp.emit (D:\git\personal\test_blog\node_modules\cross-spawn\lib\enoent.js:34:29)
at maybeClose (node:internal/child_process:1091:16)
at ChildProcess._handle.onexit (node:internal/child_process:302:5) {
code: 12
}
} Something's wrong. Maybe you can find the solution here: %s https://hexo.io/docs/troubleshooting.html

err: Error: Permission denied, please try again.

这个异常其实就比较常见了,就是认证失败
通过查看spawn.js, deploy 最终使用的rsync命令大概长这样

1
rsync --delete --ignore-errors -v -az -e "D:\\soft\\install\\cwrsync_6.2.8_x64_free\\bin\\ssh -p 22" public/ root@www.test.com:/www/test_blog

如果直接使用这个命令,powbershell其实是会有一个输入框要你输入密码的,其实本人在hexo deploy在mac电脑上使用时也是有的,但是在windows下不知道为什么就没了。

这里就不走这条路径了,直接采用无秘钥登录,即通过ssh进行登录。

首先进入rsync_home/bin

运行ssh-keygen,熟悉sshd的小伙伴一定知道这就是个秘钥生产。

直接一路enter键盘,默认的生产文件路径为

1
2
3
~/.ssh/

C:\Users\ivan\.ssh>


id_rsa.pub的文本拷贝到服务器上的authorized_keys即可

这里不熟悉的小伙伴可以自行搜索 liunux ssh无秘钥登录。

最后再来hexo g -d

1
2
3

sent 713,559 bytes received 438,308 bytes 74,314.00 bytes/sec
total size is 58,929,007 speedu

成功部署,撒花完结?不存在的。。。。

这时候访问域名,出现了 403

403 问题解决

查看nginx日志

1
2
3

2023/04/28 11:11:42 [error] 23279#23279: *28 "/www/test_blog/index.html" is forbidden (13: Permission denied), client: 115.236.79.172, server: www.test.com, request: "GET / HTTP/1.1", host: "www.test.com"
2023/04/28 11:11:42 [error] 23279#23279: *28 open() "/www/test_blog/favicon.ico" failed (13: Permission denied), client: 115.236.79.172, server: www.test.com, request: "GET /favicon.ico HTTP/1.1", host: "www.test.com", referrer: "http://www.test.com/"

权限不足。。。
查看使用rsync同步上来的文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

drwxrwx--- 3 197609 197121 4096 Apr 27 11:21 2020
drwxrwx--- 4 197609 197121 4096 Apr 27 11:21 2021
drwxrwx--- 11 197609 197121 4096 Apr 27 11:21 2022
drwxrwx--- 5 197609 197121 4096 Apr 27 11:21 2023
drwxrwx--- 2 197609 197121 4096 Apr 27 11:21 about
drwxrwx--- 7 197609 197121 4096 Apr 27 11:21 archives
drwxrwx--- 6 197609 197121 4096 Apr 27 11:21 categories
drwxrwx--- 2 197609 197121 4096 Apr 27 11:21 css
drwxrwx--- 3 197609 197121 4096 Apr 27 11:21 images
-rwxrwx--- 1 197609 197121 304656 Apr 27 16:51 index.html
drwxrwx--- 4 197609 197121 4096 Apr 27 11:21 js
drwxrwx--- 11 197609 197121 4096 Apr 27 11:21 page
-rwxrwx--- 1 197609 197121 1239294 Apr 28 11:22 search.xml
-rwxrwx--- 1 197609 197121 16138 Apr 27 16:51 sitemap.txt
-rwxrwx--- 1 197609 197121 40537 Apr 28 10:02 sitemap.xml
drwxrwx--- 60 197609 197121 4096 Apr 27 11:21 tags

其他组的权限为0.。。。而nginx是使用nginx用户运行的,也就是说没有可读权限导致的报错。真是个悲伤的故事。

于是搜索 rsync windows liunux 权限问题,得到了cygwin rsync windows permissions,该文指出了解决的三种方式。

  • 使用rsync的”–chmod”选项来指定同步后文件的权限
  • 如果需要保留文件所有者和权限等信息,可以使用”-p”选项
  • 使用”–no-perms”选项来忽略源文件的权限信息

最终本人直接选用了第一种

在搜索hexo deploy的文档后,未发现关于–chmod的选项,因此继续采用修改js的方法。

修改deployer.js,增加 params.unshift('--chmod=ugo=rx');用于增加权限设置,需求读写。

1
2
3
4
5
6
7
8
9
10
11
修改前
if (args.verbose) params.unshift('-v');
if (args.ignore_errors) params.unshift('--ignore-errors');
if (args.delete) params.unshift('--delete');
if (args.args) params.unshift(args.args);
修改后
params.unshift('--chmod=ugo=rx');
if (args.verbose) params.unshift('-v');
if (args.ignore_errors) params.unshift('--ignore-errors');
if (args.delete) params.unshift('--delete');
if (args.args) params.unshift(args.args);

最后执行hexo g -d
成功访问,真正的完结撒花

总结

总的来说,在windows上使用hexo rsync deploy部署到服务器的踩坑点还是有点多的,有点类似俄罗斯套娃,踩了一个还有一个。

最主要的其实就是编码啊,rsync的环境变量,权限这些。

祝大家少踩坑。

参考文章

解决windowspowershell中文显示问号及乱码问题
使用Hexo发布博客(Windows环境)
Cygwin 使用rsync 报错解决