处理 Proxmox VE 每分钟生成三条日志导致泛滥成灾

这个问题一直都没有注意,一直都任务是正常的日志,即使很早之前已经发现了 journald 占用过多磁盘空间,针对 journald 这个问题还做了限制日志容量为 500MB journalctl --vacuum-size=500M 。今天发现 PVE 这个规律性每分钟产生的日志,难道不是占据了所有日志容量的大头吗?

每分钟生成三条日志:

Apr 12 19:19:00 fzpve systemd[1]: Starting Proxmox VE replication runner...
Apr 12 19:19:00 fzpve systemd[1]: pvesr.service: Succeeded.
Apr 12 19:19:00 fzpve systemd[1]: Finished Proxmox VE replication runner.
Apr 12 19:20:00 fzpve systemd[1]: Starting Proxmox VE replication runner...
Apr 12 19:20:00 fzpve systemd[1]: pvesr.service: Succeeded.
Apr 12 19:20:00 fzpve systemd[1]: Finished Proxmox VE replication runner.
Apr 12 19:21:00 fzpve systemd[1]: Starting Proxmox VE replication runner...
Apr 12 19:21:00 fzpve systemd[1]: pvesr.service: Succeeded.
Apr 12 19:21:00 fzpve systemd[1]: Finished Proxmox VE replication runner.
Apr 12 19:22:00 fzpve systemd[1]: Starting Proxmox VE replication runner...
Apr 12 19:22:00 fzpve systemd[1]: pvesr.service: Succeeded.
Apr 12 19:22:00 fzpve systemd[1]: Finished Proxmox VE replication runner.

这垃圾日志貌似没有什么用,也太多,太占用资源了吧?并且把许多可能有用的日志给淹没了,怪不得 journald 日志容量那么大,难道罪魁祸首就是这每分钟产生三条垃圾日志造成的?

ls -lh /var/log/journal/c51***b72c/
total 505M
-rw-r-----+ 1 root systemd-journal  64M Feb 24 05:33 system@00***71-c4***9d.journal~
-rw-r-----+ 1 root systemd-journal 8.0M Feb 24 06:09 system@00***5cc-27***90.journal~
-rw-r-----+ 1 root systemd-journal 128M Mar 16 16:20 system@b97***f-00**01-00**cb.journal
-rw-r-----+ 1 root systemd-journal 112M Apr  4 22:36 system@b97***f-00**da-00**47.journal
-rw-r-----+ 1 root systemd-journal 128M Feb 14 13:54 system@de***9c-00**25-00**ef.journal
-rw-r-----+ 1 root systemd-journal  48M Apr 13 01:46 system.journal
-rw-r-----+ 1 root systemd-journal 8.0M Feb 14 13:54 user-1000@070**e-00**3-00**8.journal
-rw-r-----+ 1 root systemd-journal 8.0M Mar 16 16:20 user-1000@c68**5-00**a-00**1.journal

一顿操作猛如虎之后发现这垃圾日志的是 pvesr.timer 与 pvesr.service 这两个家伙弄的。

find / -name "pvesr*"
/var/lib/systemd/deb-systemd-helper-enabled/pvesr.timer.dsh-also
/var/lib/systemd/deb-systemd-helper-enabled/timers.target.wants/pvesr.timer
find: ‘/var/lib/lxcfs/cgroup’: Input/output error
/etc/systemd/system/pvesr.timer
/etc/systemd/system/timers.target.wants/pvesr.timer
/usr/lib/systemd/system/pvesr.timer
/usr/lib/systemd/system/pvesr.service
/usr/share/man/man1/pvesr.1.gz
/usr/share/perl5/PVE/CLI/pvesr.pm
/usr/share/bash-completion/completions/pvesr
/usr/share/pve-docs/pvesr-plain.html
/usr/share/pve-docs/pvesr.1.html
/usr/bin/pvesr
/run/lock/pvesr.lck

看看 pvesr.timerpvesr.service 这两个家伙

cat /etc/systemd/system/pvesr.timer

[Unit]
Description=Proxmox VE replication runner

[Timer]
AccuracySec=1
RemainAfterElapse=no

[Timer]
OnCalendar=minutely

[Install]
WantedBy=timers.target


cat /usr/lib/systemd/system/pvesr.service

[Unit]
Description=Proxmox VE replication runner
ConditionPathExists=/usr/bin/pvesr
After=pve-cluster.service

[Service]
Type=oneshot
ExecStart=/usr/bin/pvesr run --mail 1

对于我这淘汰硬件玩 PVE 就用不上那么高级的存储复制(Storage Replication)功能,且还要多节点才能用的功能,我这普通的家庭使用严重不符合这些高级条件,但即使是使用这个功能,也不用每分钟都弄那么多日志吧!

所以必需修改 pvesr.timer 这个日志分分钟产生实在是太频繁了,改为每天!

# 使用 systemctl edit --full 修改 pvesr.timer 
# 貌似不用 systemctl daemon-reload 就能直接生效
systemctl edit --full pvesr.timer

# 由原来的 minutely 修改为 daily 
[Timer]
OnCalendar=daily

世界终于又清静了许多…

Linux 三剑客(grep | sed | awk)

Linux 三剑客是(grep,sed,awk)三者的简称,这三个命令可以和正则表达式结合在一起,功能十分强大!熟练使用这三个工具可以大大提升效率。

  • grep 擅长查找
  • sed 擅长进行取行和替换操作
  • awk 擅长进行取列操作

grep 命令

grep 命令是文本搜索命令,它可以正则表达式搜索文本,也可从一个文件中的内容作为搜索关键字。

grep 的工作方式是这样的,它在一个或多个文件中搜索字符串模板。如果模板包括空格,则必须被引用,模板后的所有字符串被看作文件名。搜索的结果被送到标准输出,不影响原文件内容。

grep 命令常用参数

grep [OPTIONS] PATTERN [FILE...]
grep [OPTIONS] [-e PATTERN]...  [-f FILE]...  [FILE...]

OPTIONS:
-e  #使用正则搜索
-i  #不区分大小写
-v  #查找不包含指定内容的行
-w  #按单词搜索
-c  #统计匹配到的次数
-n  #显示行号
-r  #逐层遍历目录查找
-A  #显示匹配行及前面多少行, 如:-A3, 则表示显示匹配行及前3行
-B  #显示匹配行及后面多少行, 如:-B3, 则表示显示匹配行及后3行
-C  #显示匹配行前后多少行,   如:-C3, 则表示显示批量行前后3行
--color  #匹配到的内容高亮显示
--include  #指定匹配的文件类型
--exclude  #过滤不需要匹配的文件类型

grep 正则表达式元字符

\			#反义字符:如"\"\""表示匹配""
[ - ]		#匹配一个范围,[0-9a-zA-Z]匹配所有数字和字母
*			#所有字符,长度可为0
+			#前面的字符出现了一次或者多次
^			#匹配行的开始 如:'^grep'匹配所有以grep开头的行。
$			#匹配行的结束 如:'grep$'匹配所有以grep结尾的行。
.			#匹配一个非换行符的字符 如:'gr.p'匹配gr后接一个任意字符,然后是p。
*			#匹配零个或多个先前字符 如:'*grep'匹配所有一个或多个空格后紧跟grep的行。
.*			#一起用代表任意字符。
[]			#匹配一个指定范围内的字符,如'[Gg]rep'匹配Grep和grep。
[^]			#匹配一个不在指定范围内的字符,如:'[^A-FH-Z]rep'匹配不包含A-R和T-Z的一个字母开头,紧跟rep的行。
\(..\)		#标记匹配字符,如'\(love\)',love被标记为1。
\<			#到匹配正则表达式的行开始,如:'\<grep'匹配包含以grep开头的单词的行。
\>			#到匹配正则表达式的行结束,如'grep\>'匹配包含以grep结尾的单词的行。
x\{m\}		#重复字符x,m次,如:'0\{5\}'匹配包含5个o的行。
x\{m,\}		#重复字符x,至少m次,如:'o\{5,\}'匹配至少有5个o的行。
x\{m,n\}	#重复字符x,至少m次,不多于n次,如:'o\{5,10\}'匹配5--10个o的行。
\w			#匹配文字和数字字符,也就是[A-Za-z0-9],如:'G\w*p'匹配以G后跟零个或多个文字或数字字符,然后是p。
\W			#\w的反置形式,匹配一个或多个非单词字符,如点号句号等。
\b			#单词锁定符,如: '\bgrep\b'只匹配grep。

grep 单引号和双引号

  • 单引号:
    • 所见即所得:即将单引号中内容原样输出,也就是单引号''是全引用。
  • 双引号:
    • 解析式输出:如果双引号的内容中有命令、变量等,会先把变量、命令解析成结果,再将结果输出。双引号""是部分引用。
  • 不加引号:
    • 不会将含有空格的字符串视为一个整体输出, 如果内容中有命令、变量等,会先把变量、命令解析出结果,然后在输出最终内容来,如果字符串中带有空格等特殊字符,则不能完整的输出,需要改加双引号,一般连续的字符串,数字,路径等可以用。

