设备上没有剩余空间 - 是哪个设备?

8
我正在将一个小文件(8.5 Mb)上传到 Flask 测试服务器上。
当文件上传完成后,服务器会报告:
    File "/home/ubuntu/.virtualenvs/eco_app/lib/python2.7/site-packages/wtforms/form.py", 
        line 212, in __call__
    return type.__call__(cls, *args, **kwargs)
    File "/home/ubuntu/.virtualenvs/eco_app/lib/python2.7/site-packages/flask_wtf/form.py", line 49, in __init__
        formdata = request.form
    File "/home/ubuntu/.virtualenvs/eco_app/lib/python2.7/site-packages/werkzeug/local.py", 
        line 338, in __getattr__
    return getattr(self._get_current_object(), name)
    File "/home/ubuntu/.virtualenvs/eco_app/lib/python2.7/site-packages/werkzeug/utils.py", 
         line 71, in __get__
    value = self.func(obj)
    File "/home/ubuntu/.virtualenvs/eco_app/lib/python2.7/site-packages/werkzeug/wrappers.py", 
         line 484, in form
    self._load_form_data()
    File "/home/ubuntu/.virtualenvs/eco_app/lib/python2.7/site-packages/flask/wrappers.py", 
        line 165, in _load_form_data
    RequestBase._load_form_data(self)
    File "/home/ubuntu/.virtualenvs/eco_app/lib/python2.7/site-packages/werkzeug/wrappers.py", 
        line 356, in _load_form_data
    mimetype, content_length, options)
    File "/home/ubuntu/.virtualenvs/eco_app/lib/python2.7/site-packages/werkzeug/formparser.py", 
        line 193, in parse
    content_length, options)
    File "/home/ubuntu/.virtualenvs/eco_app/lib/python2.7/site-packages/werkzeug/formparser.py",
        line 99, in wrapper
    return f(self, stream, *args, **kwargs)
    File "/home/ubuntu/.virtualenvs/eco_app/lib/python2.7/site-packages/werkzeug/formparser.py",
        line 210, in _parse_multipart
    form, files = parser.parse(stream, boundary, content_length)
    File "/home/ubuntu/.virtualenvs/eco_app/lib/python2.7/site-packages/werkzeug/formparser.py", 
        line 520, in parse
    return self.cls(form), self.cls(files)
    File "/home/ubuntu/.virtualenvs/eco_app/lib/python2.7/site-packages/werkzeug/datastructures.py", 
        line 373, in __init__
    for key, value in mapping or ():
    File "/home/ubuntu/.virtualenvs/eco_app/lib/python2.7/site-packages/werkzeug/formparser.py", 
        line 518, in <genexpr>
    form = (p[1] for p in formstream if p[0] == 'form')
    File "/home/ubuntu/.virtualenvs/eco_app/lib/python2.7/site-packages/werkzeug/formparser.py", 
        line 494, in parse_parts
        _write(ell)
IOError: [Errno 28] No space left on device

现在,服务器有很多的可用空间 - 超过3GB。

我查看了Werkzeug github库,试图找到Werkzeug尝试写入的位置,但无法跟踪它。

我还检查了tempfile.gettempdir(),它提供了/tmp作为临时文件目录,但该文件夹几乎是空的,所以我认为这不是创建此问题的位置。

如何找到没有空间的设备?


1
你尝试过运行 df -h 吗? - Ignacio Vazquez-Abrams
是的,这就是我知道有足够的可用空间的方式。 - ABM
4个回答

15

@Tom Hunt的评论是正确的。

这个Unix SE回答解释了发生了什么

为了保护磁盘空间不足,一些守护进程会在根分区磁盘空间不足时自动用内存磁盘"shadow"当前的/tmp目录。不幸的是,一旦有足够的磁盘空间可用,该过程没有自动恢复。

我卸载了/tmp目录并遵循了Nitesh的建议:

sudo umount /tmp
sudo echo 'MINTMPKB=0' > sudo /etc/default/mountoverflowtmp

现在上传功能正常运行。


6
在盲目地应用此解决方案之前,有没有一种检查这是否真的是问题的方法? - aze

7
如果您能够在服务器上获取shell,请尝试输入df -h命令,并查找任何显示100%的Use%或小于您文件大小的Avail的条目。

3
在这种情况下,最有可能的情况是服务器通过某些中间步骤将数据存储在/tmp上。如果可以的话,增加该卷的大小;如果不行,可以更彻底地调查数据路径并看是否有改变它的方法。在一些服务器上,/var/tmp和/tmp是通过绑定挂载、符号链接或其他机制相同的,检查是否存在这种情况。 - Tom Hunt

6
Werkzeug使用tempfile.TemporaryFile()将特定大小的文件存储在临时目录中,但请注意,这些文件为了安全起见是未链接的,在目录中不会列出。确定用于此的目录的正确方法是使用tempfile.gettempdir()。您的/var/tmp目录可能配置有较小的分区。使用df -h检查该分区是否仍有足够的剩余空间。您还需要使用df -i检查可用的inodes。也可能是某个进程(可能是您的进程)持有这样的未链接文件时间过长,而空间尚未归还给操作系统。您可以通过以下方式检查持有已删除文件的进程:
lsof -nP | grep '/var/tmp' | grep '(deleted)'

或者
find /proc/*/fd -ls | grep '/var/tmp' | grep  '(deleted)'

@ABM:还有inode计数吗? - Martijn Pieters
@ABM:这是什么类型的POST请求? - Martijn Pieters
通过系统对话框选择文件并提交表单。 - ABM
@ABM:临时目录是否可能是tmpfs挂载?/etc/fstab中是否有任何限制的显示? - Martijn Pieters
1
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Martijn Pieters
收到。谢谢,@Martijn。 - ABM

4

尝试运行df -i命令,也许没有可用的inode。

编辑:

另一个选项是查找werkzeug pid,将其设置为777,

  • 运行strace -p 777 &> /tmp/strace_log
  • 尝试上传一个文件
  • 停止strace
  • 找到No space left on device消息,它会像这样:write(1, "blah blah ..."..., 57) = -1 ENOSPC (No space left on device)第一个参数是一个文件描述符
  • 向上查找并尝试定位特定的open(... = X系统调用,其中X是在“write”系统调用步骤中将失败的文件描述符

我知道很繁琐,但这就是调试。


inode 使用率为 24%。 - ABM

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接