【问题标题】:IOError: No space left on device - which device?IOError:设备上没有剩余空间 - 哪个设备?
【发布时间】:2015-04-19 20:26:02
【问题描述】:

我正在将一个小文件 (8.5 Mb) 上传到烧瓶测试服务器。

文件上传完成后,服务器报告:

    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 repo,试图找到 Werkzeug 试图写入的位置,但无法找到它。

我还检查了tempfile.gettempdir(),它提供了 /var/tmp 作为临时文件目录,但这个文件夹实际上是空的,所以我认为这不是造成问题的位置。

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

【问题讨论】:

  • 你试过运行df -h了吗?
  • 是的。这就是我知道有大量可用空间的原因。

标签: python flask werkzeug


【解决方案1】:

@Tom Hunt 的评论是正确的。

这个 unix SE 答案解释了what happened

为了防止磁盘空间不足,如果根分区的磁盘空间不足,一些守护程序会自动使用 ram 磁盘“隐藏”当前的 /tmp/ 目录。遗憾的是,一旦有足够的磁盘空间再次可用,该过程就不会自动恢复。

我卸载了 /tmp 目录并按照 Nitesh 的建议:

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

现在上传工作正常。

【讨论】:

  • 在盲目应用此解决方案之前,有没有办法检查这确实是问题所在?
【解决方案2】:

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

【讨论】:

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

Werkzeug 使用 tempfile.TemporaryFile() 在您的临时目录中存储超过一定大小的文件,但请考虑到这些文件未链接以确保安全。您不会在目录中看到它们。 tempfile.gettempdir() 是确定用于此的目录的正确方法。

您的/var/tmp 目录可能配置为较小的分区。检查df -h 以查看该分区是否还有足够的空间。您还需要使用df -i 来检查免费的inode

也可能是某个进程(可能是您的)在此类未链接文件上挂起的时间过长,并且空间尚未返回给操作系统。您可以使用以下方法检查保留已删除文件的进程:

lsof -nP | grep '/var/tmp' | grep '(deleted)'

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

【讨论】:

  • @ABM: inode 计数?
  • @ABM:这是什么 POST?
  • 发布包含通过系统对话选择的文件的表单。
  • @ABM: 临时目录可能是 tmpfs 挂载吗? /etc/fstab 中的任何内容以显示其可能受到的限制?
  • @ABM:无论如何,我假设您没有更改 Flask / Werkzeug 的默认 POST 表单解析器基础结构并在此处更改了 default_stream_factory 钩子。您可以尝试查看可以在 Python 交互式提示中创建多大的 tempfile.TemporaryFile() 对象,但此时这是服务器问题,而不是 Python 问题。
【解决方案4】:

试试df -i,可能没有空闲的inode。

编辑:

另一种选择,找到werkzeug pid,设为777,

  • 运行strace -p 777 &amp;&gt; /tmp/strace_log
  • 尝试上传文件
  • 停止跟踪
  • 找到No space left on device这个消息,会像 write(1, "blah blah ..."..., 57) = -1 ENOSPC (No space left on device) 第一个要写入的参数是文件描述符
  • 上去尝试定位特定的open(... = X syscall,X 是一个文件描述符,在“write”系统调用步骤中会失败

很麻烦,我知道,但那是调试。

【讨论】:

  • inode 利用率为 24%
猜你喜欢
  • 1970-01-01
  • 2017-04-06
  • 2017-09-20
  • 2012-12-29
  • 2012-01-14
  • 2012-05-15
  • 2018-11-22
  • 2015-07-21
  • 2020-12-16
相关资源
最近更新 更多