![症状](https://linux22.com/image/659646/%E7%97%87%E7%8A%B6.png)
在由 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。问题暂时解决了。