我在 Debian Web 服务器上使用 Apache2 的 PHP 会话似乎mod_php
随机失败,提示没有空间来写入它们:
sudo tail -60 /var/log/apache2/error.log
[Fri Jan 30 15:55:35 2015] [error] [client xxx.xxx.xxx.xxx] PHP Warning: session_start() [<a href='function.session-start'>function.session-start</a>]: open(/tmp/sess_555555555555555555, O_RDWR) failed: No space left on device (28) in /path/to-first-session-use/core/bootstrap.php on line 18
当我尝试:
ls /tmp
它会永远挂起,所以这很糟糕。
但是当我检查可用空间并检查 inode 使用情况是否合理时......
$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 150G 121G 22G 85% /
tmpfs 2.0G 0 2.0G 0% /lib/init/rw
udev 10M 16K 10M 1% /dev
tmpfs 2.0G 4.0K 2.0G 1% /dev/shm
$ df -i
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/sda1 19922944 11143605 8779339 56% /
tmpfs 513524 4 513520 1% /lib/init/rw
udev 513524 135 513389 1% /dev
tmpfs 513524 3 513521 1% /dev/shm
这些数字看起来不错。当然,85% 比我想要的要多,但不是 99% 或什么的。
我怀疑这是由于 5 年没有重启机器以及创建了大量小文件而导致的问题,但我获得的 inode 信息与此有点矛盾。我应该在哪里进行调查?
编辑:
ls -l /
drwxrwxrwt 4 root root 692M Feb 1 11:09 tmp/
drwxr-xr-x 10 root root 4.0K Jan 1 2013 usr/
drwxr-xr-x 14 root root 4.0K Oct 7 2010 var/
...etc
答案1
可能是/tmp/
目录本身充满了未清理的陈旧 PHP 会话;这意味着问题的根源可能与/tmp/
目录本身无关。如果是这种情况,我会删除所有/tmp/sess_*
文件。首先,列出所有文件,sess_*
如下所示:
ls -la /tmp/sess_*
或者你可以像这样获得计数wc
:
ls -la /tmp/sess_* | wc -l
现在,一旦您确认那里有大量文件,请继续运行此命令来删除这些/tmp/sess_*
文件:
sudo rm -rf /tmp/sess_*
并且短暂的会话文件将被吹走。
但是另一种蛮力——但相对安全——的解决这个问题的方法是删除/tmp
目录本身,重新创建/tmp
目录并重新启动服务器。
由于该/tmp
目录基本上是缓存材料的编码暂存区,因此其中不应该包含任何有效内容。因此,我最好的建议是运行以下命令来删除并重建目录/tmp
。
rm -rf /tmp && mkdir /tmp/ && chown root:root /tmp && chmod 1777 /tmp
现在,该行基本上是由 连接的 shell 命令列表,这些命令&&
将首先删除/tmp
、重新创建/tmp
、将 的所有权更改/tmp
回root:root
,然后为/tmp
目录设置适当的权限。如果您愿意,可以逐个运行每个命令,如果您觉得这样做更安全的话。
sudo rm -rf /tmp
sudo mkdir /tmp
sudo chown root:root /tmp
sudo chmod 1777 /tmp
完成后,我建议重启服务器。一切应该会恢复正常。
答案2
有时损坏的文件系统会产生类似的影响 - 例如当目录 /tmp 损坏时。或者 - 当文件太多时。
对于“快速”修复:
mv /tmp /tmp.xxx
mkdir /tmp
chmod a+rwxt /tmp
如果有帮助,请尝试重新启动系统并 fsck 根文件系统。如果没问题,只需删除 /tmp.xxx 目录。
另一种可能性是 - 当 /tmp 是“其他”分区或 tmpfs(在 linux vservers 上看到)时 - 但 df 不会显示它(因为 df 从 /etc/mtab 文件获取分区列表,有时不正确)。尝试使用以下命令直接检查 tmp 上的磁盘空间:
df /tmp
df -i /tmp
其他选项通常有助于会话 - 它使用其他会话机制。如果您有很多临时会话,不需要非常持久 - 我建议您使用 memcache 来存储会话。配置非常简单 - 您必须安装 php-memcache、memcached,然后在 php.conf 中配置:
session.save_handler = memcache
session.save_path="tcp://server:port?persistent=1&weight=1&timeout=1&retry_interval=15"
然后 - 会话将存储在 memcache 中,直到达到定义的大小。超过该大小 - 最旧的会话将被自动删除。
答案3
对我来说,改变 fs.inotify.max_user_watches 就可以了。
root@grostruc:/# service ssh restart
Error: No space left on device
root@grostruc:/# sysctl fs.inotify.max_user_watches
fs.inotify.max_user_watches = 65536
root@grostruc:/# sysctl fs.inotify.max_user_watches=262144
fs.inotify.max_user_watches = 262144
root@grostruc:/# service ssh restart
修复 /etc/sysctl.conf 中更改的值