每次重新启动 NGINX 时,都会留下两个信号量数组。鉴于信号量是一种有限的共享资源——服务器总是缓慢地向配额限制失败的方向倾斜。
重启后留下的信号量归“4294967295”(-1)所有,权限为 600。除非重启,否则它们不会通过传统方式被删除,例如:
$ sudo ipcrm -s 5111851
cannot remove id 5111851 (Operation not permitted)
以前有人处理过这个问题吗?显然,找到一种方法来通过 NGINX 配置阻止孤立数组是非常棒的,但除此之外,我完全赞成修改 init.d 脚本来清理遗留的信号量数组,我似乎无法使用标准 ipc* 实用程序删除它们。
除了重新启动之外,有没有其他方法可以删除分配给不存在用户的信号量数组?
$ sudo ipcs -st
------ Semaphore Operation/Change Times --------
semid owner last-op last-changed
...
9568370 4294967295 Not set Fri Feb 13 03:38:02 2015 <-- logrotate
9601139 4294967295 Not set Fri Feb 13 03:38:02 2015
9633908 4294967295 Not set Sat Feb 14 03:31:06 2015
9666677 4294967295 Not set Sat Feb 14 03:31:06 2015
9764982 4294967295 Not set Sun Feb 15 03:47:06 2015
9797751 4294967295 Not set Sun Feb 15 03:47:06 2015
9830520 4294967295 Not set Mon Feb 16 03:37:02 2015
9863289 4294967295 Not set Mon Feb 16 03:37:02 2015
9994362 4294967295 Not set Mon Feb 16 11:34:08 2015 <-- manual restart
10027131 4294967295 Not set Mon Feb 16 11:34:08 2015
10125436 4294967295 Not set Mon Feb 16 13:47:25 2015
10158205 4294967295 Not set Mon Feb 16 13:47:25 2015
10256510 4294967295 Not set Mon Feb 16 13:52:47 2015
10289279 4294967295 Not set Mon Feb 16 13:52:47 2015
$ nginx -V
nginx version: nginx/1.6.2
TLS SNI support enabled
configure arguments:
--prefix=/usr/share/nginx
--sbin-path=/usr/sbin/nginx
--conf-path=/etc/nginx/nginx.conf
--error-log-path=/var/log/nginx/error.log
--http-log-path=/var/log/nginx/access.log
--http-client-body-temp-path=/var/lib/nginx/tmp/client_body
--http-proxy-temp-path=/var/lib/nginx/tmp/proxy
--http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi
--http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi
--http-scgi-temp-path=/var/lib/nginx/tmp/scgi
--pid-path=/var/run/nginx.pid
--lock-path=/var/lock/subsys/nginx
--user=nginx
--group=nginx
--with-file-aio
--with-ipv6
--with-http_ssl_module
--with-http_spdy_module
--with-http_realip_module
--with-http_addition_module
--with-http_xslt_module
--with-http_image_filter_module
--with-http_geoip_module
--with-http_sub_module
--with-http_dav_module
--with-http_flv_module
--with-http_mp4_module
--with-http_gunzip_module
--with-http_gzip_static_module
--with-http_random_index_module
--with-http_secure_link_module
--with-http_degradation_module
--with-http_stub_status_module
--with-http_perl_module
--with-mail
--with-mail_ssl_module
--with-pcre --with-debug
--add-module=/builddir/build/BUILD/nginx-1.6.2/modsecurity-2.8.0/nginx/modsecurity
--add-module=/builddir/build/BUILD/nginx-1.6.2/ngx_cache_purge-2.1
--with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector
--param=ssp-buffer-size=4 -m64 -mtune=generic'
--with-ld-opt=-Wl,-E
CentOS 6,NGINX 1.6.2。
答案1
您可能需要升级到 nginx 1.8 - 这为我解决了信号量泄漏问题(至少乍一看如此)
答案2
我没有找到问题的根源,但这里有一个解决方法。
在/etc/init.d/nginx,找到 stop() 函数并在之前添加以下行return $retval
:
ipcs -s | grep "4294967295" | awk ' { print $2 } ' | xargs -I % ipcrm -s %
通过此更改,sudo service nginx restart
现在应该清除旧的信号量数组。
首先,无法删除信号量怎么办?这与 sudo 权限不在整个命令中级联有关。切换到 root 不会遇到此类问题。
[user@example ~]$ sudo ipcs -s | grep "4294967295" | awk ' { print $2 } ' | xargs -I % ipcrm -s %
ipcrm: permission denied for id (819214)
ipcrm: permission denied for id (851983)
ipcrm: permission denied for id (1114130)
[user@example ~]$ sudo -i
[root@example ~]# ipcs -s | grep "4294967295" | awk ' { print $2 } ' | xargs -I % ipcrm -s %
[root@example ~]#