Using lsof to Restore MySQL Deleted Data Files
MySQL 8.0.36 - RHEL 8.10
If you accidentally delete files, DO NOT RESTART OR SHUTDOWN the server.
The MySQL database info:
mysql> show databases; + | Database | + | information_schema | | mysql | | performance_schema | | sys | | zabbix | + 5 rows in set (0.00 sec)
mysql> SHOW VARIABLES LIKE 'datadir'; + | Variable_name | Value | + | datadir | /var/lib/mysql/ | + 1 row in set (0.65 sec)
~]# ls -1 /var/lib/mysql/zabbix/ | wc -l 207
|
Simulation files was mistakenly deleted.
rm -rf /var/lib/mysql/zabbix
|
Check MySQL service status, and set database read only.
~]# systemctl status mysqld ● mysqld.service - MySQL 8.0 database server Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: disabled) Active: active (running) since Wed 2025-09-03 19:18:15 CST; 2 days ago Main PID: 16048 (mysqld) Status: "Server is operational" Tasks: 61 (limit: 49003) Memory: 314.0M CGroup: /system.slice/mysqld.service └─16048 /usr/libexec/mysqld --basedir=/usr
Sep 03 19:17:46 oracle19c systemd[1]: Starting MySQL 8.0 database server... Sep 03 19:17:47 oracle19c mysql-prepare-db-dir[15969]: Initializing MySQL database Sep 03 19:18:15 oracle19c systemd[1]: Started MySQL 8.0 database server.
~]# mysql -uroot -p mysql> SET GLOBAL read_only = 1; Query OK, 0 rows affected (0.00 sec)
mysql> FLUSH TABLES WITH READ LOCK; Query OK, 0 rows affected (23.44 sec)
|
Using lsof to restore deleted files.
~]# lsof | grep deleted | grep "/var/lib/mysql/zabbix" | awk '{print $2,$5}' | sort | uniq 16048 mysql 16048 REG
~]# mkdir /var/lib/mysql/zabbix
~]# ls -l /proc/16048/fd | grep deleted | grep "/var/lib/mysql/zabbix" |awk '{print $9,$11}' > /tmp/deleted.txt ~]# while read num file; do echo "cat /proc/16048/fd/$num > $file"; done < /tmp/deleted.txt | bash
~]# chown -R mysql:mysql /var/lib/mysql/zabbix
~]# mysql -uroot -p
mysql> UNLOCK TABLES; Query OK, 0 rows affected (0.00 sec)
mysql> SET GLOBAL read_only = 0; Query OK, 0 rows affected (0.05 sec)
~]# systemctl restart mysqld
|
Script:
cat >get_restore_files.sh <<"EOF"
set -e
usage() { cat <<"END" usage: ./get_restore_files.sh <pid> <path>
pid : The deleted file open process id. path: The deleted file path.
Use `lsof | grep deleted` to fetch. END }
if [[ -z $1 || -z $2 ]]; then usage exit 1 fi
ls -l /proc/$1/fd | grep deleted \ | grep "$2" \ | awk '{print $9,$11}' \ | while read num file; do echo "cat /proc/$1/fd/$num > $file"; done \ > /tmp/get_$1_restore_files.txt EOF
|