http.server在子进程中运行不正常,请帮忙看看

lj267 2020-12-18 05:20:06
http.server做的httpserver 在主进程中运行正常,放到multiprocessing的子进程中就不能正常运行。查看日志发现卡在self.send_response(200) 这一句。放到子进程中运行是为了方便结束这个进程。以下是代码
#!/usr/bin/env python
#--coding:utf-8--
from multiprocessing import Process
from http.server import BaseHTTPRequestHandler, HTTPServer
import os
from os import path
from urllib.parse import urlparse
import asyncio
import websockets
import logging
import logging.handlers
import datetime
logger = logging.getLogger('mylogger')
logger.setLevel(logging.DEBUG)

rf_handler = logging.handlers.TimedRotatingFileHandler('all.log', when='midnight', interval=1, backupCount=7, atTime=datetime.time(0, 0, 0, 0))
rf_handler.setFormatter(logging.Formatter("%(asctime)s - %(message)s"))

f_handler = logging.FileHandler('error.log')
f_handler.setLevel(logging.ERROR)
f_handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(filename)s[:%(lineno)d] - %(message)s"))

logger.addHandler(rf_handler)
logger.addHandler(f_handler)
os.environ['path']=os.environ['path']+';'+os.path.abspath('')

def websocketservice():
# 接收客户端消息并处理,这里只是简单把客户端发来的返回回去
async def recv_msg(websocket):
while True:
recv_text = await websocket.recv()
response_text = f"your submit context: {recv_text}"
await websocket.send(response_text)

# 服务器端主逻辑
# websocket和path是该函数被回调时自动传过来的,不需要自己传
async def main_logic(websocket, path):
await recv_msg(websocket)

# 把ip换成自己本地的ip
start_server = websockets.serve(main_logic, '127.0.0.1', 999)
# 如果要给被回调的main_logic传递自定义参数,可使用以下形式
# 一、修改回调形式
# import functools
# start_server = websockets.serve(functools.partial(main_logic, other_param="test_value"), '10.10.6.91', 5678)
# 修改被回调函数定义,增加相应参数
# async def main_logic(websocket, path, other_param)
print("webserver started")
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

def httpservice():
curdir = path.dirname(path.realpath(__file__))
sep = '/'

# MIME-TYPE
mimedic = [
('.html', 'text/html'),
('.htm', 'text/html'),
('.js', 'application/javascript'),
('.css', 'text/css'),
('.json', 'application/json'),
('.png', 'image/png'),
('.jpg', 'image/jpeg'),
('.gif', 'image/gif'),
('.txt', 'text/plain'),
('.avi', 'video/x-msvideo'),
]

class myHTTPServer_RequestHandler(BaseHTTPRequestHandler):
# GET
def do_GET(self):
sendReply = False
querypath = urlparse(self.path)
filepath, query = querypath.path, querypath.query

if filepath.endswith('/'):
filepath += 'index.html'
filename, fileext = path.splitext(filepath)
for e in mimedic:
if e[0] == fileext:
mimetype = e[1]
sendReply = True
if sendReply == True:
try:
logger.debug(sendReply)
with open(path.realpath(curdir + sep + filepath),'rb') as f:
content = f.read()
logger.debug('0')
self.send_response(200) #这一句过不了,日志只能打印到0,1不能打印出来
logger.debug('1')
self.send_header('Content-type',mimetype)
logger.debug('2')
self.end_headers()
logger.debug('3')
self.wfile.write(content)
logger.debug("4")
except IOError:
self.send_error(404,'File Not Found: %s' % self.path)
logger.debug("失败")
port = 8080
print('starting server, port', port)
# Server settings
server_address = ('',port)
httpd = HTTPServer(server_address, myHTTPServer_RequestHandler)
logger.debug('running server...')
httpd.serve_forever()

if __name__ == '__main__':
p1=Process(target=httpservice)
p1.daemon=True
p1.start()
print("进程1")
p2=Process(target=websocketservice)
p2.daemon=True
p2.start()
print("进程2")


...全文
38 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复
1.计算文件数和目录数
下面的语句可以帮你计算有多少个文件和多少个目录
# ls -l * |grep "^-"|wc -l ---- to count files
# ls -l * |grep "^d"|wc -l ----- to count dir
还可以将以上的语句变成script或做个alias


