问题回顾

近两天被gitlab搞疯了,首先中了勒索病毒,然后重新在服务器上部署了一个gitlab,拷贝数据到新的gitlab数据仓库中,调试数据时发现尽管数据删除了,但是gitlab页面仍然还有这个项目的名字,于是尝试删除postgresql的数据目录(/var/opt/gitlab/postgresql/data)下的数据,但是重启服务时,服务启动失败;恢复数据回data目录下时,再启动postgresql时发现启动失败,gitlab 502了。

image.png

  1. #启动gitlab
  2. root@ip-192-168-128-191:/var/opt/gitlab/postgresql/data# gitlab-ctl start
  3. ok: run: alertmanager: (pid 6063) 0s
  4. ok: run: gitaly: (pid 6072) 1s
  5. ok: run: gitlab-exporter: (pid 6086) 0s
  6. ok: run: gitlab-workhorse: (pid 6088) 0s
  7. ok: run: grafana: (pid 6097) 1s
  8. ok: run: logrotate: (pid 6106) 0s
  9. ok: run: nginx: (pid 6112) 1s
  10. ok: run: node-exporter: (pid 6118) 0s
  11. ok: run: postgres-exporter: (pid 6124) 1s
  12. ok: run: postgresql: (pid 6140) 0s
  13. ok: run: prometheus: (pid 6142) 0s
  14. ok: run: puma: (pid 6153) 1s
  15. ok: run: redis: (pid 6158) 0s
  16. ok: run: redis-exporter: (pid 6164) 0s
  17. ok: run: sidekiq: (pid 6174) 1s
  18. #查询进程发现postgresql不存在
  19. root@ip-192-168-128-191:/var/opt/gitlab/postgresql/data# netstat -lnupt
  20. Active Internet connections (only servers)
  21. Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
  22. tcp 0 0 127.0.0.1:9121 0.0.0.0:* LISTEN 6164/redis_exporter
  23. tcp 0 0 127.0.0.1:9090 0.0.0.0:* LISTEN 6142/prometheus
  24. tcp 0 0 127.0.0.1:9187 0.0.0.0:* LISTEN 6124/postgres_expor
  25. tcp 0 0 127.0.0.1:9093 0.0.0.0:* LISTEN 6063/alertmanager
  26. tcp 0 0 127.0.0.1:36489 0.0.0.0:* LISTEN 904/containerd
  27. tcp 0 0 127.0.0.1:9100 0.0.0.0:* LISTEN 6118/node_exporter
  28. tcp 0 0 127.0.0.1:9229 0.0.0.0:* LISTEN 6088/gitlab-workhor
  29. tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 6112/nginx: master
  30. tcp 0 0 127.0.0.1:9168 0.0.0.0:* LISTEN 6086/ruby
  31. tcp 0 0 127.0.0.1:9236 0.0.0.0:* LISTEN 6077/gitaly
  32. tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN 700/systemd-resolve
  33. tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 914/sshd
  34. tcp 0 0 127.0.0.1:3000 0.0.0.0:* LISTEN 6097/grafana-server
  35. tcp 0 0 0.0.0.0:8060 0.0.0.0:* LISTEN 6112/nginx: master
  36. tcp6 0 0 :::9094 :::* LISTEN 6063/alertmanager
  37. tcp6 0 0 :::22 :::* LISTEN 914/sshd
  38. udp 0 0 127.0.0.53:53 0.0.0.0:* 700/systemd-resolve
  39. udp 0 0 192.168.128.191:68 0.0.0.0:* 675/systemd-network
  40. udp6 0 0 :::9094 :::* 6063/alertmanager
  41. #查询postgresql进程
  42. root@ip-192-168-128-191:/var/opt/gitlab/postgresql/data# netstat -lnupt|grep 6140

解决问题

查询postgresql日志

  1. root@ip-192-168-128-191:/var/log/gitlab/postgresql# tail -f /var/log/gitlab/postgresql/current
  2. 2021-12-01_09:23:01.31345 LOG: database system is shut down
  3. 2021-12-01_09:23:02.36350 LOG: starting PostgreSQL 12.7 on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0, 64-bit
  4. 2021-12-01_09:23:02.36572 LOG: listening on Unix socket "/var/opt/gitlab/postgresql/.s.PGSQL.5432"
  5. 2021-12-01_09:23:02.49096 LOG: database system was shut down at 2021-12-01 09:07:58 GMT
  6. 2021-12-01_09:23:02.49110 LOG: invalid record length at 0/447CA80: wanted 24, got 0
  7. 2021-12-01_09:23:02.49111 LOG: invalid primary checkpoint record
  8. 2021-12-01_09:23:02.49113 PANIC: could not locate a valid checkpoint record
  9. 2021-12-01_09:23:02.64761 LOG: startup process (PID 6621) was terminated by signal 6: Aborted
  10. 2021-12-01_09:23:02.64763 LOG: aborting startup due to startup process failure
  11. 2021-12-01_09:23:02.66443 LOG: database system is shut down
  12. ......

