
# fork失败，无法创建新的线程怎么办？
#### 问题描述
Linux操作系统的ECS，在执行命令或者日志打印时，出现如下报错信息：
错误信息1：
```
root@localhost:~# free -g
            total       used       free     shared     buffers   cached 
Mem:         94          43         51        0           0        0
Swap:        19          0         19
root@localhost:~# uname -a
-bash: fork: Cannot allocate memory
```
错误信息2：
```
xxxxsshd2[23985]: fatal: setresuid 20054: Resource temporarily unavailable
xxxxsshd2[28377]: Disconnecting: fork failed: Resource temporarily unavailable
xxxxsshd2[4484]: Disconnecting: fork failed: Resource temporarily unavailable
```
错误信息3：
```
[root@ecs-xxxx ~]$ sudo docker info
runtime/cgo: pthread_create failed: Resource temporarily unavailable
SIGABRT: abort
```
#### 根因分析
通常情况，出现上述错误由于创建线程失败，可能原因是ECS系统内存不足，系统当前的线程数达到了配置的最大值。
#### 处理方法
1. 登录管理控制台。
2. 通过ECS的主机监控功能的"内存使用率"指标，查看云服务器内存使用情况确认云服务器内存情况，详细操作，请参见[查看监控指标](https://support.huaweicloud.com/usermanual-ecs/zh-cn_topic_0027371530.html) 。
   - 如果内存不足，建议扩容内存或者优化内存的使用，扩容内存可参考[变更规格通用操作](https://support.huaweicloud.com/usermanual-ecs/zh-cn_topic_0013771092.html)。
   
   - 否则，执行步骤[3]。
    
3. 以root用户登录云服务器，执行以下命令，排查message和dmesg日志。
   **dmesg -T**
   **cat /var/log/messages**
   - 如果出现如[图1]所示的cgroup相关报错打印，执行步骤[8]。
   
   - 否则，执行步骤[4]。
     图1日志报错   
     ![](https://support.huaweicloud.com/trouble-ecs/zh-cn_image_0000001741678076.png "点击放大") 
     
4. 执行以下命令，查看当前系统线程总数。
   **ps -efL \| wc -l**
   
5. 执行以下命令，将得到的两个值与步骤[4]查到的当前系统线程总数进行对比。
   **sysctl -a \| grep pid_max**
   **sysctl -a \| grep threads-max**
   - 如果当前系统线程总数接近这两个值其中一个，那么就需要对这pid_max、threads-max这两个参数进行调优。调优步骤请参考[调优pid_max、threads-max参数]。
   
   - 否则，执行步骤[6]。
    

6. 执行以下命令，确定报错进程的pid。
   **ps -ef \| grep 报错进程名**
   
7. 执行以下命令，根据得到的pid检查该进程的limits配置： **cat /proc/pid/limits**
   图2确定进程limits配置   
   ![](https://support.huaweicloud.com/trouble-ecs/zh-cn_image_0000001788896469.png "点击放大")
   - 查看Max processes行，如果当前用户创建的所有线程数接近该值，那么需要对limits参数进行调优，调优步骤请参考[调优limits参数]。
   
   - 否则，执行步骤[8]。
    
8. 执行以下命令，根据日志的cgroup报错可以得到pid_max、pids.current参数值。
   **cat /sys/fs/cgroup/pids/拼接日志中报错目录/pids.max**
   **cat /sys/fs/cgroup/pids/拼接日志中报错目录/pids.current**
   图3cgroup目录   
   ![](https://support.huaweicloud.com/trouble-ecs/zh-cn_image_0000001788934273.png "点击放大")
   示例如下：
   1. 执行以下命令，根据进程的pid查找对应的cgroup目录。 **cat /proc/pid/cgroup**
      图4根据pid查找对应的cgroup目录   
      ![](https://support.huaweicloud.com/trouble-ecs/zh-cn_image_0000001790747761.png "点击放大")
      返回结果中的pids行为"/user.slice/user-0.slice/session-5.scope/"，与/sys/fs/cgroup/pids/拼接，可得进程对应的cgroup目录为"/sys/fs/cgroup/pids/user.slice/user-0.slice/session-5.scope/"。
      
   
   2. 执行以下命令，根据得到的cgroup目录获取pid_max、pids.current参数值。 **cat /sys/fs/cgroup/pids/user.slice/user-0.slice/session-5.scope/pids.max**
      **cat /sys/fs/cgroup/pids/user.slice/user-0.slice/session-5.scope/pids.current**
      - 如果pids.current接近pids.max，那么需要对cgroup参数进行调优，调优步骤请参考[调优cgroup参数]。
      
      - 否则，请提交工单联系技术支持处理。
       
    
 
#### 相关命令
- 调优pid_max、threads-max参数
  1. 由于不同操作系统发行版默认参数不一致，执行以下命令，查询当前配置参数。 **sysctl -a \| grep pid_max**
     **sysctl -a \| grep threads-max**
     
  
  2. 执行以下命令，修改pid_max、threads-max参数。 **echo 'kernel.pid_max = 4194304' \>\> /etc/sysctl.conf**
     **echo 'kernel.threads-max = 4194304' \>\> /etc/sysctl.conf**
     
  
  3. 执行以下命令，使配置生效。 **sysctl -p**
     
   
- 调优limits参数
  1. 以启动报错业务进程的用户登录云服务器，执行以下命令查询当前配置参数。 **ulimit -u**
     
  
  2. 执行以下命令，根据业务需求和当前值评估，配置合适的nproc上限。
     以root用户nproc配置100000为例：
     **echo 'root soft nproc 100000' \>\> /etc/security/limits.conf**
     **echo 'root hard nproc 100000' \>\> /etc/security/limits.conf**
     
  
  3. 重新登录云服务器，执行以下命令确认配置是否生效。 **ulimit -u**
     - 回显值如果是步骤[2]配置的值，表示配置已经生效，在该session重启业务进程即可。
     
     - 否则，请提交工单联系技术支持处理。
      
   
- 调优cgroup参数
  - 临时修改方案： 执行以下命令，以将相关cgroup临时修改上限为最大为例，修改当前超出限制的cgroup目录。
    **echo max \> /sys/fs/cgroup/pids/user.slice/user-0.slice/session-25.scope/pids.max**
    
  
  - 永久修改方案： 执行以下命令，以将相关cgroup设置到无穷大为例，修改当前超出限制的cgroup目录。
    该值可以根据需要调整，修改完成后需要重启云服务器使配置生效。
    **echo DefaultTasksMax=infinity \>\>/etc/systemd/system.conf**
    **echo DefaultTasksMax=infinity \>\>/etc/systemd/user.conf**
    **echo UserTasksMax=infinity \>\>/etc/systemd/logind.conf**
    
   
 
