nginx进程数如何配置(nginx进程nobody)
nginx进程nobody
一、由于启动用户和nginx工作用户不一致所致
1.1查看nginx的启动用户,发现是nobody,而为是用root启动的
命令:ps aux | grep "nginx: worker process" | awk'{print $1}'
1.2将nginx.config的user改为和启动用户一致,
命令:vi conf/nginx.conf
二、缺少index.html或者index.php文件,就是配置文件中index index.html index.htm这行中的指定的文件。
1. server {
2. listen 80;
3. server_name localhost;
4. index index.php index.html;
5. root /data/www/;
6. }
如果在/data/www/下面没有index.php,index.html的时候,直接文件,会报403 forbidden。
三、权限问题,如果nginx没有web目录的操作权限,也会出现403错误。
解决办法:修改web目录的读写权限,或者是把nginx的启动用户改成目录的所属用户,重启Nginx即可解决
1. chmod -R 777 /data
2. chmod -R 777 /data/www/
四、SELinux设置为开启状态(enabled)的原因。
4.1、查看当前selinux的状态。
1. /usr/sbin/sestatus
4.2、将SELINUX=enforcing 修改为 SELINUX=disabled 状态。
1. vi /etc/selinux/config
2.
3. #SELINUX=enforcing
4. SELINUX=disabled
4.3、重启生效。reboot。
1. reboot
重启php以及nginx
killall php-fpm && php-fpm &
nginx -s reload
nginx worker进程功能
Nginx 跟 Haproxy 其实他们两个的定位是有所不同的,Nginx的定位是一个server,Haproxy的定位是一个load balancer。
Nginx通过各种plugin module可以支持Load balance的功能,而且性能不弱于haproxy太多,所以总有人拿来将两个东西比较。其实Apache也可以通过相关模块做load balancer,只不过性能差得多而已所以没人用而已。当然了Nginx的LB功能现在是其支柱主打功能而已。
看到有很多答案对于haproxy多进程有误解,这里特别说下,haproxy早就支持多进程模型,但是并不是Nginx的Worker Master结构,而是平等多进程结构,同时也支持REUSE PORT选项,所以在这里Nginx跟Haproxy对于多核利用上都是一样的并没有本质区别。
haproxy从1.8之后,添加了多线程的模式,现在它更推荐的也是这个模型,在一些平台上能够更好的利用多核。而Nginx从来没有多线程模型。而且看起来社区也没打算支持。
Nginx其实基于server的功能来说,是Haproxy不具备的,让Haproxy像一个普通Web server那样回复一个普通的HTTP请求是很难的,不大规模修改源码根本做不到。Haproxy是围绕转发模型设计的,整个流程就是围绕如何快速把一个请求或者回复转发到另一端。并不是像Server一样接受请求然后回复。
但是Nginx作为一个纯粹的LB来说,尤其是针对Web LoadBalancer来说,功能没有haproxy那么细致。Haproxy支持的ACL对象非常广泛,很多情况并不需要脚本辅助就可以完成复杂的功能,而Nginx稍微复杂的LoadBalance功能都需要使用脚本才能完成,这样性能就会差很多。
从功能角度上来讲,Nginx其实功能比Haproxy要多(当然并不都是免费的),因为他的开发社区和定位方向都比Haproxy要大和宽泛。在Nginx上面的各种解决方案也要多的多。比如WAF,haproxy一致都没有比较好的原生解决方案。还有包括最近针对Service Mesh的支持,haproxy都是很难跟得上。
但是基础功能,包括HTTP2,TLS 1.3,Script, SSL/TLS offload,ocsp,SNI preload,其实haproxy最新版本早就已经支持,甚至比Nginx还更早些(HTTP2比较晚,但是现在也支持了)。另外,关于硬件SSL offload支持其实主要是OpenSSL的engine的支持,所以这个大家都差不多,只要兼容最新OpenSSL都没什么问题。
Haproxy的优点其实是转发性能稍高,因为haproxy追求zero copy的forward流程,所以代码都倾向于优化在这一点上。但是这个优势现在被广泛的TLS/SSL应用抹平了,对比0 copy节省的时间来说加解密的消耗的性能占绝大多数,所以haproxy基本上在现在的广泛SSL环境下没有什么优势了。除非你想用纯HTTP,而且还想使用比较复杂的基于HTTP头部的Load Balance功能,那么Haproxy是个好选择,否则只是单纯LB的话,LVS性能其实更更高,毕竟人家在Kernel里面。
从代码层面来说,Nginx的结构化代码和模块化都比Haproxy好太多。Haproxy代码模块化一直是个大问题,内部结构模块化不足,二次开发困难,最近到1.9了才有些改善,但是仍然有很多内部trick的hack和让人发懵的FLAG。相比Nginx做到的彻底的模块化,可以轻易的通过开发自己的模块来改变或者实现相关功能,这个haproxy是不具备的。
从开发社区来说,Nginx也比Haproxy好太多,Haproxy虽然社区历史更久,但是一直都是不愠不火,贡献者因为原作者的严格的控制,一直都很少,再加上没有module开发功能,所以吸引的开发者一直都不多。带来的问题就是版本更新慢,支持的新功能慢。HTTP2的开发完全靠原作者一个人,所以支持进度严重拖后。
这篇文章看起来好像是变成了对haproxy吐槽,但是因为在工作中接触这两个东西实在太多,而且是进行深度二次开发,所以自认为还是有一定的了解的。从目前来看,如果haproxy不能更开放招募更多的贡献者,不能彻底修改架构支持module开发,是无法比拟NGINX的。
另外Haproxy优势一点的就是免费版的功能比Nginx免费版的更实惠。对于小又穷的站点的确是个好处。
nginx的进程
查看进程列表(条件过滤) Linux没运行一个程序就会产生一个进程,那么可以通过查看Nginx进程来判断它是否运行。
直接查看进程pid 这种直接返回pid的方式比较适合跟其他程序结合使用,
nginx nocache
缓存失效是指时间过期了建议重新缓存打开
nginx no such process
subprocess 模块主要用于创建子进程,并连接它们的输入、输出和错误管道,获取它们的返回状态。通俗地说就是通过这个模块,你可以在 Python 的代码里执行操作系统级别的命令,比如ipconfig、du -sh等。
subprocess 模块替代了一些老的模块和函数,比如:os.system、os.spawn*等。
subprocess 过去版本中的call(),check_call()和check_output()已经被run()方法取代了。run()方法为 3.5 版本新增。
大多数情况下,推荐使用run()方法调用子进程,执行操作系统命令。在更高级的使用场景,你还可以使用 Popen 接口。其实run()方法在底层调用的就是 Popen 接口。
subprocess.run
subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, shell=False, timeout=None, check=False, encoding=None, errors=None)
功能:执行 args 参数所表示的命令,等待命令结束,并返回一个 CompletedProcess 类型对象。
注意,run() 方法返回的不是我们想要的执行结果或相关信息,而是一个 CompletedProcess 类型对象。
上面参数表里展示的只是一些常用的,真实情况还有很多。
args:表示要执行的命令,必须是一个字符串,字符串参数列表。
stdin、stdout 和 stderr:子进程的标准输入、输出和错误。其值可以是subprocess.PIPE、subprocess.DEVNULL、一个已经存在的文件描述符、已经打开的文件对象或者 None。
subprocess.PIPE表示为子进程创建新的管道,subprocess.DEVNULL表示使用os.devnull。默认使用的是 None,表示什么都不做。另外,stderr 可以合并到 stdout 里一起输出。
timeout:设置命令超时时间。如果命令执行时间超时,子进程将被杀死,并弹出TimeoutExpired异常。
check:如果该参数设置为 True,并且进程退出状态码不是 0,则弹出CalledProcessError异常。
encoding:如果指定了该参数,则 stdin、stdout 和 stderr 可以接收字符串数据,并以该编码方式编码。否则只接收 bytes 类型的数据。
shell:如果该参数为 True,将通过操作系统的 shell 执行指定的命令。
看下面的例子:
>>> subprocess.run(["ls", "-l"]) # 没有对输出进行捕获 CompletedProcess(args=['ls', '-l'], returncode=0) >>> subprocess.run("exit 1", shell=True, check=True) Traceback (most recent call last): ... subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1 >>> subprocess.run(["ls", "-l", "/dev/null"], stdout=subprocess.PIPE) CompletedProcess(args=['ls', '-l', '/dev/null'], returncode=0, stdout=b'crw-rw-rw- 1 root root 1, 3 Jan 23 16:23 /dev/null\n') >>> subprocess.run("python --version", stdout=subprocess.PIPE) CompletedProcess(args='python --version', returncode=0, stdout=b'Python 3.6.1\r\n') >>>s= subprocess.run("ipconfig", stdout=subprocess.PIPE) # 捕获输出 >>>print(s.stdout.decode("GBK"))
subprocess.CompletedProcess
run() 方法的返回值,表示一个进程结束了。CompletedProcess类有下面这些属性:
args 启动进程的参数,通常是个列表或字符串。
returncode 进程结束状态返回码。0表示成功状态。
stdout 获取子进程的 stdout。通常为 bytes 类型序列,None 表示没有捕获值。如果你在调用 run() 方法时,设置了参数stderr=subprocess.STDOUT,则错误信息会和 stdout 一起输出,此时 stderr 的值是 None。
stderr 获取子进程的错误信息。通常为 bytes 类型序列,None 表示没有捕获值。
check_returncode() 用于检查返回码。如果返回状态码不为零,弹出CalledProcessError异常。
subprocess.DEVNULL
一个特殊值,用于传递给 stdout、stdin 和 stderr 参数。表示使用os.devnull作为参数值。
subprocess.PIPE
管道,可传递给 stdout、stdin 和 stderr 参数。
subprocess.STDOUT
特殊值,可传递给 stderr 参数,表示 stdout 和 stderr 合并输出。
args 与 shell
args 参数可以接收一个类似'du -sh'的字符串,也可以传递一个类似['du', '-sh']的字符串分割列表。shell 参数默认为 False,设置为 True 的时候表示使用操作系统的 shell 执行命令。
下面我们来看一下两者的组合结果。
In [14]: subprocess.run('du -sh') --------------------------------------------------------------------------- FileNotFoundError Traceback (most recent call last) ...... FileNotFoundError: [Errno 2] No such file or directory: 'du -sh' In [15]: subprocess.run('du -sh', shell=True) 175M . Out[15]: CompletedProcess(args='du -sh', returncode=0)
可见,在 Linux 环境下,当 args 是个字符串时,必须指定 shell=True。成功执行后,返回一个CompletedProcess 对象。
In [16]: subprocess.run(['du', '-sh'], shell=True) .....大量的数据 4 ./文档 179100 . Out[16]: CompletedProcess(args=['du', '-sh'], returncode=0) In [17]: subprocess.run(['du', '-sh']) 175M . Out[17]: CompletedProcess(args=['du', '-sh'], returncode=0)
可见,当args是一个['du', '-sh']列表,并且shell=True的时候,参数被忽略了,只执行不带参数的du命令。
总结:Linux 中,当 args 是个字符串是,请设置 shell=True,当 args 是个列表的时候,shell 保持默认的 False。
获取执行结果
run() 方法返回的是一个 CompletedProcess 类型对象,不能直接获取我们通常想要的结果。要获取命令执行的结果或者信息,在调用 run() 方法的时候,请指定 stdout=subprocess.PIPE。
>>> ret = subprocess.run('dir', shell=True) >>> ret CompletedProcess(args='dir', returncode=0) >>> ret = subprocess.run('dir', shell=True, stdout=subprocess.PIPE) >>> ret CompletedProcess(args='dir', returncode=0, stdout=b' \xc7\xfd\xb6\xaf\xc6\xf7 ......') >>> ret.stdout b' \xc7\xfd\xb6\xaf\xc6\xf7 C \xd6\xd0\xb5\xc4\xbe\xed\xca\xc7 ......'
从例子中我们可以看到,如果不设置stdout=subprocess.PIPE,那么在返回值CompletedProcess(args='dir', returncode=0)中不会包含 stdout 属性。反之,则会将结果以 bytes 类型保存在 ret.stdout 属性中。
交互式输入
并不是所有的操作系统命令都像‘dir’或者‘ipconfig’那样单纯地返回执行结果,还有很多像‘python’这种交互式的命令,你要输入点什么,然后它返回执行的结果。使用run()方法怎么向stdin里输入?
这样?
import subprocess ret = subprocess.run("python", stdin=subprocess.PIPE, stdout=subprocess.PIPE,shell=True) ret.stdin = "print('haha')" # 错误的用法 print(ret)
这样是不行的,ret作为一个CompletedProcess对象,根本没有stdin属性。那怎么办呢?前面说了,run()方法的stdin参数可以接收一个文件句柄。比如在一个1.txt文件中写入print('i like Python')。然后参考下面的使用方法:
import subprocess fd = open("d:\\1.txt") ret = subprocess.run("python", stdin=fd, stdout=subprocess.PIPE,shell=True) print(ret.stdout) fd.close()
这样做,虽然可以达到目的,但是很不方便,也不是以代码驱动的方式。这个时候,我们可以使用Popen类。
subprocess.Popen()
用法和参数与run()方法基本类同,但是它的返回值是一个Popen对象,而不是CompletedProcess对象。
>>> ret = subprocess.Popen("dir", shell=True) >>> type(ret) <class 'subprocess.Popen'> >>> ret <subprocess.Popen object at 0x0000000002B17668>
Popen对象的stdin、stdout和stderr是三个文件句柄,可以像文件那样进行读写操作。
>>>s = subprocess.Popen("ipconfig", stdout=subprocess.PIPE, shell=True) >>>print(s.stdout.read().decode("GBK"))
要实现前面的‘python’命令功能,可以按下面的例子操作:
import subprocess s = subprocess.Popen("python", stdout=subprocess.PIPE, stdin=subprocess.PIPE, shell=True) s.stdin.write(b"import os\n") s.stdin.write(b"print(os.environ)") s.stdin.close() out = s.stdout.read().decode("GBK") s.stdout.close() print(out)
通过s.stdin.write()可以输入数据,而s.stdout.read()则能输出数据。
本网站文章仅供交流学习 ,不作为商用, 版权归属原作者,部分文章推送时未能及时与原作者取得联系,若来源标注错误或侵犯到您的权益烦请告知,我们将立即删除.