未经审视的人生不值得过。

我的pleroma检修笔记1

2023.02.10

运行pleroma一年后的debug、数据备份和版本升级。

pleroma在我租的那台1G 内存,25GB的小vps里运行一年了,在使用中逐渐出现一些问题和新的需求。

最想要解决的两个问题:

  • 我关注的fediverse用户超过了150个,时间线上消息太多看不过来,需要用列表分类。而低版本2.4pleroma没有列表功能。已知 pleroma的前端之一soapbox可以做列表,但看过soapbox与pleroma开发者们发生的争执后,我并不是很想学怎么装这个前端。所以,有别的办法吗?

  • 去年下半年以来,时间线频繁出现了刷不出嘟友最新嘟文、乱序、与某些实例断联的问题。我一开始用重启解决 systemctl restart pleroma.service,每次重启后可以短暂恢复,但过了几天又是同样的问题。这究竟是怎么回事呢?

不得不学的基本操作

  • pleroma数据备份 和 版本升级
    • 前段时间,我的pleroma实例彻底与某些实例断联,让我猜想是不是我站版本太低了(otz努力赶上大部队)。
    • 其次考虑到以后可能要换vps,不可能一直不学备份。只能硬着头皮动手学了。

参考资料

基于上面的需求,我去搜了一些相关的资料,发现中文pleroma教程越来越多了( •̀ ω •́ )y
以下是各种参考资料:

https://blog.debula.ml/index.php/archives/5/ 【数据备份、版本升级、前端 等】
https://im.happytoo.cyou/posts/2301%E5%A4%87%E4%BB%BDpleroma/ 【数据备份】
https://seviche.cc/2023-01-22-backup/ 【数据备份】

https://dabr.ca/notice/AQhdqry35qWK6cVaBU 【相似的报错1】
https://dabr.ca/notice/AQfGjf2GH0kYH3XE9I 【相似的报错2】

(非常感谢大家的pleroma相关讨论和各种教程,给了我很多启发和帮助。只有多交流才会有进步的可能~)

思路

去年的pleroma安装,我完全是复制粘贴suica写好的教程,对于PostgreSQL、nginx这些概念完全不懂。

今年要思考怎么修好实例,自己就得提出一些猜测,再学着验证。去年只要求简单地理解概念,今年要求更深入地理解概念,还得额外面临一些不确定性进行试错和快速复原,所以学习的成本和难度增加了。最后,我的pleroma检修思路是:先备份,再检查内存和储存的情况,再针对性地解决问题,问题解决失败了,于是重装升级。

以下是全过程的记录。

备份

pleroma单个账号的数据备份

只要该pleroma实例开通了邮件功能,就可以使用kana以前写的脚本进行备份,亲测有用。

  • 火狐 安装 Tampermonkey后,访问 https://greasyfork.org/en/scripts/442817-pleroma-backup 安装该脚本
  • 登录pleroma ,进入pleroma用户的个人主页
  • 使用web开发者工具,在控制台 输入backupPleroma()后会自动生成一个zip的下载链接
  • 下载到本地,解压后即可查看该用户的单独账号数据(内含书签、喜欢、嘟文资料等)

混乱时间线的原因探究

看了那两个相似报错后,我开始猜测时间线时好时坏是否和vps的1G小内存有关系。

于是通过查询命令free -h记录了一些内存变化:

时间线卡死时:

root@XXXXXXXX:~# free -h
              total        used        free      shared  buff/cache   available
Mem:          987Mi       411Mi        75Mi       306Mi       500Mi       132Mi
Swap:            0B          0B          0B

重启后,时间线变得丝滑了起来:

root@XXXXXXXX:~# free -h
              total        used        free      shared  buff/cache   available
Mem:          987Mi       393Mi       163Mi       299Mi       430Mi       195Mi
Swap:            0B          0B          0B

于是我做了一些拯救1G内存的操作,感觉没啥用但有个安慰:在pleroma-fe 的settings - instance中,我把100调成了80。

Fed. incoming replies max depth 100
Max. depth of reply-to and reply activities fetching on incoming federation, to prevent out-of-memory situations while fetching very long threads. If set to `nil`, threads of any depth will be fetched. Lower this value if you experience out-of-memory crashes.

做完这一切后,我突发奇想,查了一下数据库大小。

root@XXXXXXXX:~# su - postgres
postgres@vm367944:~$ psql

postgres=# SELECT pg_size_pretty( pg_database_size('pleroma') );
pg_size_pretty
----------------
 19 GB
(1 row)

(ˉ▽ˉ;)…我的vps硬盘只有25GB,pleroma运行一年后就变成了19GB,而本站只有我一个人在用。我自己的嘟文绝对没有那么大,那么19GB到底是装了什么呢?我开始猜测,是不是pleroma缓存了大量的外站嘟文数据,而没有进行定期清理,才会导致数据库变得如此庞大。

