Payments are experiencing issues due to temporary restrictions in Russia. If your payment does not go through, please submit a support request.Our support team is available 24/7 — we are always here to help with hosting and server issues.We are now accepting requests for dedicated server rental and colocation services in our data center.Reminder: we recommend enabling backups for additional data protection.A new VPS/VDS lineup with NVMe storage and improved performance is now available.Maintenance work on some servers has been completed. All services are operating normally.
Article6 min readViews3

File Deleted but Space Not Freed: Diagnostics with lsof

How to find an open deleted file using lsof and verify space reclamation. A real test with two file descriptors: why du decreases immediately, but available space reported by df only grows after the last FD is closed.

Comments 0

Extracted drive connected to a computer via cable
In this article

A large log file was deleted, but almost no free space was added. This is possible in Linux: the file name has already disappeared from the directory, but the process continues to keep it open. Until the last kernel link to such an object is closed, the blocks occupied by it may remain allocated.

Confirm the initial situation

This instruction applies to Linux with the lsof utility installed. A standard user's permissions may restrict visibility of other processes. If you administer the server, run the check with permissions appropriate for your role; otherwise, delegate the task to the responsible specialist.

df -h /var

Record the file system and available space. The path /var is provided as an example: you need the specific volume where the deleted file was located. Without this binding, it is easy to mistake a stranger's temporary file for the cause of the website section filling up.

Find open files without a name

lsof supports filtering by the number of hard links. A value less than one allows you to find open files that have been deleted from the directory tree:

lsof -nP +L1

The -nP parameters disable the conversion of network addresses and ports into names. The output must include the process, its identifier, the descriptor, the device, and the size. If the list is empty, this may indicate the absence of such objects, but it could also mean insufficient permissions or visibility in the current process space.

Do not simply sum every line

One object may sometimes appear under multiple processes or file descriptors. Simply summing all lines will overestimate the reclaimable volume. Match the device and inode, and verify that the object belongs to the correct file system.

The deletion label itself is not a malfunction. Applications can legitimately create temporary files and remove their names while leaving descriptors open. What matters is the file size, the duration of retention, and the correlation with the observed growth in used space.

Staging example: one file and two descriptors

On October 2, 2026, we reproduced this scenario in a separate Linux test environment: kernel 6.18.44, lsof 4.95.0, GNU df/du 9.4, and an overlay file system. A Python process wrote 64 MiB of data to a regular file, executed fsync, and saved two descriptors of the same file via dup. There is no client data or live site here: the example demonstrates the file hold mechanism, not the result of cleaning a specific server.

Before deletion, the name held.log existed in the directory. We then deleted exactly that name while keeping both descriptors open. To verify the target process, we used the command below. The number 73809 is the PID of our test; substitute the found PID on your own server. The -a parameter is important: it combines selection conditions with AND, so only deleted open files of the selected process remain.

lsof -nP -a -p 73809 +L1

COMMAND PID USER FD TYPE DEVICE SIZE NLINK NODE NAME

python3 73809 root 3u REG 0,27 67108864 0 1589490 …/held.log (deleted)

python3 73809 root 4u REG 0,27 67108864 0 1589490 …/held.log (deleted)

In the example, only the long path in NAME is shortened; other values are taken from real output. FD 3u and 4u are different descriptors, opened for reading and writing. REG indicates a regular file, NLINK 0 means no names pointing to it. Matching DEVICE 0,27 and NODE 1589490 show that both lines refer to the same object. The meaning of the fields and the +L1 selection is described in the lsof guide.

To verify the volume, we compared df and du at each step in bytes: df -B1 --output=source,fstype,size,used,avail,target for the test directory's file system and du -B1 -s for the directory itself. Before the file was created, the directory occupied 4096 bytes. This is directory overhead that remains after the file is deleted.

Test state

Open file descriptors

du for directory, bytes

Available per df, bytes

File exists

3,4

67112960

27976044544

File name removed

3,4

4096

27976044544

First FD closed

4

4096

27976044544

Last FD closed

no

4096

28043153408

After removing the name, du stopped accounting for the file, but the free space reported by df did not increase. Closing the first descriptor also did not change df: the second descriptor continued to hold the same object. After the last descriptor was closed by the process, the lines disappeared from its lsof output, and the available space increased by exactly 67108864 bytes, or 64 MiB. This exact sequence is described by unlink(2) in the Linux documentation.

Adding the two SIZE values from the initial output yields 128 MiB. In this test, this represents a double count of a single file: its logical size and allocated blocks were both 64 MiB. On another server, the logical size does not necessarily equal the guaranteed reclaimable space: sparse files, filesystem specifics, and records from other processes affect the result. The estimate is confirmed by running df again on the same volume, not just by the SIZE/OFF column.

Test boundaries: we checked a single ordinary file without memory mapping and closed file descriptors within our own test process. This is not a test of Nginx, database, NFS, snapshots, or quotas behavior. The lsof environment also warned about an unavailable /dev/mqueue; therefore, an empty common list is not considered proof of a complete server check. For our file, the presence and disappearance of the FD were additionally verified via /proc for the selected process. On a production server, output must be read together with warnings and access rights, and the release method must be chosen based on the application documentation.

The next step depends on the application

For example, a web server may continue writing to an old log file after an incorrect rotation. In this case, check the standard log reopening mechanism. For a database, the cause and permissible actions will differ. There is no universal command that safely closes any found file.

Do not terminate the process simply because it appears at the top of the list. It may be handling current requests or transactions. Do not zero out file descriptors via utility paths: such interference can disrupt the application and destroy data. Pass the found identifier, size, and observation time to the service owner.

Result verification

After the standard action selected by the administrator, repeat lsof -nP +L1 and measure free space on the same partition. The disappearance of a specific held object together with an increase in free space confirms the hypothesis much better than the mere fact of restarting the service.

If the space has not changed, return to other causes: snapshots, file system metadata, or new records created during the check. Record the result even if the outcome is negative. This allows the next specialist to continue the diagnosis rather than repeating random deletions and restarts.

Discussion 0

Share your experience and ask questions. Comments without links appear after editorial review.

No comments yet. Start the discussion.