症状

症状

在由 OVH 运行的 VPS(显然是基于 OpenVZ 的,因为/proc/user_beancounters存在)上,运行的进程相对较少,尝试sudo给我标题中的错误。

以下是一份样本记录:

ekleog@ekleog:~$ sudo echo a
[sudo] password for ekleog:
sudo: unable to create sockets: Cannot allocate memory
ekleog@ekleog:~$ free -h
             total       used       free     shared    buffers     cached
Mem:          8.0G       212M       7.8G         0B         0B        43M
-/+ buffers/cache:       168M       7.8G
Swap:         128M         0B       128M
ekleog@ekleog:~$ sudo echo a
sudo: unable to create sockets: Cannot allocate memory

如您所见,分叉没有问题,因为 shell 分叉运行free,但sudo似乎无法打开套接字。在同一个域中,thunderbird 无法打开 SMTP 连接,但 ssh 继续隧道传输新请求而没有任何问题。

问题源于打开了太多套接字,这一点似乎得到了以下事实的证实:关闭 Thunderbird(它保留了大约 50 个连接来监控我的所有 IMAP 文件夹)后问题消失。此外,重新打开它时,问题没有恢复,所以一定是某处存在资源泄漏?

我目前只有一个用户(我),所以我希望 OVH 的限制不是那么严重。

最后,在“危机”期间,我尝试了跑步netstat(不太习惯使用它,所以我可能错了):

ekleog@ekleog:~$ netstat -a | wc -l
608
ekleog@ekleog:~$ cat /proc/sys/fs/file-max
1627524

对我来说这似乎很奇怪,因为sudo会阻塞。

您知道如何停止这种情况吗?这种情况会时不时出现(大约每隔一天一次),而且非常烦人。

显然问题出在 OpenVZ 设置上,就像/proc/user_beancounters我遇到的numothersock一个巨大的一样failcnt

为了减少依赖于每个单独程序的打开套接字的数量,我会提出单独的问题。

答案1

我将在这个答案中分享我的发现,希望这能对将来的某人有所帮助。如果没有@EEAA 评论中的及时观察,这些发现是不可能的。

事实上,这个限制来自 OpenVZ 软件。根据文档,numothersock你可以看到这个限制:/proc/user_beancounters“Parallels Virtuozzo Containers for Linux 中的 UBC 资源”

数字袜子- 非 TCP 套接字的最大数量(本地套接字、UDP 和其他类型的套接字)。

您可以使用以下方式检查插座数量ss

党卫军用于转储套接字统计信息。

ss -xa | wc -l

要识别哪个进程绑定每个套接字:

sudo ss -xap

就我的具体情况而言,我发现超过 25% 的套接字限制是由于 postfix 造成的,因此我减少了default_process_limit参数/etc/postfix/main.cf(相关问题这里)。

答案2

(同义答案,但添加了一些诊断信息和搜索关键词。)

症状

当前的问题是无法创建新的非 TCP 套接字,这意味着大多数 Unix 域套接字用于系统中的进程间通信。它可能无法始终重现,因为有时会删除一些套接字,从而打开一些选项来创建低于限制的新套接字。

症状不仅限于sudo使用,但会影响服务器上运行并通过套接字连接使用 MySQL 的大多数或所有网站。错误消息如下:

PDOException: SQLSTATE[HY000] [2001] Can't create UNIX socket (12) in […]
PDOException: SQLSTATE[HY000] [2002] Can't connect to local MySQL server 
    through socket '/var/run/mysqld/mysqld.sock' (12) in […]
PHP Warning:  mysqli_connect(): (HY000/2001): Can't create UNIX socket 
    (12) in […]
PHP Warning:  mysqli_connect(): (HY000/2002): Can't connect to local MySQL 
    server through socket '/var/run/mysqld/mysqld.sock' (12) in […]

此外,在登录阶段,通过postfix相应服务器发送和获取电子邮件也可能会失败。错误消息包括:dovecot

mailq: fatal: inet_addr_local[getifaddrs]: getifaddrs: Cannot allocate memory

这些错误的共同点是错误代码 12,这意味着“操作系统错误代码 12:无法分配内存”,按照perror 12[来源]。

解决方案

查看 的输出cat /proc/user_beancounters,它显示了您的 VPS 的 OpenVZ 虚拟化环境限制。您很可能会numothersock在那里看到大量资源限制失败(对我来说超过 10,000 次)。这意味着软件尝试创建套接字,但 OpenVZ 禁止这样做,因为已经存在最大数量的非 TCP 套接字。

要查看计入此资源限制的所有套接字的数量和使用情况numothersock,请查看以下命令生成的输出文件:

ss --processes --all --socket=udp,unix,unix_dgram,unix_stream > results.txt 

在我的例子中,它显示大约 80% 的套接字与 postfix 和 dovecot 进程相关。通过将并发连接数从默认的 100 限制为合理的 10,可以将与 Postfix 相关的套接字减少到大约 10% – 请参阅说明。将该解决方案应用于 postfix ( default_process_limit = 10) 并重新启动后,我使用的套接字数量立即从 ~1020 减少到 ~520。问题暂时解决了。

相关内容