使用规则:常量用单引号''括起,而含有变量则用双引号""括起。单双可同时出现,单括住双。

grep 命令操作示例

# 匹配指定字符
# 在 test.txt 文本文件中查找匹配 sgtfz 的行
grep sgtfz test.txt

# 匹配 sgtfz 或 xy 的行,注意引号内不能有空格!
grep 'sgtfz\|xy' test.txt
# 或者
grep -E "sgtfz|xy" test.txt
# 或者
grep -E 'sgtfz|xy' test.txt
# 或者 awk 命令也可以
awk '/sgtfz|xy/'

# 匹配以 sgtfz 开头的行
grep ^sgtfz test.txt

# 在 ls 命令输出文本中查找匹配 sgtfz 的行
ls -lh | grep sgtfz

# 排除指定字符
# 在 test.txt 文本文件中查找不包含 sgtfz 的行
grep -v sgtfz test.txt

sed 命令

sed 是一种在线编辑器,它是文本处理中非常好使的工具,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用 sed 命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。Sed 主要用来自动编辑一个或多个文件,简化对文件的反复操作,编写转换程序等。

sed 命令语法

sed [options] 'command' file(s)
sed [options] -f scriptfile file(s)
sed 命令语法说明
[options]  #选项
-e  #直接在命令行模式上进行sed动作编辑,此为默认选项
-f  #将sed的动作写在一个文件内,用–f filename 执行filename内的sed动作
-i  #直接修改文件内容
-n  #只打印模式匹配的行
-r  #支持扩展表达式
-h或--help		#显示帮助
-V或--version	#显示版本信息

command  #指令

file(s)  #指定待处理的文本文件列表。

sed 常用编辑指令

a\  #在当前行下面插入文本
i\  #在当前行上面插入文本
c\  #把选定的行改为新的文本
d   #删除,删除选择的行
D   #删除模板块的第一行
s   #替换指定字符
h   #拷贝模板块的内容到内存中的缓冲区
H   #追加模板块的内容到内存中的缓冲区
g   #获得内存缓冲区的内容,并替代当前模板块中的文本
G   #获得内存缓冲区的内容,并追加到当前模板块文本的后面
l   #列表不能打印字符的清单
n   #读取下一个输入行,用下一个命令处理新的行而不是用第一个命令
N   #追加下一个输入行到模板块后面并在二者间嵌入一个新行,改变当前行号码
p   #打印模板块的行。 P(大写) 打印模板块的第一行
q   #退出Sed
b   #lable 分支到脚本中带有标记的地方,如果分支不存在则分支到脚本的末尾
r   #file 从file中读行
t   #label if分支,从最后一行开始,条件一旦满足或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾
T   #label 错误分支,从最后一行开始,一旦发生错误或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾
w   #file 写并追加模板块到file末尾
W   #file 写并追加模板块的第一行到file末尾
!   #表示后面的命令对所有没有被选定的行发生作用
=   #打印当前行号
#   #把注释扩展到下一个换行符以前

sed 替换标记指令

g   #表示将匹配到的内容进行全局替换
\1  #表示前面第一个左括号所表示的内容 ,\2表示前面第二个左括号中表示的内容,依次类推
&   #表示前面匹配到的内容

sed 正则表达式元字符

^  		#匹配行开始,如:/^sed/匹配所有以sed开头的行
$  		#匹配行结束,如:/sed$/匹配所有以sed结尾的行
.  		#匹配一个非换行符的任意字符,如:/s.d/匹配s后接一个任意字符,最后是d
*  		#匹配0个或多个字符,如:/*sed/匹配所有模板是一个或多个空格后紧跟sed的行
[]  	#匹配一个指定范围内的字符,如/[ss]ed/匹配sed和Sed
[^]  	#匹配一个不在指定范围内的字符,如:/[^A-RT-Z]ed/匹配不包含A-R和T-Z的一个字母开头,紧跟ed的行
\(..\)  #匹配子串,保存匹配的字符,如s/\(love\)able/\1rs,loveable被替换成lovers
&  		#保存搜索字符用来替换其他字符,如s/love/**&**/,love这成**love**
\<  	#匹配单词的开始,如:/\ 
\>  	#匹配单词的结束,如/love\>/匹配包含以love结尾的单词的行
x\{m\}  #重复字符x,m次,如:/0\{5\}/匹配包含5个0的行
x\{m,\}		#重复字符x,至少m次,如:/0\{5,\}/匹配至少有5个0的行
x\{m,n\}	#重复字符x,至少m次,不多于n次,如:/0\{5,10\}/匹配5~10个0的行

sed 命令操作示例

定界符
# 以上命令中字符 / 在 sed 中作为定界符使用,也可以使用任意的定界符
sed 's:test:TEXT:g' 
sed 's|test|TEXT|g' 

# 定界符出现在样式内部时,需要进行转义
sed 's/\/bin/\/usr\/local\/bin/g'
组合多个表达式
sed '表达式' | sed '表达式' 
# 等价于:  
sed '表达式; 表达式'
s 指令 – 替换操作
# 替换文本中的字符串
sed 's/book/books/' file

# -n 选项和 p 命令一起使用表示只打印那些发生替换的行
sed -n 's/test/TEST/p' file

# 直接编辑文件选项 -i ,会匹配 file 文件中每一行的第一个 book 替换为 books
sed -i 's/book/books/g' file
g 指令 – 全面替换标记
# 使用后缀 /g 标记会替换每一行中的所有匹配
sed 's/book/books/g' file

# 当需要从第 N 处匹配开始替换时,可以使用 /Ng
echo sksksksksksk | sed 's/sk/SK/2g' 
skSKSKSKSKSK

echo sksksksksksk | sed 's/sk/SK/3g'
skskSKSKSKSK  

echo sksksksksksk | sed 's/sk/SK/4g'
skskskSKSKSK 
d 指令 – 删除操作
# 删除空白行
sed '/^$/d' file

# 删除文件的第2行
sed '2d' file

# 删除文件的第2行到末尾所有行
sed '2,$d' file

# 删除文件最后一行
sed '$d' file

# 删除文件中所有开头是test的行
sed '/^test/'d file
& 指令 – 已匹配字符串标记
# 正则表达式 \w\+ 匹配每一个单词,使用 [&] 替换它,& 对应于之前所匹配到的单词
echo this is a test line | sed 's/\w\+/[&]/g'
[this] [is] [a] [test] [line] 

# 所有以 192.168.0.1 开头的行都会被替换成它自已加 localhost
sed 's/^192.168.0.1/&localhost/' file 192.168.0.1localhost
\1 指令 – 子串匹配标记
# 匹配给定样式的其中一部分
echo this is digit 7 in a number | sed 's/digit \([0-9]\)/\1/' 
this is 7 in a number

# 命令中 digit 7,被替换成了 7。样式匹配到的子串是 7,\(..\) 用于匹配子串,对于匹配到的第一个子串就标记为 \1,依此类推匹配到的第二个结果就是 \2,例如
echo aaa BBB | sed 's/\([a-z]\+\) \([A-Z]\+\)/\2 \1/' 
BBB aaa

# love 被标记为 1,所有loveable会被替换成 lovers,并打印出来
sed -n 's/\(love\)able/\1rs/p' file
, 指令 – 选定的行范围
# 所有在模板 test 和 check 所确定的范围内的行都被打印
sed -n '/test/,/check/p' file

# 打印从第 5 行开始到第一个包含以 test 开始的行之间的所有行
sed -n '5,/^test/p' file

# 对于模板 test 和 west 之间的行,每行的末尾用字符串 aaa bbb 替换
sed '/test/,/west/s/$/aaa bbb/' file
e 指令 – 多点编辑
# -e选项允许在同一行里执行多条命令
sed -e '1,5d' -e 's/test/check/' file
# 上面 sed 表达式的第一条命令删除 1 至 5 行,第二条命令用 check 替换 test 。命令的执行顺序对结果有影响。如果两个命令都是替换命令,那么第一个替换命令将影响第二个替换命令的结果。

# 和 -e 等价的命令是 --expression
sed --expression='s/test/check/' --expression='/love/d' file
r 指令 – 从文件读入
# file 里的内容被读进来,显示在与 test 匹配的行后面,如果匹配多行,则 file 的内容将显示在所有匹配行的下面
sed '/test/r file' filename
w 指令 – 写入文件
# 在 example 中所有包含 test 的行都被写入file里
sed -n '/test/w file' example
a\ 指令 – 在行下追加
将 this is a test line 追加到 以 test 开头的行后面
sed '/^test/a\this is a test line' file

# 在 test.conf 文件第 2 行之后插入 this is a test line
sed -i '2a\this is a test line' test.conf 
i\ 指令 – 在行上追加
# 将 this is a test line 追加到以test开头的行前面
sed '/^test/i\this is a test line' file