2.显示文件的类型
用命令file可以使你知道某个文件究竟是ELF格式的可执行文件,还是shell script文件或是其他的什么格式,例如:#file startx


3.用dd命令转换数据格式
你大概知道dd命令是用来拷贝数据的。特别是用来制作启动盘。但是dd也能用于数据转换。在 "endian" 结构的系统上,导出Ingres数据库的内容时,代码会发生奇怪的转换,它把:“The cat in the hat”转变成了“hT eac tnit ehh ta”,把数据恢复过来的办法就是采用dd命令:
dd if=randys_bad_data of=marcs_good_data conv=swab
最后部分 "conv=swab" 告诉dd采取 "swap bytes" 方式转换。
同样的,如果要吧EBCDIC格式的数据转换为ASCII格式就可以采用如下命令:
dd if=ebcdic_file of=ascii_file conv=ascii
dd的man帮助显示出有不少于10种转换,仔细看看,下次遇到同样问题时,就可以用dd来帮忙了。


4.禁止使用ping命令
ping命令是计算机之间进行相互检测线路完好的一个应用程序,计算机间交流数据的传输没有经过任何的加密处理,因此我们在用ping命令来检测某一个服务器时,可能在因特网上存在某个非法分子,通过专门的黑客程序把在网络线路上传输的信息途窃取,并利用偷盗过来的信息对指定的服务器或者系统进行攻击,为此我们有必要在Linux系统禁止使用Linux命令。在linux里,如果要想使ping没反应也就是用来忽略icmp包,因此我们可以在Linux的命令行输入如下命令:echo 1 > /proc/sys/net/ipv4/icmp_echo_igore_all ;
如果想恢复使用ping命令,就可以输入:echo 0 > /proc/sys/net/ipv4/icmp_echo_igore_all命令。


5.显示Win9X分区里的长文件名
  如果你发现Win9X分区里的长文件命不能显示,可以重新用vfat方式来mount。对于启动时就mount的分区可以修改文件/etc/fstab,将里面的msdos字样改为vfat。如果无法用vfat mount, 则要重新编译一下核心,加入对vfat的支持。

6.Linux里的Norton Commander
  在提示符下键入命令mc后你就会看到一个与Norton Commander很相似的界面,实际上功能也很相似甚至更强大,比如可以直接对.tar.gz压缩包里的文件进行操作(有点像ZipMagic)。


7.启动后直接进入X
  编辑/etc/inittab文件,把id:3:initdefautl改为id:4:initdefautl。不过搜索路径可能会有些问题, 关机时你得直接进入/sbin里去执行shutdown。


8.巧妙使用“Tab”键
大家知道在Linux字符界面输入命令时,有时需要输入很多字符,如果经常这样逐个地输入字符,比较麻烦。假设键入的字符足以确定该目录下一个惟一的文件时,我们只需按键盘上的“Tab”键就可以自动补齐该文件名的剩下部分,例如要把目录/ccc下的文件“ddddddd-1.2.3.tar.gz”解包时,当我们在命令行键入到“tar xvfz /ccc/d”时,如果该文件是该目录下惟一以“d”打头的文件的话就可以直接按下“Tab”键,这时命令会被自动补齐为:tar xvfz /ccc/ddddddd-1.2.3.tar.gz ,从而提高了输入效率


9.强行退出X
  有时候在X里由于程序出错鼠标键盘都不起作用,这时候不用着急,因为在Linux下几乎不会像在Win95里那样恶性死机, 你只须键入Ctrl Alt BackSpace键就可以回到字符界面下了。


10.重装Win9x后lilo失效无法启动Linux
  只须先用软盘启动Linux然后运行一次lilo即可。对于RedHat可以用命令mkbootdisk来制作启动盘,例如:
mkbootdisk--devices/dev/fd0 2.0.34-1。其2.0.34-1是/lib/modules下的一个目录。


11.去掉引导区内的lilo信息
  安装lilo后如果硬盘数量或分区情况有改变的话将导致硬盘不能启动,这时只须用软盘启动dos再运行 fdisk/mbr即可。(用这个方法还可清除任何引导区病毒哦)


