Python OSError Não há espaço disponível no dispositivo

0

EDITAR:

Acontece que é uma colisão de hash do sistema de arquivos ext4.

Estou escrevendo muitos arquivos em uma pasta, sem subdiretórios, mas depois de 2,8 milhões de arquivos, este erro aparece:

with open(bottleneck_path, 'w') as save_file:
OSError: [Errno 28] No space left on device: '/home/user/path/redacted'

Eu verifiquei o tamanho do nome do arquivo, que tem apenas 149 caracteres. O tamanho do arquivo é de cerca de 18K.

Meu sistema operacional é o Linux.

df -i:

Filesystem                               Inodes   IUsed    IFree IUse% Mounted on
udev                                    4106923     544  4106379    1% /dev
tmpfs                                   4113022     836  4112186    1% /run
/dev/sda2                              28401664 9008557 19393107   32% /
tmpfs                                   4113022      40  4112982    1% /dev/shm
tmpfs                                   4113022       5  4113017    1% /run/lock
tmpfs                                   4113022      16  4113006    1% /sys/fs/cgroup
/dev/sda1                                     0       0        0     - /boot/efi

df -T

Filesystem                             Type      1K-blocks       Used  Available Use% Mounted on
udev                                   devtmpfs   16427692          0   16427692   0% /dev
tmpfs                                  tmpfs       3290420      22136    3268284   1% /run
/dev/sda2                              ext4      447088512  355325584   69029056  84% /
tmpfs                                  tmpfs      16452088      82448   16369640   1% /dev/shm
tmpfs                                  tmpfs          5120          4       5116   1% /run/lock
tmpfs                                  tmpfs      16452088          0   16452088   0% /sys/fs/cgroup
/dev/sda1                              vfat         523248       3684     519564   1% /boot/efi

du -sh.

56G

ls | wc -l

2892084

Pelo que entendi, o ext4 deve ser capaz de lidar com isso muito bem.

EDITAR:

tune2fs -l / dev / sda2

tune2fs 1.42.13 (17-May-2015)
Filesystem volume name:   <none>
Last mounted on:          /
Filesystem UUID:          cd620466-1f88-400b-acf5-457a9c9544cf
Filesystem magic number:  0xEF53
Filesystem revision #:    1 (dynamic)
Filesystem features:      has_journal ext_attr resize_inode dir_index filetype needs_recovery extent flex_bg sparse_super large_file huge_file uninit_bg dir_nlink extra_isize
Filesystem flags:         signed_directory_hash 
Default mount options:    user_xattr acl
Filesystem state:         clean
Errors behavior:          Continue
Filesystem OS type:       Linux
Inode count:              28401664
Block count:              113587456
Reserved block count:     5679372
Free blocks:              82864623
Free inodes:              25755495
First block:              0
Block size:               4096
Fragment size:            4096
Reserved GDT blocks:      996
Blocks per group:         32768
Fragments per group:      32768
Inodes per group:         8192
Inode blocks per group:   512
Flex block group size:    16
Filesystem created:       Wed Mar  1 15:14:22 2017
Last mount time:          Mon Mar 27 13:20:00 2017
Last write time:          Mon Mar 27 13:20:00 2017
Mount count:              35
Maximum mount count:      -1
Last checked:             Wed Mar  1 15:14:22 2017
Check interval:           0 (<none>)
Lifetime writes:          1813 GB
Reserved blocks uid:      0 (user root)
Reserved blocks gid:      0 (group root)
First inode:              11
Inode size:           256
Required extra isize:     28
Desired extra isize:      28
Journal inode:            8
First orphan inode:       1312056
Default directory hash:   half_md4
Directory Hash Seed:      e186507d-32b5-49c0-8ce1-09bf2a75d816
Journal backup:           inode blocks

Usando

touch /home/user/path/redacted/somefile_1

gera um erro, mas a mesma estrutura de nome de arquivo com um nome diferente funciona bem. por exemplo:

touch /home/user/path/redacted/somefile_2

EDIT: Acontece que é uma colisão de hash do sistema de arquivos ext4.

    
por Wesley 29.03.2017 / 08:55

2 respostas

0

Você pode testar se realmente está relacionado ao sistema operacional?

Como você não colocou seu código de script python na questão, aqui está um script que cria arquivos de 3mio com nomes de arquivos de 150 caracteres cada. No meu fim isso está funcionando bem sem erros.

After running the script successfully :

  • Move this question to stackoverflow to get help with your code.

if the script fails (ie. after 2.8 mio files):

  • Move this question to unix/linux to get linux OS related help.

Você precisa definir o target_dir para um diretório vazio existente

#!/usr/bin/env python3
# vim:fenc=utf-8 ts=4 sw=4 sts=4 et:
# -*- coding: utf-8 -*-
import sys

target_dir = "/home/user/sandbox/test/"
no_files = 3000000

sys.stdout.write("start")


def pretty_no(nr, l):
    #  create filename string
    res = str(nr)
    l -= len(res)
    return "0"*l+res

for i in range(0, no_files):
    fn = target_dir+pretty_no(i, 150)
    f = open(fn, "w")
    f.write("hello world!")
    f.close()
    sys.stdout.write("\r%s files" % i)

print("\ndone")
    
por 29.03.2017 / 11:23
0

O problema não é que existam colisões de hash - a htree pode suportar colisões muito bem. O problema é que atualmente o ext4 suporta apenas uma árvore de hash profunda de dois níveis. Existem patches para aumentar esse limite:

link

Note que o desempenho quando você tem dois milhões de diretórios não será ótimo. Eu recomendo usar uma hierarquia de diretórios multi-nível --- por exemplo, / home / t / y / tytso em vez de ter gazllions de diretórios em / home.

    
por 30.03.2017 / 00:44