在清理数据库之前,我决定先备份数据库。我首先选用pg_dump进行备份,可惜并不顺利,出现了如下报错:

# 暂停运行实例
su pleroma -s $SHELL -lc "./bin/pleroma stop"

# 创建存放数据库文件的文件夹并设置其所有者为用户 pleorma
mkdir -p /p_backup/pleroma_b
chown -R pleroma /p_backup

# 用pg_dump备份
postgres=# \! pg_dump pleroma -f /p_backup/pleroma_b/pleroma.pgdump

# 报错来了
pg_dump: [archiver] could not write to output file: No space left on device

没有硬盘空间了。于是我查了一下此刻的硬盘存储情况:

root@XXXXXXXX:~# df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        26G   25G     0 100% /

我猜测新备份的pleroma.pgdump的数据大小已经超过了6GB,所以硬盘装不下了……于是我删除了新备份多次重试,始终报错空间不足。此刻,我并没有想到别的好办法。也没有去尝试备份到别的地方,我选择了备份到本地。可是,这时候我找到的pleroma.pgdump只有366MB大小,和我查到的19GB相去甚远,我找不到别的数据在哪里,于是我就只把这个366MB的文件下载到了本地。

然后,我想,既然是硬盘空间不够才导致pg_dump无法备份,那我可不可以清理数据库之后,再进行备份呢?

我在官方文档找到了如下命令:https://docs-develop.pleroma.social/backend/administration/CLI_tasks/database/

./bin/pleroma_ctl database prune_objects [option ...]
./bin/pleroma_ctl database vacuum full

如果我没有理解错误的话:第一个命令是清理缓存外站数据,但空出来的磁盘空间只有在执行第二个Full命令后才能生效。而我也看到了官方文档里面的警告,这两个命令都需要有足够的硬盘空间。如果运用失败了也可以取消命令(但它没写怎么取消)

于是按照这个理解,我决定试一试,快速执行了上面两个命令。

root@XXXXXX:~# su pleroma -s $SHELL -lc "./bin/pleroma_ctl database prune_objects "

12:59:45.282 [info]  Pruning objects older than 30 days

13:01:38.217 [debug] QUERY ERROR source="objects" db=112930.9ms queue=2.6ms idle=846.6ms
DELETE FROM "objects" AS o0 WHERE (o0."data"->'to' ? $1 OR o0."data"->'cc' ? $2) AND (o0."inserted_at" < $3) AND (split_part(o0."data"->>'actor', '/', 3) != $4) ["https://www.w3.org/ns/activitystreams#Public", "https://www.w3.org/ns/activitystreams#Public", ~N[2023-01-09 09:59:45], "dasgelobteland.art"]==

** (DBConnection.ConnectionError) tcp recv: closed
lib/ecto/adapters/sql.ex:760: Ecto.Adapters.SQL.raise_sql_call_error/1
lib/ecto/adapters/sql.ex:693: Ecto.Adapters.SQL.execute/5
lib/mix/tasks/pleroma/database.ex:97: Mix.Tasks.Pleroma.Database.run/1
(stdlib 3.12.1) erl_eval.erl:680: :erl_eval.do_apply/6
(elixir 1.10.3) lib/code.ex:341: Code.eval_string_with_error_handling/3

# 显然出现了报错,但我已经看不懂了。我继续执行了FUll

root@XXXXXX:~# su pleroma -s $SHELL -lc "./bin/pleroma_ctl database vacuum full "

13:07:48.160 [info]  Runnning VACUUM FULL.

13:07:48.164 [warn]  Re-packing your entire database may take a while and will consume extra disk space during the process.

13:07:48.357 [debug] QUERY ERROR db=196.7ms queue=2.4ms idle=566.2ms
vacuum full; []
** (Postgrex.Error) ERROR 53100 (disk_full) could not extend file "base/16385/780447": wrote only 4096 of 8192 bytes at block 823

hint: Check free disk space.
lib/ecto/adapters/sql.ex:760: Ecto.Adapters.SQL.raise_sql_call_error/1
(stdlib 3.12.1) erl_eval.erl:680: :erl_eval.do_apply/6
(elixir 1.10.3) lib/code.ex:341: Code.eval_string_with_error_handling/3

用完这两个命令之后,我知道硬盘空间已经装满了。我以为我能够通过重新删除来恢复硬盘空间,但我却没有找到对应的新增文件,再加上看不懂这些报错,我也不敢去乱删。

此时我已经无法再使用任何工具辅助备份了,我手里只有本地下载的那个366MB的数据库了。而且由于硬盘已满,postgres也无法正常运行。