# 在 test.conf 文件第 5 行之前插入 this is a test line
sed -i '5i\this is a test line' test.conf
n 指令 – 下一个
# 如果 test 被匹配,则移动到匹配行的下一行,替换这一行的 aa,变为 bb,并打印该行,然后继续
sed '/test/{ n; s/aa/bb/; }' file 
y 指令 – 变形
把 1~10 行内所有 abcde 转变为大写,注意,正则表达式元字符不能使用这个命令
sed '1,10y/abcde/ABCDE/' file
q 指令 – 退出
# 打印完第10行后,退出 sed sed '10q' file 保持和获取:h 命令和 G 命令 在 sed 处理文件的时候,每一行都被保存在一个叫模式空间的临时缓冲区中,除非行被删除或者输出被取消,否则所有被处理的行都将打印在屏幕上。接着模式空间被清空,并存入新的一行等待处理。
sed -e '/test/h' -e '$G' file 

# 在这个例子里,匹配 test 的行被找到后,将存入模式空间,h 命令将其复制并存入一个称为保持缓存区的特殊缓冲区内。第二条语句的意思是,当到达最后一行后,G 命令取出保持缓冲区的行,然后把它放回模式空间中,且追加到现在已经存在于模式空间中的行的末尾。在这个例子中就是追加到最后一行。简单来说,任何包含 test 的行都被复制并追加到该文件的末尾。
hx 指令 – 保持和互换
# 互换模式空间和保持缓冲区的内容。也就是把包含test与check的行互换
sed -e '/test/h' -e '/check/x' file 
scriptfile 脚本指令
# sed 脚本是一个 sed 的命令清单,启动 Sed 时以 -f 选项引导脚本文件名。Sed 对于脚本中输入的命令非常挑剔,在命令的末尾不能有任何空白或文本,如果在一行中有多个命令,要用分号分隔。以 # 开头的行为注释行,且不能跨行。
sed [options] -f scriptfile file(s)
打印奇数行或偶数行
#奇数行
sed -n 'p;n' test.txt   
# 偶数行
sed -n 'n;p' test.txt  

#奇数行 
sed -n '1~2p' test.txt  
# 偶数行
sed -n '2~2p' test.txt  
打印匹配字符串的下一行
grep -A 1 SCC URFILE 
sed -n '/SCC/{n;p}' URFILE 
awk '/SCC/{getline; print}' URFILE

awk 命令

awk 是一个强大的文本分析工具,相对于 grep 的查找,sed 的编辑,awk 在其对数据分析并生成报告时,显得尤为强大。简单来说 awk 就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。

awk 有 3 个不同版本: awk、nawk 和 gawk,未作特别说明,一般指 gawk,gawk 是 AWK 的 GNU 版本。

awk 其名称得自于它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母。实际上 AWK 的确拥有自己的语言: AWK 程序设计语言 , 三位创建者已将它正式定义为“样式扫描和处理语言”。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。

参考资料来源 https://www.cnblogs.com/ggjucheng/archive/2013/01/13/2858470.html

awk 是一种编程语言,用于在 linux/unix 下对文本和数据进行处理。数据可以来自标准输入(stdin)、一个或多个文件,或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能,是 linux/unix 下的一个强大编程工具。它在命令行中使用,但更多是作为脚本来使用。 awk 有很多内建的功能,比如数组、函数等,这是它和 C 语言的相同之处,灵活性是 awk 最大的优势。

awk 命令语法

尽管操作可能会很复杂,但语法总是这样,其中 pattern 表示 AWK 在数据中查找的内容,而 action 是在找到匹配内容时所执行的一系列命令。花括号({})不需要在程序中始终出现,但它们用于根据特定的模式对一系列指令进行分组。 pattern 就是要表示的正则表达式,用斜杠括起来。

awk 语言的最基本功能是在文件或者字符串中基于指定规则浏览和抽取信息,awk 抽取信息后,才能进行其他文本操作。完整的 awk 脚本通常用来格式化文本文件中的信息。

通常,awk 是以文件的一行为处理单位的。awk 每接收文件的一行,然后执行相应的命令,来处理文本。

# awk 语法
awk '{pattern + action}' {filenames}


# 有三种方式调用awk

# 1.命令行方式
awk [-F  field-separator]  'commands'  input-file(s)
# 其中,commands 是真正awk命令,[-F域分隔符]是可选的。 input-file(s) 是待处理的文件。
# 在awk中,文件的每一行中,由域分隔符分开的每一项称为一个域。通常,在不指名-F域分隔符的情况下,默认的域分隔符是空格。

# 2.shell脚本方式
# 将所有的awk命令插入一个文件,并使awk程序可执行,然后awk命令解释器作为脚本的首行,一遍通过键入脚本名称来调用。
# 相当于shell脚本首行的:#!/bin/sh
# 可以换成:#!/bin/awk

# 3.将所有的awk命令插入一个单独文件,然后调用:
awk -f awk-script-file input-file(s)
# 其中,-f选项加载awk-script-file中的awk脚本,input-file(s)跟上面的是一样的。

awk 命令操作示例

awk 命令太复杂,这里仅列出一些常用的操作示例吧。

# 截取列元素

# 获取当前目录列表每行的第1、2、3列元素,并以空格隔开
ls -l | awk '{print $1 ,$2 ,$3 }'
# 以空字符 '' 隔开
ls -l | awk '{print $1  $2  $3 }' 
# 以特定字符+++++、******隔开
ls -l | awk '{print $1"+++++"$2"*****"$3 }'

# 获取最后一列或倒数第几列
# 获取最后一列
awk '{ print $NF }'
# 获取倒数第二列
awk '{ print $(NF-1) }' 

Nginx/Apache实现非标准(80/443)端口HTTP跳转HTTPS

80 端口是为 HTTP(HyperText Transport Protocol)即超文本传输协议开放的,此为上网冲浪使用次数最多的协议,主要用于 www(World Wide Web)即万维网传输信息的协议。443 端口即网页浏览端口,主要是用于 HTTPS 服务,是提供加密和通过安全端口传输的另一种HTTP。

80 与 443 这两为默认网页浏览端口,我们称之为标准网页服务端口吧。使用标准端口的网站服务器,在我们浏览网站的时候,只需要输入域名,不需要输入端口号即可正常访问,非常方便。

但是对于我们在家庭宽带下部署的网站,由于运营商限制了标准默认的网页服务端口 80 与 443 ,因此在家庭服务器上部署的网站服务等,都只能使用非标准端口对外提供服务。那么我们访问非标准端口下的网站只能输入完整的 <协议类型><域名>:<端口> 才能正常访问网站,非常麻烦。

例如我目前搭建的 WordPress 网站使用的端口为 8888 ,那么要访问我这个 WordPress 网站就要在浏览器上完整输入 https://sgtfz.cn 才能正常访问。如果只输入 sgtfz.top:8888 这样是无法正常访问的,Nginx 服务器会出现如下报错

400 Bad Request

The plain HTTP request was sent to HTTPS port

因为服务器监听 8888 这个端口配置了 SSL 证书,必需使用 https 协议访问。没有输入前缀协议 https:// ,默认以 http://sgtfz.top:8888 访问必然会报错而无法正常访问。

非标准端口实现 HTTP 跳转 HTTPS

这个问题老早就已经发现了,但没有找到任何有用的解决方法,所以一直搁置到如今。在一个不经意间,发现了 Nginx 的奇妙重定向,不是一般的重定向。是 error_page 497 重定向,解决了这个历史遗留问题!

error_page 497 https://$server_name:$server_port$request_uri;

目前我的 WordPress Nginx 服务器配置文件:

登录查看完整内容

如果按照正常逻辑,搜索关于 400 Bad Request 这个报错,或搜索关于 The plain HTTP request was sent to HTTPS port 这个相关的问题,是很难发现 error_page 497 玄机的。

实际上我折腾解决 Nginx 这个非标准端口 http 重定向至 https 的历史遗留问题后,想继续折腾 Apache2 也是关于这个问题的重定向,Apache2 的报错如下:

Bad Request

Your browser sent a request that this server could not understand.
Reason: You’re speaking plain HTTP to an SSL-enabled server port.
Instead use the HTTPS scheme to access this URL, please.

使用浏览器开发者工具,发现 Apache2 报错也是 400 Bad Request 。其实在我写这个文章前,我没有注意 Nginx 报错也是 400 Bad Request ,以为 Nginx 是 497 报错,在写这篇文章时重现 Nginx 报错才发现。折腾 Apache2 一直都在寻找关于 400 的报错,被 400 报错迷惑导致了最终的失败?那么是不是可以借鉴 Nginx error_page 497 这个方法来继续折腾 Apache2 呢?

好吧,时间允许的话,继续吧!问题是明天要很早去扫墓哟 @.@

2022年4月3日 2:40

还是忍不住搞定了 Apache2 的非标准端口 http 重定向至 https 的问题了!直接上配置文件示例:

<VirtualHost *:8883>
  # 开启 HTTP/2
  Protocols h2 h2c http/1.1

  DocumentRoot "/xxx/"

  # Apache 的 ServerName 貌似必需加上端口号
  ServerName  sgtfz.top:8883

  # 日志
  ErrorLog ${APACHE_LOG_DIR}/error.log
  CustomLog ${APACHE_LOG_DIR}/access.log combined

  # Enable/Disable SSL for this virtual host.
  SSLEngine on

  # 证书公钥配置
  SSLCertificateFile /etc/apache2/cert/sgtfztop_cert.pem
  # 证书私钥配置
  SSLCertificateKeyFile /etc/apache2/cert/sgtfztop_key.pem
  # 证书链配置
  SSLCertificateChainFile /etc/apache2/cert/sgtfztop_chain.pem
  ......
  # 重定向 400 错误 到 https://sgtfz.top:8883/ 
  ErrorDocument 400 https://sgtfz.top:8883/
</VirtualHost>

精准针对 400 错误 重定向 https://sgtfz.top:8883/

如下 2 种方法都行:

  • ErrorDocument 400 https://sgtfz.top:8883/
  • ErrorDocument 400 "https://%{SERVER_NAME}:%{SERVER_PORT}/"

简单粗暴。但 Apache 的这种方式重定向,有一个致命的缺点:

  • 不管你访问任何目录或文件都只能重定向到指定页面 https://sgtfz.top:8883/
    • 例如访问 sgtfz.top:8883/others/ 将会重定向到 https://sgtfz.top:8883/

因此,如果非标准端口 HTTP 跳转 HTTPS ,Nginx 才有最完美的解决方案。

存储与备份

数据安全这个问题太过深奥、复杂,对于我们自己的个人数据,仅能做到自己能力范围内的所谓安全吧。那么我们就记录一下,目前能力范围内,能够做到的个人数据所谓安全的方案。

存储数据的类型

目前我主要存储的数据类型,且个人认为重要的有大概如下:

  • 资料类,个人工作办公文档表格等图文类型文件
  • 音视频类,个人或家庭照片、视频、音频等
  • 软件类的,系统iso,办公软件,图片或图形处理软件等个人收藏的软件。
  • 可能还有其它杂七杂八的等等

实际上个人的重要数据不是非常的多,目前有 1TB 的存储已经足有存储这些重要的东西了。各种乱七八糟的娱乐类的音视频文件,随时可以网上下载的东西,都不列为我认为的重要的数据。

如何存储这些数据

我们如何整理存储这些数据,这个也是太过于深奥、复杂,每个不同的环境、条件等等因素不同都千差万别。

目前我的存储方案

配置一台 All in One 电脑,即没有特殊情况,从来不关机的电脑做服务器硬件基础。Proxmox VE (PVE)作为底层系统(母鸡),根据各种需求来孵化各种小鸡。(所有服务器系统及软件都用官方,杜绝第三方系统及软件)

目前 Proxmox VE 孵化的小鸡

  • OpenWrt 负责家庭网关
  • WordPress 负责内容管理系统
  • NextCloud 负责文件管理系统
  • Windows 负责各种辅助

OpenWrt 是开源的路由软件,用着放心,起码比目前市面上各种乱七八糟的华而不实的各种风险路由用得踏实。

WordPress 个人觉得负责内容管理非常完美,在有时间的时候,可以将重要的内容由 WordPress 为我们存储、发布、呈现、分享…

NextCloud 私有云,负责存储文档资料、音视频、各种软件、文件等等,这就是云存储,不过是私人的云存储。个人认为是靠谱的存储,起码比目前任何网络第三方存储靠谱。但门槛高!要自己搭建并完善这个私有云。NextCloud 给我们实现了一个同步盘,能有效避免因硬件损坏而丢失数据,还有各种版本控制,文件修改记录,且还能共享连接等等,更多关于 NextCloud 的优缺点这里不再详细介绍了。

Windows 这个不用介绍了,我相信在我生活的周边环境上,用苹果电脑的人应该非常非常少,所以都是用 Windows 的系统。这个 Windows 是运行在 Proxmox VE 小鸡上的呀,主要负责匹配 UPS 软件,安装各种下载软件(迅雷、百度云等等)作为辅助的存在。

如何备份数据

Proxmox VE 作为底层系统(母鸡)的备份,个人认为备份各种配置文件即可。

NextCloud 私有云,已经为我们实现了许多关于文件存储方面的数据安全了,因此我们只需要备份 NextCloud 服务器小鸡,就能进一步加固了我们的数据安全。

WordPress 内容管理系统,我们一样是备份 WordPress 服务器小鸡即可。

备份 Proxmox VE 母鸡

目前我发现一个备份 Proxmox VE 的脚本 prox_config_backup.sh ,非常好用。

该脚本原作者分享的 GitHub 网址 GitHub – DerDanilo/proxmox-stuff: prox_config_backup

如果手动运行脚本,我们需要先设置备份目录环境变量 export BACK_DIR="/path/to/backup/directory" 定义自己的备份目录!

如果计划任务运行脚本,我们就修改脚本默认保存备份的目录为自己需要定义的目录 _bdir=${BACK_DIR:-/mnt/backups/proxmox}

prox_config_backup.sh 脚本完整内容如下:

#!/bin/bash
# Version	      0.2.2 - BETA ! !
# Date		      02.20.2020
# Author 	      DerDanilo 
# Contributors    aboutte, xmirakulix, bootsie123

# set vars

# always exit on error
set -e

# permanent backups directory
# default value can be overridden by setting environment variable before running prox_config_backup.sh
# example: export BACK_DIR="/mnt/pve/media/backup"
# or
# example: BACK_DIR="." ./prox_config_backup.sh
_bdir=${BACK_DIR:-/mnt/backups/proxmox}

# number of backups to keep before overriding the oldest one
MAX_BACKUPS=5

# temporary storage directory
_tdir=${TMP_DIR:-/var/tmp}

_tdir=$(mktemp -d $_tdir/proxmox-XXXXXXXX)

function clean_up {
    echo "Cleaning up"
    rm -rf $_tdir
}

# register the cleanup function to be called on the EXIT signal
trap clean_up EXIT

# Don't change if not required
_now=$(date +%Y-%m-%d.%H.%M.%S)
_HOSTNAME=$(hostname -f)
_filename1="$_tdir/proxmoxetc.$_now.tar"
_filename2="$_tdir/proxmoxpve.$_now.tar"
_filename3="$_tdir/proxmoxroot.$_now.tar"
_filename4="$_tdir/proxmoxcron.$_now.tar"
_filename5="$_tdir/proxmoxvbios.$_now.tar"
_filename6="$_tdir/proxmoxpackages.$_now.list"
_filename7="$_tdir/proxmoxreport.$_now.txt"
_filename8="$_tdir/proxmoxlocalbin.$_now.tar"
_filename_final="$_tdir/proxmox_backup_"$_HOSTNAME"_"$_now".tar.gz"

##########

function description {
    clear
    cat <<EOF

        Proxmox Server Config Backup
        Hostname: "$_HOSTNAME"
        Timestamp: "$_now"

        Files to be saved:
        "/etc/*, /var/lib/pve-cluster/*, /root/*, /var/spool/cron/*, /usr/share/kvm/*.vbios"

        Backup target:
        "$_bdir"
        -----------------------------------------------------------------

        This script is supposed to backup your node config and not VM
        or LXC container data. To backup your instances please use the
        built in backup feature or a backup solution that runs within
        your instances.

        For questions or suggestions please contact me at
        https://github.com/DerDanilo/proxmox-stuff
        -----------------------------------------------------------------

        Hit return to proceed or CTRL-C to abort.

EOF
    read dummy
    clear
}

function are-we-root-abort-if-not {
    if [[ ${EUID} -ne 0 ]] ; then
      echo "Aborting because you are not root" ; exit 1
    fi
}