12.查看文件的方法
如果你只想看文件的前5行,可以使用head命令,如: head -5 /etc/passwd 如果你想查看文件的后10行,可以使用tail命令,如: tail -10 /etc/passwd 你知道怎么查看文件间一段吗?你可以使用sed命令 如: sed -n 5,10p /etc/passwd 这样你就可以只查看文件的第5行到第10行。


13.消除Xwindows下的死机现象
我们可以用两个常用的方法来消除这种现象:第一,用键盘上的复合键“Ctrl Alt Backspace”来关闭当前正在运行的任务;第二,首先按住键盘上的“Ctrl Alt F2”复合键,让系统切换到另一个操作台,然后登录到系统,再执行“#ps -ax/grep startx”命令,这将会列出你的Xserver的进程标识,接着在命令行输入如下命令就能消除Xwindows下的死机现象:#kill -9 PID_Number,最后通过“Alt F1”复合键返回到原来的平台。


14.用当前路径作提示符
  对bash来说,在.bashrc里加一行:PS1="?$PWD\?$"
  对tcsh来说,在.tcshrc里加一行:set prompt="%/>"


15.快速关闭Linux系统
最新版本的Linux/UNIX系统借鉴了大型机的技术,采用了抗掉电的日志式文件系统,可以自动跟踪保存用户数据,自动同步刷新文件系统,用户完全可以随手关闭电源,从而达到快速关闭系统的目的。


16.修复Linux下超级用户的密码
如果超级用户将密码忘记,就无法进入系统,也无法管理和使用系统。本来这种事不太可能发生,但是在一些Linux单机使用者,尤其是初学者,却是比较容易发生。一般的解决方法就是格式化硬盘来重新安装系统,但这有点儿小题大作了。准备好bootdisk和rootdisk两张软盘,从软驱启动,启动到root盘并出现shell提示符。将Linux根目录分区mount至/mnt目录,比如你的Linux在硬盘第一分区,就在命令行输入mount/dev/hda1 /mnt,然后进入mnt目录,将其的etc/passwd文件改名,输入mv /mnt/etc/passwd /mnt/etc/passwd.bak就可以了;接着使用命令cp /etc/passwd /mnt/etc/passwd将软盘上的/etc/passwd文件复制到硬盘的etc目录下,这样重新由硬盘启动,登录时就不会询问超级密码;最后使用mv/etc/passwd.bak passwd命令将passwd文件改回,再运行passwd命令重新设定密码就可以了。


17.一次处理一整个目录
  Linux/UNIX的很多常用命令如rm,cp等都有一个参数“-r”,是递归的意思,命令里加了参数“-r”就可以对目标目录及其下所有子目录进行操作,如:
rm -rf /test(f是“force”意为强行),该命令完全删除根目录下的子目录test,作用类似于dos下的deltree,当然使用这个命令时要特别小心。再如:cp -r/test/test1有类似dos下xcopy/s的作用。


18.列出除了某些类型文件的当前目录所有文件
使用Ksh,用ls !(*.Z)可以显示所有文件,除了*.Z文件。 这个命令在一个目录里有许多种类型的文件的时候很有用。


19.制作LILO启动盘
只要将/etc/lilo.conf的boot=/dev/hdxx改为/dev/fd0,然后执行lilo -v将LILO写入磁盘,LILO启动盘就做好了。注意,在启动盘做完后,再将boot=/dev/fd0改回原来的设置,并再次执行lilo -v写回主引导记录或Super Block。


20.使用nohup命令
如果你想进程在你退出系统后还能执行,可以使用NOHUP命令 如: % nohup tar -cf /dev/tape /home & 你退出后再重新登录的话,使用ps命令可以看到进程还在执行。


37,719

社区成员

发帖
与我相关
我的任务
社区描述
JavaScript,VBScript,AngleScript,ActionScript,Shell,Perl,Ruby,Lua,Tcl,Scala,MaxScript 等脚本语言交流。
社区管理员
  • 脚本语言(Perl/Python)社区
  • IT.BOB
加入社区
  • 近7日
  • 近30日
  • 至今

试试用AI创作助手写篇文章吧