我只好删除所有东西,开始重装,试着看能不能用这个366MB恢复点什么。

重装升级

如果站没有炸,我可能会试一试用 https://docs-develop.pleroma.social/backend/administration/updating/ 里面的 OTP installations 命令来升级pleroma (下次再试吧)

可惜数据库已经被我搞得一塌糊涂,所以我采取了 彻底删除 ,再 重新安装pleroma新版本的思路来升级

# 在root用户下 停止pleroma服务
systemctl stop pleroma
# 禁用pleroma 
systemctl disable pleroma

删除安装过程中创建的pleroma、nginx 和 systemd文件和文件夹(以下只是我删除的路径,仅作参考)

/var/lib/pleroma  
/opt/pleroma  
/etc/pleroma  

/etc/nginx/sites-available  
/etc/nginx/sites-enabled  

/etc/systemd/system/pleroma.service  

如果没删干净,在重新安装时候会出现相关报错,只需要根据报错再去删掉就行。如果安装成功后,输入pleroma实例网址,却出现页面空白,浏览器开发工具显示是某些js加载失败,或者出现net::ERR_HTTP2_PROTOCOL_ERROR的报错,极大可能是nginx出了问题,可以卸载整个nginx再重装。如果担心nginx没删干净,也直接卸载再重装。

# 删除除/etc/nginx 配置文件外的所有文件
sudo apt-get remove nginx

# 删除nginx配置文件
sudo apt-get purge nginx

# 删除安装nginx时安装的依赖包
sudo apt-get autoremove

# 重装
apt-get -o DPkg::options::=--force-confmiss --reinstall install nginx

重启 nginxsystemctl reload nginx

删除数据库和数据库用户 <pleroma_db>替换为你的pleroma数据库名称,默认名称就是pleroma,如果不是,可以通过psql命令查询

sudo -Hu postgres psql -c 'DROP DATABASE <pleroma_db>;';
sudo -Hu postgres psql -c 'DROP USER <pleroma_db>;'

删除系统用户 userdel pleroma可能会出现这样的报错提醒:userdel: user vivek is currently used by process 749 error and fix on Linux

于是参考了 https://www.cyberciti.biz/faq/userdel-user-vivek-is-currently-used-by-process-749-error-and-fix-on-linux/

# 停止运行
kill -15 749(749替换为对应出现的数字)

# 重新尝试删除
userdel pleroma

我逐一停止运行后再删掉了pleroma系统用户,这个网页里面的 killall并没有起效。在尝试中,有一次我放弃了彻底删除系统用户这个操作,想着凑合着安装试一试,但发现如果不删干净还是会出问题,所以还是能删就删。

最后,重新按照suica的教程进行otp 方式的安装,只不过这一次的安装包地址我就换成了最新的pleroma2.5版本

安装包地址请参考 https://blog.debula.ml/index.php/archives/5/#1.%E7%A4%BE%E4%BA%A4%E7%BD%91%E7%BB%9C%EF%BC%9APleroma 里面的寻找方式,我使用的也是amd64

# 下载安装 Pleroma 2.5 所需的文件到 /tmp 文件夹并解压

su pleroma -s $SHELL -lc "curl 'https://git.pleroma.social/pleroma/pleroma/-/jobs/226602/artifacts/download?file_type=archive'  -o /tmp/pleroma.zip 
unzip /tmp/pleroma.zip -d /tmp/"

接下来的安装方式可以完全参考suica的教程了。如果我的数据库恢复没有失败,我的步骤就会参考版本回滚的那个教程……但……是……(⋟﹏⋞)

重装成功之后,我发现我之前的数据是彻底没有了,366MB也毫无作用。

pleroma新版本有列表功能了

当我升级到2.5后,发现了新版本已经有列表分类功能,所以第一个问题就解决了,我暂时没有兴趣去装别的前端了。不过如果要自己动手做pleroma的主题,还是要装pleroma-fe的前端。

后续

过了一天,我查资料的时候看到了 https://dabr.ca/notice/ASIIfXSYztsow8VkdE

看完之后我好像明白了之前踩坑的原因了。于是我想着,等过半个月之后,我的新站又缓存了一些数据,并且在硬盘空间较为充足的情况下,我再试着用一用清理数据库的那两个命令,也许这一次不会再报错了。试一试呢。

2023/4/7 更新

4月2号重新折腾了一下,结果如下:

检查2个月内的数据库增长情况,这期间站子没有加任何中继,但数据库依然高达960MB……悲QAQ

用pg_dump备份了,成功。这一步是为了防止下面的清理数据库出问题,备份非常重要,越早做备份越好。

