记一次生产事故

编程

写在前面

今天,跑在阿里云ECS上的生产环境,突然间访问异常,接口各种报错,无奈公司没有专业的运维人员,只能硬着头皮解决一下。

问题排查

先从表面看起,数据库首先报错

Caused by: org.postgresql.util.PSQLException: ERROR: could not extend file "base/16385/16587_fsm": No space left on device

建议:Check free disk space.

直观上看,设备没有可用空间,也就是磁盘满了。

进入服务器后台,执行

$ df -h

Filesystem Size Used Avail Use% Mounted on

udev 7.9G 0 7.9G 0% /dev

tmpfs 1.6G 3.5M 1.6G 1% /run

/dev/vda1 59G 56G 0 100% /

tmpfs 7.9G 4.0K 7.9G 1% /dev/shm

tmpfs 5.0M 4.0K 5.0M 1% /run/lock

tmpfs 7.9G 0 7.9G 0% /sys/fs/cgroup

/dev/mapper/vg0-vol0 1000G 14G 937G 2% /data

tmpfs 1.6G 0 1.6G 0% /run/user/0

发现确实磁盘满了,而且满的很彻底。系统盘占用100%,估计什么服务都跑不动了。/dev/vda1 59G 56G 0 100% /

不过发现/dev/mapper/vg0-vol0 1000G 14G 937G 2% /data,1000G只用了2%

阿里云ECS分为系统盘和数据盘,1000G的是数据盘

第一反应,应该是搭建的PG数据库的数据没有移到数据盘上。

将Postgres数据库数据目录移动到系统盘

参考如何将PostgreSQL数据目录移动到Ubuntu 16.04上的新位置

$ sudo -u postgres psql

postgres# SHOW data_directory; # 查看当前数据目录

data_directory

------------------------------

/var/lib/postgresql/9.5/main

(1 row)

postgres# q; # 退出

# 为了确保数据的完整性,我们将在实际更改数据目录之前关闭PostgreSQL

$ sudo systemctl stop postgresql

# 确保关闭完成

$ sudo systemctl status postgresql

. . .

Jul 22 16:22:44 ubuntu-512mb-nyc1-01 systemd[1]: Stopped PostgreSQL RDBMS.

$ sudo rsync -av /var/lib/postgresql /data # /data为要迁移到的新目录

$ cd /data

$ ls

... postgresql

# 删除原数据目录

$ sudo rm -rf /var/lib/postgresql

# 将新数据目录链接到原数据目录

$ sudo ln -s /data/postgresql /var/lib/postgresql

# 重启Postgres数据库

$ sudo systemctl start postgresql

$ sudo systemctl status postgresql

完成以上步骤,即将postgre数据库数据目录移到了阿里云数据盘

以为OK了,执行

$ df -h

Filesystem Size Used Avail Use% Mounted on

udev 7.9G 0 7.9G 0% /dev

tmpfs 1.6G 3.5M 1.6G 1% /run

/dev/vda1 59G 56G 51M 100% /

tmpfs 7.9G 4.0K 7.9G 1% /dev/shm

tmpfs 5.0M 4.0K 5.0M 1% /run/lock

tmpfs 7.9G 0 7.9G 0% /sys/fs/cgroup

/dev/mapper/vg0-vol0 1000G 14G 937G 2% /data

tmpfs 1.6G 0 1.6G 0% /run/user/0

纹丝未动。。。

Ubuntu查询大文件

猜测是存在大文件导致磁盘被占满

$ cd /

$ find . -type f -size +800M -print0 | xargs -0 du -h

5.6G ./var/log/syslog.1

6.7G ./var/log/syslog

...

$ rm ...

如果发现是log字眼的大文件,我们可以毫不留情的删掉,要是遇见一些不认识的,不要贸然删掉,一定要查清楚文件的作用,能删则删,千万不要不小心删库跑路。。。

删除完毕后,再次查看

$ df -h

Filesystem Size Used Avail Use% Mounted on

udev 7.9G 0 7.9G 0% /dev

tmpfs 1.6G 3.4M 1.6G 1% /run

/dev/vda1 59G 45G 12G 80% /

tmpfs 7.9G 4.0K 7.9G 1% /dev/shm

tmpfs 5.0M 4.0K 5.0M 1% /run/lock

tmpfs 7.9G 0 7.9G 0% /sys/fs/cgroup

/dev/mapper/vg0-vol0 1000G 14G 936G 2% /data

tmpfs 1.6G 0 1.6G 0% /run/user/0

多出了12G。

查看已删除空间却没有释放的进程

这时候,服务应该可以恢复成功。但你马上会发现,磁盘又被占满,而这次,日志文件却不算大。

查看已经删除的文件,空间有没有释放,没有的话kill掉pid

使用rm删除文件的时候,虽然文件已经被删除,但是由于文件被其他进程占用,空间却没有释放

$ sudo lsof -n |grep deleted

java 17866 root 237r REG 253,1 163541 1709285 /tmp/tomcat.8250394289784312179.8080/work/Tomcat/localhost/ROOT/upload_c6db0c17_6e6a_4141_bfb6_ac1b2d8a3b0b_00000000.tmp (deleted)

...

$ sudo kill -9 17866

再次使用df -h命令,磁盘使用率一下子减少了好多。

总结

  • 服务器系统盘被占满是非常可怕的!届时,一切服务都将变得不可用,业务系统也会莫名其妙多出奇怪的问题。所以,运维需要经常性的查看服务器磁盘占用情况,阿里云ECS用户,可以开启报警,及时发现问题,解决问题!

  • 阿里云ECS提供了系统盘和数据盘,记住,例如Pg、Redis、Cassandra等容易占磁盘的服务,一定要将数据目录放在阿里云ECS提供的数据盘上。

  • /var/log是系统日志目录,可以经常性的关注下,大容量日志尽早删除。

  • 对待进程不停对文件写日志的操作,要释放文件占用的磁盘空间,最好的方法是在线清空这个文件,可以通过如下命令完成:

[root@localhost ~]# echo "" >/var/log/syslog

通过这种方法,磁盘空间不但可以马上释放,也可保障进程继续向文件写入日志,这种方法经常用于在线清理Apache、Tomcat、Nginx等Web服务产生的日志文件。

最后,有一个专业的运维是多么重要!

以上是 记一次生产事故 的全部内容, 来源链接: utcz.com/z/513350.html

回到顶部