从错误日志中我们可以发现一个信息“PANIC: could not locate a valid checkpoint record”,日志检查点定位错误,用pg_resetwal工具就可以恢复

pg_resetwal会清除预写式日志(WAL)并且有选择地重置存储在 pg_control文件中的一些其他控制信息。如果这些文件已经被损坏, 某些时候就需要这个功能。当服务器由于这样的损坏而无法启动时, 这只应该被用作最后的手段。 在运行这个命令之后,就应该可以启动服务器, 但是记住数据库可能包含由于部分提交事务产生的不一致数据。 你应当立刻转储你的数据、运行initdb并且重新载入。重新载入后, 检查不一致并且根据需要修复之。

这个工具只能被安装服务器的用户运行,因为它要求对数据目录的读写访问。 出于安全原因,你必须在命令行中指定数据目录。pg_resetwal 不使用环境变量PGDATA。

如果pg_resetwal抱怨它无法为pg_control 决定合法数据,你可以通过指定-f(强制)选项强制它继续。 在这种情况下,丢失的数据将被替换为看似合理的值。可以期望大部分域是匹配的, 但是下一个 OID、下一个事务 ID 和纪元、下一个多事务 ID 和偏移以及 WAL 开始地址域可能还是需要人工协助。这些域可以使用下面讨论的选项设置。 如果你不能为所有这些域决定正确的值,-f还是可以被使用, 但是恢复的数据库还是值得怀疑:一次立即的转储和重新载入是势在必行的。 在你转储之前不要在该数据库中执行任何数据修改操作, 因为任何这样的动作都可能使破坏更严重。

这个命令不能在服务器正在运行时被使用。如果在数据目录中发现一个服务器锁文件, pg_resetwal将拒绝启动。如果服务器崩溃那么一个锁文件可能会被留下, 在那种情况下你能移除该锁文件来让pg_resetwal运行。 但是在你那样做之前,再次确认没有服务器进程仍然存活。

  1. root@ip-192-168-128-191:/var/lib/polkit-1# /opt/gitlab/embedded/bin/pg_resetwal -f /var/opt/gitlab/postgresql/data/
  2. pg_resetwal: error: cannot be executed by "root"
  3. pg_resetwal: You must run pg_resetwal as the PostgreSQL superuser.

从错误提示中可以看出,我们需要使用postgresql 超级用户gitlab-psql

  1. #切换到gitlab-psql 用户下再次执行命令
  2. root@ip-192-168-128-191:/var/lib/polkit-1# su - gitlab-psql
  3. $ /opt/gitlab/embedded/bin/pg_resetwal -f /var/opt/gitlab/postgresql/data/
  4. Write-ahead log reset
  5. $ exit

重启postgresql,再次查询进程,我们可以看出数据库已经可以连接了。

  1. root@ip-192-168-128-191:/var/lib/polkit-1# gitlab-ctl restart postgresql
  2. ok: run: postgresql: (pid 19499) 0s
  3. root@ip-192-168-128-191:/var/lib/polkit-1# netstat -lnupt|grep 19499
  4. root@ip-192-168-128-191:/var/lib/polkit-1# tail -f /var/log/gitlab/postgresql/current
  5. 2021-12-01_10:22:40.41943 FATAL: terminating connection due to administrator command
  6. 2021-12-01_10:22:40.41943 FATAL: terminating connection due to administrator command
  7. 2021-12-01_10:22:40.41943 FATAL: terminating connection due to administrator command
  8. 2021-12-01_10:22:40.41995 LOG: background worker "logical replication launcher" (PID 19459) exited with exit code 1
  9. 2021-12-01_10:22:40.42000 LOG: shutting down
  10. 2021-12-01_10:22:40.46447 LOG: database system is shut down
  11. 2021-12-01_10:22:40.51856 LOG: starting PostgreSQL 12.7 on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0, 64-bit
  12. 2021-12-01_10:22:40.52894 LOG: listening on Unix socket "/var/opt/gitlab/postgresql/.s.PGSQL.5432"
  13. 2021-12-01_10:22:40.66366 LOG: database system was shut down at 2021-12-01 10:22:40 GMT
  14. 2021-12-01_10:22:40.66832 LOG: database system is ready to accept connections