然后开始清理数据库,打算删掉30天以前的所有外站缓存,也就是要重新尝试上次那两个清理数据库的命令。先在管理员模式里面 的 setting - instance - Remote post retention days ,把默认的90天缓存改成30天

# 删除30天之前的外站缓存嘟文,成功的话大概是下面的反应
 root@XXXXX:~# su pleroma -s $SHELL -lc "./bin/pleroma_ctl database prune_objects"
 
 13:05:45.220 [info]  Pruning objects older than 30 days
 13:05:48.075 [debug] QUERY OK source="objects" db=2845.5ms queue=7.8ms idle=655.6ms
 DELETE FROM "objects" AS o0 WHERE (o0."data"->'to' ? $1 OR o0."data"->'cc' ? $2) AND (o0."inserted_at" < $3) AND (split_part(o0."data"->>'actor', '/', 3) != $4) XXXXXXXXXXXXXXXXXXXXXXXX
 13:05:48.252 [debug] QUERY OK db=170.6ms queue=2.2ms idle=1511.1ms
 DELETE FROM hashtags AS ht
 WHERE NOT EXISTS (
 SELECT 1 FROM hashtags_objects hto
 WHERE ht.id = hto.hashtag_id)

# 整理数据库
 root@XXXXX:~# su pleroma -s $SHELL -lc "./bin/pleroma_ctl database vacuum full"
 13:07:04.861 [info]  Running VACUUM FULL.
 13:07:04.861 [warn]  Re-packing your entire database may take a while and will consume extra disk space during the process.
 Session terminated, killing shell... ...killed.

重新查看数据库大小,小了很多,从960MB降到529MB。这下才开始真正地备份~ 再一次用pg_dump备份。

# 暂停运行实例
 root@XXXXX:~# su pleroma -s $SHELL -lc "./bin/pleroma stop"

# 创建存放数据库文件的文件夹,写入权限
 root@XXXXX:~# mkdir -p /pleromabackup
 root@XXXXX:~# chmod 777 /pleromabackup

# 用pg_dump备份
 root@XXXXX:~# su - postgres
 postgres=# \! pg_dump pleroma -f /pleromabackup/pleroma.pgdump

pleroma 从版本2.5 升级到 2.5.1。上一次我是重新下载pleroma安装包来升级,这一次我就用了官方的OTP命令。

# 升级
 root@XXXXX:~# su pleroma -s $SHELL -lc "./bin/pleroma_ctl update"

升级之后,然后跟着 https://docs.pleroma.social/backend/administration/backup/#restoremove 的步骤来恢复pleroma,也可以参考 https://blog.debula.ml/index.php/archives/5/#%E6%95%B0%E6%8D%AE%E6%81%A2%E5%A4%8D/%E7%89%88%E6%9C%AC%E5%9B%9E%E6%BB%9A 里面记录的数据恢复过程。步骤主要是 :重新生成数据库配置,改密码;清空数据库;重建数据库 (不再赘述)

恢复数据

#  这一步我就用不了pg_restore了,报错如下:
 root@XXXXX:~# sudo -Hu postgres pg_restore -d pleroma -v -j 4 /pleromabackup/pleroma.pgdump
 could not change directory to "/root": Permission denied
 pg_restore: [archiver] input file appears to be a text format dump. Please use psql.

参考了 https://stackoverflow.com/questions/68824946/pg-restore-archiver-input-file-appears-to-be-a-text-format-dump-please-use-p ,解决了。

 # 用psql恢复数据库,注意它可能会非常慢,需要耐心地等待……我等了20min
 root@XXXXX:~# sudo -u postgres psql pleroma < /pleromabackup/pleroma.pgdump

关于这个恢复速度不一样的原因,请看 https://www.qiniu.com/qfans/qnso-71884114#comments ,以及得到了debula (还不知道该怎么正确地称呼人家……otz)的讲解:pg_restore 的提示看着像是备份的命令有问题,保存的是重建数据库的sql命令。最后因为恢复本质上是在一行一行执行sql,很容易卡住。如果想加速可以把 -1 改成 -j 4,-j 4 是 pg_restore 用 4 个线程同时恢复的参数,psql 里面没有 https://www.postgresql.org/docs/current/app-pgrestore.html

我大概明白了pg_restore和psql这两种恢复方式的区别:sudo -Hu postgres pg_restore -d(dbname) pleroma -v -j 4(线程) /pleromabackup/pleroma.pgdump 而我用的另一种是 sudo -u postgres psql db_name < 'file_path',而后者psql比pg_restore慢,所以等了很久。不过,我不明白为什么会报错我的备份格式不对?我直接抄的备份命令……那别人为啥没有这个报错呢?还好,最后用psql恢复也达到效果了。那我下次再认真探究这个问题吧。

恢复数据库成功后,再重新启动pleroma即可。