function check-num-backups {
    if [[ $(ls ${_bdir}/*${_HOSTNAME}*.tar.gz -l | grep ^- | wc -l) -ge $MAX_BACKUPS ]]; then
      local oldbackup="$(basename $(ls ${_bdir}/*${_HOSTNAME}*.tar.gz -t | tail -1))"
      echo "${_bdir}/${oldbackup}"
      rm "${_bdir}/${oldbackup}"
    fi
}

function copyfilesystem {
    echo "Tar files"
    # copy key system files
    tar --warning='no-file-ignored' -cvPf "$_filename1" /etc/.
    tar --warning='no-file-ignored' -cvPf "$_filename2" /var/lib/pve-cluster/.
    tar --warning='no-file-ignored' -cvPf "$_filename3" /root/.
    tar --warning='no-file-ignored' -cvPf "$_filename4" /var/spool/cron/.
    
    if [ "$(ls -A /usr/local/bin 2>/dev/null)" ]; then tar --warning='no-file-ignored' -cvPf "$_filename8" /usr/local/bin/.; fi
        
    if [ "$(ls /usr/share/kvm/*.vbios 2>/dev/null)" != "" ] ; then
	echo backing up custom video bios...
	tar --warning='no-file-ignored' -cvPf "$_filename5" /usr/share/kvm/*.vbios
    fi
    # copy installed packages list
    echo "Copying installed packages list from APT"
    apt-mark showmanual | tee "$_filename6"
    # copy pvereport output
    echo "Copying pvereport output"
    pvereport | tee "$_filename7"
}

function compressandarchive {
    echo "Compressing files"
    # archive the copied system files
    tar -cvzPf "$_filename_final" $_tdir/*.{tar,list,txt}

    # copy config archive to backup folder
    # this may be replaced by scp command to place in remote location
    cp $_filename_final $_bdir/
}

function stopservices {
    # stop host services
    for i in pve-cluster pvedaemon vz qemu-server; do systemctl stop $i ; done
    # give them a moment to finish
    sleep 10s
}

function startservices {
    # restart services
    for i in qemu-server vz pvedaemon pve-cluster; do systemctl start $i ; done
    # Make sure that all VMs + LXC containers are running
    qm startall
}

##########


description
are-we-root-abort-if-not
check-num-backups

# We don't need to stop services, but you can do that if you wish
#stopservices

copyfilesystem

# We don't need to start services if we did not stop them
#startservices

compressandarchive

恢复方法(从作者那搬过来的教程,防止GitHub打不开,懒得机器翻译了,)

On my machine, you end up with a GZipped file of about 1-5 MB with a name like “proxmox_backup_proxmoxhostname_2017-12-02.15.48.10.tar.gz”.
Depending upon how you schedule it and the size of your server, that could eventually become a space issue so don’t
forget to set up some kind of archive maintenance.

To restore, move the file back to proxmox with cp, scp, webmin, a thumb drive, whatever.
I place it back into the /var/tmp directory from where it came.

# Unpack the original backup
tar -zxvf proxmox_backup_proxmoxhostname_2017-12-02.15.48.10.tar.gz
# unpack the tared contents
tar -xvf proxmoxpve.2017-12-02.15.48.10.tar
tar -xvf proxmoxetc.2017-12-02.15.48.10.tar
tar -xvf proxmoxroot.2017-12-02.15.48.10.tar

# If the services are running, stop them:
for i in pve-cluster pvedaemon vz qemu-server; do systemctl stop $i ; done

# Copy the old content to the original directory:
cp -avr /var/tmp/var/tmp/etc /etc
cp -avr /var/tmp/var/tmp/var /var
cp -avr /var/tmp/var/tmp/root /root

# And, finally, restart services:
for i in qemu-server vz pvedaemon pve-cluster; do systemctl start $i ; done

If nothing goes wrong, and you have separately restored the VM images using the default Proxmox process.
You should be back where you started. But let’s hope it never comes to that.

实际我们可以根据自己的需求,手动恢复需要的配置文件即可。

备份小鸡

OpenWrt 与 Windows 是分别运行在独立的虚拟机上,WordPress 与 NextCloud 是分别运行在独立的 LXC 容器上。

OpenWrt 我们的路由器,一般能够正常工作基本就 OK 。除了平时的日常更新,还有配置一些端口转发,DDNS,DHCP等,这些都是随机应变的配置。我觉得只要配置好基础的服务类软件然后做一个备份即可,剩下的各种日常配置修改,就根据日后的需求再做完善,不必列入计划任务去备份。

Windows 也是一样,基础配置好做一个备份即可。

备份 WordPress

WordPress 原来是跟 NextCloud 同在一个 LXC 上的,后来才独立出来运行在一个独立的 LXC 容器上,是避免受到 NextCloud 的影响,效果会更好一点。

运行 WordPress 的 LXC 容器配置是这样的

  • 一核心,1GB 内存
  • 根磁盘 rootfs ,存放在 LVM 盘 pve 组,120GB 固态硬盘上
  • 挂载点 mp0,存放在 LVM 盘 vghddst 组,机械硬盘上

整个 WordPress 运行在根磁盘 rootfs 上

挂载点 mp0 是用于备份的:

  • 计划任务执行每天备份存放数据库
  • 计划任务执行每天 Rsync 同步 wp-content 目录
为 WordPress 小鸡拍快照

拍照可以保存历史,必要时候可以回到过去!

假如网站被勒索病毒了,Rsync 或 Lsyncd 同步还是无法规避这种风险,那么快照是不是就完美的应对这种风险了呢!

母鸡每天为小鸡拍一张快照,在拍快照的同时检查并保留最新的 3 张快照,删除超过 3 天的旧照。(请注意,以下拍照方案在测试阶段,这个方案从设计到测试耗了我2天哟)

#!/bin/bash

######## 必需检查或填写 VMID 与 str 参数 ########

# 需要做快照的 VM-ID 或 LXC-ID
VMID=102

# 快照名前缀
str=test

# 保留快照的数量 = 设置值(vol) - 1
vol=4

########### 以上为必需检查或填写的参数 ###########

# 年月日时分
DATE=`date +%Y%m%d%H%M`

############### 创建快照 ###############
/usr/sbin/pct snapshot $VMID "$str"_"$DATE"

# 稍微休息10秒
sleep 10

############### 保留快照与删除快照 ################

# 变量-查看快照
lssnap="/usr/sbin/pct listsnapshot ${VMID}"

# 变量-删除快照
delsnap='\/usr\/sbin\/pct delsnapshot '"$VMID"' '"$str"''

# 从列出的快照列表,排除需保留的新快照,将设置值(vol)(包括第vol个)之后的旧快照列表字符串转化为命令行
cmd=`$lssnap | grep "$str" | sort -n -r | awk '{print $2}' | sed -n "$vol",'$p' | sed '/^'"$str"'/a\sleep 8' | sed 's/.$/&\;/' | sed 's/'"$str"'/'"$delsnap"'/g'`

# 判断字符串不为空
if [ -n "$cmd" ]; then
    # 执行命令
    eval $cmd
else
    echo "没有任何快照被删除"
fi
# 退出
exit

特别注意的是

因为根磁盘 rootfs 与挂载点 mp0 两个虚拟磁盘,拍照就会分别为 2 个磁盘拍照,假如某天其中一个磁盘损坏,那么我们就无法通过正常的 pct 命令或 Web 管理页面上还原快照!如果需要单独还原未损坏的磁盘的快照,可以通过编辑该 LXC 小鸡配置文件(必需先备份该配置文件) /etc/pve/nodes/fzpve/lxc/102.conf 将损坏的挂载点配置删除,就能通过正常的 pct 命令或 Web 管理页面还原快照了。还原快照之后,必需注意检查并完善还原之后的配置文件 /etc/pve/nodes/fzpve/lxc/102.conf 最后才启动 LXC

其实备份数据库已经可以回到过去,但是 Rsync 我们设置的是镜像同步模式,不是增量模式,因为增量模式我目前还没有更详细的了解,或者说增量模式不适合我使用。

备份 NextCloud

运行 WordPress 的 LXC 容器配置是这样的

  • 二核心,4GB 内存
  • 根磁盘 rootfs ,存放在 LVM 盘 pve 组,120GB 固态硬盘上
  • 挂载点 mp0 ,存放在 LVM 盘 vgssd 组,1TB 固态硬盘上
  • 挂载点 mp1 ,存放在 LVM 盘 vghddst 组,机械硬盘上

rootfs 运行 Apache + MariaDB + PHP 环境

挂载点 mp0 用于存放 NextCloud 网站目录

挂载点 mp1 用于备份

  • 计划任务执行每天备份存放数据库
  • Lsyncd 实时同步 NextCloud 的 data 目录
  • 计划任务执行每天 Rsync 同步 NextCloud 目录
为 NextCloud 小鸡拍快照

可以完全参照 WordPress 的拍照方案,但需要注意的是,我只是想拍挂载点 mp1 一个磁盘的快照,这样就必需修改一下拍照的配置,这个以后慢慢完善后,在补充上来。

2022年3月27日

NextCloud 的存储方案做了一些细微的调整:

  • 挂载点 mp0 ,1TB SSD 主要负责存放重要的个人数据(目前还没200GB)
  • 挂载点 mp1,1.5TB HDD 主要负责 Rsync 同步 mp0 的重要数据
    • 在 mp1 上建立 NextCloud External Storage(外部存储)
    • 个人 Windows 电脑 NextCloud 桌面端同步包括 External Storage 的数据。
      • External Storage 目录配置为 Apache AutoIndex 作为静态资源下载站。
      • 数据库备份及各种日志(快照、Rsync、等日志)推送到 External Storage 子目录。
        • 子目录配置 Apache AuthConfig 密码登录授权访问

调整 NextCloud 存储原因是由于有一大部分常用的软件及系统文件,平时经常需要访问与下载,NextCloud 共享下载目录真的挺耗资源的!所以干脆将这部分从 NextCloud 核心存储转移到外部存储(External Storage),这样既腾出了本来就局促的SSD存储空间,又能将这部分静态资源由 Apache AutoIndex 负责提供下载。

Apache AutoIndex 静态下载 对比 NextCloud 共享下载,既减轻了服务器负载的同时又提高了响应速度,一举两得!

实际上还有很大一部分的不舍得删除的音视频资源,也转移到了 External Storage !这样一顿操作猛如虎之后,1TB 的 SSD 仅用了180GB左右。存储在 SSD 的重要数据共有三份镜像数据存储在不同的磁盘上,安全等级最高。存储在 External Storage 外部存储上的普通数据共有二份镜像数据存储在不同的磁盘上,安全等级一般,但对我而言也够了。

母鸡配置备份与快照方案

通过几天的摸爬打滚,母鸡为小鸡们拍照脚本如下:

登录查看完整内容

解决 Nginx 导致 WordPress 无法上传超过 1MB 的文件

我在家庭服务器上的 WordPress 原本是与 NextCloud 运行在同一个 LXC 容器上的,由于 NextCloud 这个耗资源大户确实是耗资源,且不是正常耗资源的那种,而是专门吃 buff/cache ,即使给他 8GB 的内存,都能被 buff/cache 吃完哟!详细不在这里细数 NextCloud 的缺点了,有关 NextCloud 的牢骚详细在这 https://sgtfz.cn/members/cyf/activity/2739/,反正我昨天已经完美的把 WordPress 独立运行在一台新建的 1核心 1GB内存 的虚拟机上了。

问题来了,WordPress 在 Nginx + PHP + MariaDB 这个新环境上有点水土不服呀。

实际上这个问题本就不应该出现,出现这个问题的原因是由于我们不熟悉配置 Nginx 环境的服务器。但如果他能正常的工作,没有遇到问题,又怎么可能花时间去进一步了解 Nginx 呢!我在阿里云公网环境部署的 Nginx + PHP + MariaDB 就没有遇到此问题,因为没有上传超过 1MB 以上的图片,文件更是没有上传过,因为阿里云公网上的那个宽带,那个费用,分分钟不想搞。要不是新用户优惠,那续费价格实在是吓到我了,真就不搞了!真没意思。哪里有无限的新用户呢,所以不可持续的,还是决定放弃吧…

还是家里好啊!我这台家庭服务器实在多了呀,有电,有宽带(动态公网IP),他就可以咯,所以才有继续折腾的意义与动力…

WordPress 无法上传媒体文件的报错并不直观

这个问题如果不细心的去稍微的品一下,分分钟被报错的提示所误导,导致找不到问题根源从而无法解决问题。

WordPress 无法上传媒体文件报错如下图所示:

请注意下图。最大上传文件大小:512MB

WordPress 上传图片或文件报错

因此我们应该不会再怀疑报错是由于限制了上传大小所导致的啦!

上图示例包括上传图片的报错与上传文件的报错。

上传图片报错

上传图片的时候,有些能正常,有些会报错。

上传图片出现报错的都是这样的报错:

  • 服务器无法处理图像。如果服务器繁忙或没有足够的资源来完成任务,就会发生这种情况。上传较小的图像可能会有所帮助。建议的最大尺寸为 2560 像素。

上传文件报错

上传文件的时候,除了某些不支持的文件类型会报错:抱歉,您无权上传此文件类型。

在支持的文件类型上,有些能正常,有些会报错。

上传文件出现报错的都是这样的报错:

  • 从服务器收到预料之外的响应。此文件可能已被成功上传。请检查媒体库或刷新本页。

解决 WordPress 无法上传媒体文件的报错

根据 WordPress 媒体库无法上传文件的报错提示,围绕着这方面的问题一直在寻找解决问题的答案,正是由于 WordPress 的这个报错提示指引了我走进了深渊!

在深渊里挣扎的同时真相已浮出了水面

实际上还是由于限制了上传的大小,导致的问题!

  • 明明图片分辨率超过 2560 像素,却还是有可以正常上传的!
  • 明明图片没有超过 2560 像素的,却还是无法正常上传的!

原来只要文件超过 1MB 的都会出现报错,从而无法正常上传到媒体库!

但是为什么媒体库这里显示:

最大上传文件大小:512MB

因为我在配置服务器的 php.ini 已经配置了可以上传单个文件不超 512MB

post_max_size = 512M
upload_max_filesize = 512M

那么目前除了 Nginx 还能有谁在限制呢!马上查看 Nginx 的日志:

2022/03/14 00:25:25 [error] 4116#4116: *31 client intended to send too large body: 1406102 bytes, client: 192.168.33.1, server: sgtfz.top, request: "POST /wp-admin/async-upload.php HTTP/2.0", host: "sgtfz.top:8888", referrer: "https://sgtfz.cn/wp-admin/upload.php"
2022/03/14 00:26:44 [error] 4116#4116: *31 client intended to send too large body: 1310747 bytes, client: 192.168.33.1, server: sgtfz.top, request: "POST /wp-admin/async-upload.php HTTP/2.0", host: "sgtfz.top:8888", referrer: "https://sgtfz.cn/wp-admin/upload.php"
2022/03/14 00:31:22 [error] 4116#4116: *31 client intended to send too large body: 113168773 bytes, client: 192.168.33.1, server: sgtfz.top, request: "POST /wp-admin/async-upload.php HTTP/2.0", host: "sgtfz.top:8888", referrer: "https://sgtfz.cn/wp-admin/upload.php"

真相大白!

配置 Nginx 默认上传限制

经了解 Nginx 默认上传文件限制为 1MB ,超过 1MB 的文件无法上传成功。所以我们只需修改 Nginx 的配置文件,增加 client_max_body_size 512M; 此参数,就能解决目前所遇到的问题。

client_max_body_size 1024M; 此参数应该写在哪里,众说纷纭!

有说写在 http { 写在这里 }

有说写在 server { 写在这里 }

有说写在 location / { 写在这里 }

反正我写在这里:

# 我已配置好的 WordPress 网站配置文件
vi /etc/nginx/sites-available/wordpress

server {
    ......
    listen *:443 ssl http2;
    listen [::]:443 ssl http2;

    server_name  sgtfz.top;
    # 写在这里呀!!!!!!!
    client_max_body_size 512M;
    root /sites-data/wordpress/;
    index index.php;
    ......
}

保存配置后,重启 Nginx ,这个问题完美解决啦!

WordPress 媒体库默认裁剪限制 2560 像素

我们解决了 Nginx 的默认限制后,WordPress 可以正常上传不超 512MB 的文件啦,但是上传了一张 4000×4000 像素的图片发现,媒体库显示为 2560×2560 像素分辨率!这不是我要的结果呀!

一波还未平息,一波又来侵袭,茫茫人海,狂风暴雨 …

解决方法:

在子主题的 functions.php 增加一行参数

add_filter( 'big_image_size_threshold', '__return_false' );

终于完美了。

Led Control System V3 报错异常:索引超出了数组界限。

LED 广告屏幕管理工具 Led Control System v3.56 绿色版,在 Windows10 企业版 LTSC 2019 无法启动,然而在 Windows10 企业版 21H2 上却能正常运行!奇了个怪了!!

解决方法:系统更新到最新

折腾过程记录如下:

双击运行 StarLedV3.exe 如下图所示:

Index was outside the bounds of the array

然后我们进入 LedControlSystme 目录双击 LedControlSystem.exe

提示需要安装 .NET Framework 3.5(包含 .NET 2.0 和 3.0)

提示安装 .NET Framework 3.5

安装完成 .NET Framework 3.5(包含 .NET 2.0 和 3.0)并重启电脑后

再次运行 LedControlSystem.exe ,依旧报错无法启动,提示 索引超出了数组界限。

索引超出了数组界限

尝试了许多的方法,安装 VC++ 各个版本,安装 dx9 等,各种尝试都无法解决问题!

最后,安装系统更新,解决了问题,实在是折腾人呀!

更新记录:

首次检查更新了如下补丁,提示重启电脑,然后重启

更新的记录如下:

初次更新了 1809 的 02 累积更新 KB5010351

测试 LedControlSystem.exe 依旧报错无法启动。

然后再次检查更新,怎么还在安装 1809 的 02 累积更新 KB5010351 呢?

这次安装时间有点长

还在继续更新 KB5010351

更新完成再次重启电脑。

之后查看更新记录:

1809 的 02 累积更新 KB5010351(2) 这有点神奇,装了2个?哈哈。

累积更新 KB5010351(2)

再次测试 LedControlSystem.exe,软件居然正常启动啦!太妙啦!!

NextCloud 集成 Collabora Online 在线办公

我的 NextCloud 本来集成的是 Onlyoffice 在线办公的,可能由于升级了 NextCloud22.2.3 或升级了 Onlyoffice6.4.2 之后,Onlyoffice 在线办公出了一些致命的 Bug 导致不得不放弃 Onlyoffice。

Onlyoffice 致命的 Bug

这个 bug 要把他描述清楚都是一件非常困难的事情

举例说明:

现在是 9点15分,使用 PC 端 MSoffice 的 Excel 或 Word(其他文档未测试)新建文档,名称为:test.docx 或 test.xlsx ,内容为:1234567,保存文件后 NextCloud 同步到云端。

5分钟后(即9点20分),我们再次使用 PC 端或手机端 MSoffice 的 Excel 或 Word 编辑该文档,修改内容为:1234567abc ,然后再次保存。

  • 此时 NextCloud 会自动创建一个 5 分钟前的版本文件(即 9点15分 保存的内容:1234567)。

10分钟后(即9点30分),无论是手机端打开该文档或 PC 端打开该文档,都能正常的显示最终修改后的内容(内容为:1234567abc),一切完美正常。

  • 此时使用在线 OnlyOffice 打开该文件,也能正常显示最终修改后的完整内容(即 9点30分 保存的内容为:1234567abc)。

特别注意!现在时间是 9点30分,OnlyOffice 此时打开浏览文件内容,没有编辑文件。

5分钟后(即 9点35分),我们再次使用 PC 端或手机端 MSoffice 的 Excel 或 Word 编辑该文档,修改内容为:1234567abcEFGH,然后再次保存。

  • 此时 NextCloud 会自动再次创建一个 5分钟前 的版本文件(即 9点30分 保存的内容:1234567abc)。
    • 现在如果再次使用在线 OnlyOffice 打开该文档,问题就出现了!
    • OnlyOffice 只能看到在 9点30分 那一刻他打开的内容(内容为:1234567abc)
    • 之后无论是使用 PC 端或手机端的 MSoffice 软件增加或删减内容,OnlyOffice 一直只能看到 9点30分 那一刻的内容(即 9点30分 保存的内容为:1234567abc)
    • 现在无论是使用 PC 端或手机端的 MSoffice 打开该 test 文档,内容一切正常的哟!(即 9点35分 保存的内容为:1234567abcEFGH)

5分钟后(即 9点40分),如果此时我们没有发现这个严重的问题,继续使用在线 OnlyOffice 打开该文档,(即 9点30分 保存的内容:1234567abc)然后编辑增加内容为:12345abcd8899。

  • 此时 NextCloud 会自动再次创建一个 5 分钟前的版本文件(即 9点35分 保存的内容为:1234567abcEFGH)。
  • 此时 test 文档内容为:12345abcd8899
  • 此时无论是 PC 端或手机端 MSoffice 再次打开浏览 test 文档所看到的内容为:12345abcd8899
  • 此时不知情的情况下(即 9点35分 保存的内容为:1234567abcEFGH)丢失得神不知鬼不觉!

我们需要正常的内容为:1234567abcEFGH8899

被 OnlyOffice 这个致命的 bug 造成丢失的 EFGH 内容,到底有多严重,这就可大可小了!!

所以我愤怒的禁用了 OnlyOffice

使用 docker 部署 Collabora Online 服务器

因为使用 docker 部署实在是太舒服了,几个步骤就能完成。

安装 Collabora Online 服务器

注意域名匹配自己的 NextCloud 服务器的域名 cloud\\.sgtfz\\.top ,服务器将监听localhost:9980 ,自定义的字体可以直接映射本地字体到容器 --volume

# 获取Collabora Online docker 镜像
docker pull collabora/code

# 启动 Collabora Online 容器,映射本地字体文件夹到容器里 --volume
docker run -t -d -p 127.0.0.1:9980:9980 -e 'domain=cloud\\.sgtfz\\.top' --restart always --cap-add MKNOD --volume "/usr/local/share/fonts/truetype/:/opt/collaboraoffice/share/fonts/truetype/local/:ro" collabora/code

配置 Apache 反向代理

Ubuntu 或 Debian 上配置 Apache 反代理的方法

a2enmod proxy
a2enmod proxy_wstunnel
a2enmod proxy_http

创建 Apache 配置文件

  • collaboraonline.conf
登录查看完整内容

升级 Collabora Online docker 容器

下面我们记录如何升级 Collabora Online docker 容器

# 获取新的 docker 镜像
docker pull collabora/code

root@debian:~# docker pull collabora/code
Using default tag: latest
latest: Pulling from collabora/code
2f94e549220a: Pull complete
8c2d3cacc76b: Pull complete
9e459d1a469c: Pull complete
075eed41d5be: Pull complete
960b5a458fb1: Pull complete
Digest: sha256:9ca5c0176c40ecc0eee705653f4ef380e82e69dfc6c61a377a31442797945bd8
Status: Downloaded newer image for collabora/code:latest
docker.io/collabora/code:latest


# 列出 docker 容器
docker ps

root@debian:~# docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED       STATUS          PORTS                      NAMES
1c88224348c8   2aa80bf820c9   "/start-collabora-on…"   6 weeks ago   Up 34 minutes   127.0.0.1:9980->9980/tcp   elegant_galileo


# 停止 Collabora Online 容器
docker stop 1c88224348c8

# 删除 Collabora Online 容器
docker rm 1c88224348c8

# 启动新的 Collabora Online 容器,映射本地字体文件夹到容器里
docker run -t -d -p 127.0.0.1:9980:9980 -e 'domain=cloud\\.sgtfz\\.top' --restart always --cap-add MKNOD --volume "/usr/local/share/fonts/truetype/:/opt/collaboraoffice/share/fonts/truetype/local/:ro" collabora/code


# 查看已保存的 docker 镜像
docker images

root@debian:~# docker images
REPOSITORY       TAG       IMAGE ID       CREATED        SIZE
collabora/code   latest    a5b0b6370643   5 days ago     1.46GB
collabora/code   <none>    2aa80bf820c9   6 weeks ago    1.46GB
hello-world      latest    feb5d9fea6a5   3 months ago   13.3kB

# 删除旧版本的 docker 镜像
docker rmi 2aa80bf820c9

完美的从 Only office 转到 Collabora office ,实际上 Only office 的界面和操作体检都比较好,可惜 Bug 太致命。截止到今天 2022年1月份,我测试了最新发布的 Onlyoffice 7 依旧没有解决这个致命的 Bug 。我已经对 Onlyoffice 失去了耐心,决定继续一直使用 Collabora office 直到下一个 Onlyoffice 8 再看看吧 …

Collabora Online 存在的问题及解决

Office 相关文件不能正常显示 ico图标

NextCloud 动态页无法显示 office 文档相关的 ico 图标(包括 .xlsx,.docx文件),但有小部分一些又能正常显示 office 相关的 ico 图标。

解决方法:

问题出在 NextCloud 应用程序 Collabora Online 连接器,找到 Collabora Online 应用程序目录的 Office.php 大概如下路径目录

/www/nextcloud/apps/richdocuments/lib/Preview/Office.php

注释以下三行代码,保存即可。

public function isAvailable(\OCP\Files\FileInfo $file) {
    // if (isset($this->capabilitites['collabora']['convert-to']['available'])) {
    //     return (bool)$this->capabilitites['collabora']['convert-to']['available'];
    // }
return false;
}

这样修改,在应用程序更新后会失效,但我没有找到更好的解决方法。如果应用程序更新,那么此问题应该也会得到解决吧,假如没有解决,那么就继续找该文件修改咯。

TCL D48A620U 智能系统启动中…卡住了

什么智能系统?一个安卓魔改系统,然后加入定制的各种广告软件和各种引导加入会员与引导付费的内容,还能智能到哪里去了?整一堆乱七八糟的,花里胡哨的垃圾东西,开机慢,体验差,就一台电视而已!集成什么多少核心的CPU,多大的运行内存,且残废的安卓系统又如何,还不是半年就淘汰的电子垃圾,浪费成本,不切实际!这不现在卡住了么!惊不惊喜!

TCL D48A620U 智能系统启动中… 卡壳中

还智能系统呢!智障系统我看可还行。

按住右侧摇把 向下键 ↓ 然后接通电源,会经过一段清理程序,然后再到下图这个画面:

铁粉社区,算了吧!

尝试访问铁粉社区 http://fans.tcl.com/ ,我去!!!毛都没有,还铁粉社区,都是套路。

就这!

这就是所谓的智能!

好吧,进入解决问题的环节。话说好久好久没有搞过电视了哟,再搞搞看看效果如何吧。

这问题首先得从它的软件部分着手,因为它是智能的嘛!

登录查看完整内容

acme.sh 申请并自动续期 ssl 证书

acme.sh 是一个 ACME Shell 脚本

  • 一个完全用 Shell(Unix shell)语言编写的 ACME 协议客户端
  • 完整的 ACME 协议实现
  • 支持 ECDSA 证书
  • 支持 SAN 和通配符证书
  • 简单、强大且非常易于使用。您只需要 3 分钟即可学会
  • Bash、dash 和 sh 兼容
  • 纯粹用 Shell 编写,不依赖于 python
  • 只需一个脚本即可自动颁发、更新和安装您的证书

这可能是最简单最好用的的自动颁发和更新免费证书的 shell 脚本。

可能在2021年8月份吧,acme 将默认 CA 更改为 ZeroSSL,所以默认按照以前的就方法申请 letencrypt 证书会有一些报错,所以我们有必要再记录一下或适应一下现在新版的 acme.sh

使用 acme.sh 申请并自动续期 SSL 证书

一、安装 acme.sh

很简单,一个命令:

curl https://get.acme.sh | sh
  • 国内安装可能有时候由于网络问题,导致安装不成功,确保安装过程日志:Install success!
  • 如果安装不成功可以再次运行安装命令,继续尝试安装。
  • 安装完成会自动创建一个计划任务,每天 0 点左右自动检测所有的证书,如果证书快过期了,则会自动更新证书。

二、申请证书

强烈推荐用 DNS API 模式申请证书,没必要尝试其他方法。完美支持在阿里云购买的域名使用 DNS API 模式,仅需 Ali_Key 与 Ali_Secret,我们需要提前在阿里云上开通子账户功能,为了安全请配置好仅用于DNS API的子账户的权限。

1、配置API key

Ali_Key 和 Ali_Secret 将保存在 ~/.acme.sh/account.conf 中,并在需要时重复使用。

# 分别执行以下命令配置 API key
export Ali_Key="LT********S"
export Ali_Secret="O******************F"

2、申请证书

申请的是通配符证书

# 注意这里指定 CA 为 letsencrypt。 --server letsencrypt
/root/.acme.sh/acme.sh --issue --dns dns_ali -d sgtfz.cn -d *.sgtfz.cn --server letsencrypt

因为在 acme.sh 没有更换默认 CA 为 ZeroSSL 之前,我的是 letsencrypt 申请颁发的 SSL 证书,因此如果你还是想使用 letsencrypt 作为默认 CA,可以使用下面的命令配置

/root/.acme.sh/acme.sh --set-default-ca --server letsencrypt

如果你按照以前的命令申请证书:

# 注意这里没有指定 CA,默认 CA 为 ZeroSSL
/root/.acme.sh/acme.sh --issue --dns dns_ali -d sgtfz.cn -d *.sgtfz.cn

会提示你需要电子邮件更新账户:

root@aly-ECS-T5-sgtfz:~# /root/.acme.sh/acme.sh --issue --dns dns_ali -d sgtfz.cn -d *.sgtfz.cn
[Sun 02 Jan 2022 10:19:58 PM CST] Using CA: https://acme.zerossl.com/v2/DV90
[Sun 02 Jan 2022 10:19:59 PM CST] Create account key ok.
[Sun 02 Jan 2022 10:19:59 PM CST] No EAB credentials found for ZeroSSL, let's get one
[Sun 02 Jan 2022 10:19:59 PM CST] acme.sh is using ZeroSSL as default CA now.
[Sun 02 Jan 2022 10:19:59 PM CST] Please update your account with an email address first.
[Sun 02 Jan 2022 10:19:59 PM CST] acme.sh --register-account -m my@example.com
[Sun 02 Jan 2022 10:19:59 PM CST] See: https://github.com/acmesh-official/acme.sh/wiki/ZeroSSL.com-CA
[Sun 02 Jan 2022 10:19:59 PM CST] Please add '--debug' or '--log' to check more details.
[Sun 02 Jan 2022 10:19:59 PM CST] See: https://github.com/acmesh-official/acme.sh/wiki/How-to-debug-acme.sh

如果我们选择使用默认 CA 为 ZeroSSL 申请 SSL 证书,可以按照提示更新账户:

/root/.acme.sh/acme.sh --register-account -m sgtfz@sgtfz.cn --server zerossl

三、安装证书

注意, 默认生成的证书都放在安装目录下:~/.acme.sh/,请不要直接使用此目录下的文件,例如: 不要直接让 nginx/apache 的配置文件使用这下面的文件。这里面的文件都是内部使用,而且目录结构可能会变化。

正确的使用方法是使用 --install-cert 命令,并指定目标位置,然后证书文件会被复制到相应的位置。

# 证书匹配apache与nginx。
# nginx使用key.pem、chain.pem
# apache使用cert.pem、key.pem、chain.pem
/root/.acme.sh/acme.sh --install-cert -d sgtfz.cn \
--cert-file      /etc/nginx/cert/sgtfzcn_cert.pem \
--key-file       /etc/nginx/cert/sgtfzcn_key.pem \
--fullchain-file /etc/nginx/cert/sgtfzcn_chain.pem \
--reloadcmd     "service nginx force-reload"

或者 --reloadcmd "service apache2 force-reload" 对应重载 apache

一个小提醒,这里用的是 service nginx force-reload,不是 service nginx reload,据测试,reload 并不会重新加载证书,所以用的 force-reload

Nginx 的配置 ssl_certificate 使用 /etc/nginx/ssl/fullchain.cer ,而非 /etc/nginx/ssl/<domain>.cer ,否则 SSL Labs 的测试会报 Chain issues Incomplete 错误。

--install-cert 命令可以携带很多参数,来指定目标文件。并且可以指定 reloadcmd,当证书更新以后,reloadcmd 会被自动调用,让服务器生效。

详细参数请参考: https://github.com/Neilpang/acme.sh#3-install-the-issued-cert-to-apachenginx-etc

值得注意的是,这里指定的所有参数都会被自动记录下来,并在将来证书自动更新以后,被再次自动调用

四、更新 acme.sh

目前由于 acme 协议和 letsencrypt CA 都在频繁的更新,因此 acme.sh 也经常更新以保持同步

升级 acme.sh 到最新版:

acme.sh --upgrade

如果你不想手动升级,可以开启自动升级:

acme.sh --upgrade --auto-upgrade

之后,acme.sh 就会自动保持更新了。

你也可以随时关闭自动更新:

acme.sh --upgrade --auto-upgrade 0

更多详细说明,请到官方代码库查看

https://github.com/acmesh-official/acme.sh

Windows Terminal 远程SSH连接阿里云ECS配置

Windows 通过SSH远程连接阿里云ECS服务器,由于阿里云ECS上用的是密钥对进行连接,所以我们需要配置 Windows Terminal 引用密钥来进行SSH连接

设置 Windows Terminal

在 Windows Terminal 设置,打开 JSON 文件,找到 "list": 下在最后面追加我们自定义的配置项,下面是没有追加的默认的配置

        "list": 
        [
            {
                "colorScheme": "Campbell",
                "commandline": "powershell.exe",
                "font": 
                {
                    "size": 11
                },
                "guid": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}",
                "hidden": false,
                "name": "Windows PowerShell"
            },
            {
                "colorScheme": "Campbell",
                "commandline": "cmd.exe",
                "font": 
                {
                    "size": 11
                },
                "guid": "{0caa0dad-35be-5f56-a8ff-afceeeaa6101}",
                "hidden": false,
                "name": "\u547d\u4ee4\u63d0\u793a\u7b26"
            },
            {
                "font": 
                {
                    "size": 11
                },
                "guid": "{b453ae62-4e3d-5e58-b989-0a998ec441b8}",
                "hidden": false,
                "name": "Azure Cloud Shell",
                "source": "Windows.Terminal.Azure"
            }
        ]

我们在 "list": 的方括号内的最后追加自己的配置

 			{
				"guid": "{94f54466-5a23-455f-a7d8-cbb495bb81bc}",
				"hidden": false,
				"name": "aly ECS",
				"commandline": "ssh -i D:/NextCloud/KeeWeb/aly-ECS-sgtfz-key.pem root@47.113.100.27",
				"closeOnExit": true
			}

上面自定义配置的说明:

  • "guid": "{guid}" 我们可以直接在 Windows Terminal 命令行输入 new-guid 即可生成。
  • "name": "aly ECS" 这里可以自定义自己喜欢的名称。
  • "commandline": 如上面的格式填上密钥的路径。

最后配置完成的配置文件如下:

        "list": 
        [
            {
                "colorScheme": "Campbell",
                "commandline": "powershell.exe",
                "font": 
                {
                    "size": 11
                },
                "guid": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}",
                "hidden": false,
                "name": "Windows PowerShell"
            },
            {
                "colorScheme": "Campbell",
                "commandline": "cmd.exe",
                "font": 
                {
                    "size": 11
                },
                "guid": "{0caa0dad-35be-5f56-a8ff-afceeeaa6101}",
                "hidden": false,
                "name": "\u547d\u4ee4\u63d0\u793a\u7b26"
            },
            {
                "font": 
                {
                    "size": 11
                },
                "guid": "{b453ae62-4e3d-5e58-b989-0a998ec441b8}",
                "hidden": false,
                "name": "Azure Cloud Shell",
                "source": "Windows.Terminal.Azure"
            },
			{
				"guid": "{94f54466-5a23-455f-a7d8-cbb495bb81bc}",
				"hidden": false,
				"name": "aly ECS",
				"commandline": "ssh -i D:/NextCloud/KeeWeb/aly-ECS-sgtfz-key.pem root@47.113.100.27",
				"closeOnExit": true
			}
        ]

现在我们尝试连接阿里云ECS服务器啦

Windows terminal

但是又出现了问题,Windows Terminal 提示如下:

Windows Terminal 警告密钥未受保护

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions for 'D:/NextCloud/KeeWeb/aly-ECS-sgtfz-key.pem' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "D:/NextCloud/KeeWeb/aly-ECS-sgtfz-key.pem": bad permissions

原因是由于密钥文件权限太开放,需要设置为仅对使用用户可见。

Windows 系统设置密钥文件权限

  • 密钥文件:keyfile.pem
    • 右键点击 → keyfile.pem → 属性 → 安全 → 高级 → 禁用集成 → 从此对象中删除所有已继承的权限 → 确定 → 是 → 确定
    • 右键点击 → keyfile.pem → 属性 → 安全 → 高级 → 添加 → 选择主体 → 高级 → 立即查找 → 从搜索结果找到当前用户 → 双击 当前用户 → 确定 → 确定

Windows Terminal 终于可以正常连接阿里云ECS了!