一个 django 开发的后端,因为是学校里的学长组织的项目,所以给了一个他们实验室里的一台 windows 作为服务器,平时远程上去用。最近有一个接口account/check
经常卡死,具体情况就是
curl
命令不会断开,所以会一直卡死其他接口都正常
我上服务器上排查了一下,发现了一个天坑
cmd 窗口在选中模式下,account/check
会卡死,其他接口正常但是终端没有输出( django 处于调试或者开发模式,每请求一次都打印在终端)
去网上查了一下,找到了这个 https://stackoverflow.com/questions/33883530/why-is-my-command-prompt-freezing-on-windows-10
虽然不知道为什么只有account/check
会出现这个问题,不过可以确定这个选择模式真是一个大聪明
网上找到的解决方案是:关闭 Quick Edit Mode
但我觉得这还是不太方便。如果这种大聪明功能一多,岂不是拿到一台新的 windows 机器还要设置一堆东西?我觉得可能是使用终端的方式错了,v 友们有没有遇到这个问题?都是怎么解决的?
1
Worldispow 2023-12-04 14:08:39 +08:00 via Android
你程序咋启动的,没跑在后台吗?
即便是 linux ,程序也要跑到后台啊。。。 |
2
vituralfuture OP 补充一下,上面的链接的内容就是,当 cmd 窗口处于选中模式下时,进程会被 halt (原文是这个词,我猜是阻塞的意思),直到进程尝试往终端打印。
我测试出的情况就是,当窗口处于选择模式下,终端没有任何的输出。然后随便点击一下窗口,退出选择模式,终端 会一口气输出之前被卡住的所有信息。 我在项目里是负责前端的,给后端同学反映这个问题,他并没有发现问题的原因,只是点击了一下窗口发现莫名其妙好了,然后 django 输出了一个错误`Broken Pipe`,然后他以为是这个原因。很显然这不是根本原因,因为浏览器超时自动断开了连接,然而这个接口恢复执行后拿到了一个另一方已经断开连接的管道,自然就会出现`Broken Pipe` |
3
vituralfuture OP @Worldispow 负责后端的同学打开了一个 cmd 窗口,然后执行`python manage.py runserver 0.0.0.0:8080`
我对 windows 也不太了解,不过刚刚看后端的同学似乎在尝试用 windows 的 IIS 。 如果我用 linux 的话,我应该是`nohup python xxxx &` |
4
cwcc 2023-12-04 14:20:13 +08:00
这个问题应该是 conhost 本身的默认配置导致的。因为有时候确实会不小心点一下窗口内,然后出现个白色的光标,程序就被卡住了。最简单的办法就是不用 conhost 作为持久化程序运行的本体,使用 WT 或者别的守护方式,服务什么的也行。
|
5
vituralfuture OP @vituralfuture #3 本科生参加的很多项目基本都是灌水,菜,见谅
|
6
maggch97 2023-12-04 14:32:18 +08:00 9
遇到不能理解的问题先想想为什么会这样设计,而不是在什么都不会的时候这也吐槽那也吐槽。
|
7
Hellert 2023-12-04 14:35:05 +08:00
这种控制台的最好是用 WinSW 把所有开机启动的程序安装为服务,它同时会将控制台输出保存为文件,方便你查看。
我印象中 conhost 还有一个问题,就是如果你按住鼠标拖动控制台窗口,你的程序也会暂停运行。具体我记不清了,现在现在基本用 Windows Terminal 了。 |
8
zenghx 2023-12-04 14:56:02 +08:00 5
这不是 cmd 祖传的设定吗
|
10
kenvix 2023-12-04 15:01:06 +08:00 2
这怎么就天坑了?控制台程序进入选择模式时,控制台输出流阻塞以便于你选取,这是预期行为。你应该思考下为什么你打个 log 都能把整个程序阻塞住?
|
11
ShadowPower 2023-12-04 15:06:05 +08:00
Windows 曾经还有另一个天坑,Windows XP 有,和这个相似。
如果拖动窗口或者右键单击窗口标题栏,弹出菜单,整个窗口都会被暂停。 这玩意可以用来卡游戏 bug…… |
12
8153 2023-12-04 15:09:01 +08:00
祖传特性,不要惊讶。cmd 开的东西,不要选中,不然可能阻塞了
|
13
8153 2023-12-04 15:09:39 +08:00
这个时候一直按照 enter 就行了
|
14
wetalk 2023-12-04 15:12:44 +08:00
祖传特性,cmd 下启动 run 脚本一直是这样
|
15
kenvix 2023-12-04 15:21:40 +08:00
@vituralfuture 那你直接跟后端骂他写的什么垃圾东西,打 log 能卡住 web 服务,正常人干不出来这事。今天能因为 conhost 阻塞导致整个程序卡死,明天就能因为 log 打太快导致业务缓慢
|
16
murmur 2023-12-04 15:24:04 +08:00
选择的时候标题会变
选择:命令提示符 到底是天坑还是你看的不仔细 |
17
ak47iej 2023-12-04 15:24:34 +08:00
这不是 windows cmd 祖传特性吗....
|
18
ShadowPower 2023-12-04 15:26:41 +08:00
对了,Windows 的 cmd 一直以来都不是用来兼容 Unix 的东西,而是兼容 DOS 用的。
不少设计来自 IBM ,一直传承下来。 在标准 IBM PC 键盘上其实还有个 Pause Break 按钮,按一下就可以让程序暂停下来。 如果想要一个和 Unix 兼容的终端,过去有 MinTTY ,现在有 Windows Terminal 。 |
19
cc666 2023-12-04 15:27:16 +08:00
windows cmd 很早之前就这样了,以至于这是成为了一个 feature ,能实现一些疑难的调试工作
|
20
leeyuzhe 2023-12-04 15:27:27 +08:00
一直这样啊,这叫什么天坑。阻塞输出流方便选择不是一个很正常的逻辑么。。
|
21
aLazarus 2023-12-04 15:32:20 +08:00
@ShadowPower #11 听上去似乎可以在 dnf 上卡技能?
|
22
tool2d 2023-12-04 15:47:19 +08:00
我也遇到过,也是远程开发控制台程序。
结论是,不要用控制台输出就可以了,改成日志输出。 |
23
adoal 2023-12-04 15:51:10 +08:00 1
顺便说一下,如果是 Linux 下正经的生产环境里跑的业务系统,并不建议用交互登录的用户 nohup & 挂后台。至少要写个 systemd unit 或者别的服务管理器下的配置,用不能交互登录的服务专用用户来运行。
|
24
ShadowPower 2023-12-04 15:52:29 +08:00
@aLazarus 我记忆里有两个:
QQ 堂冒险模式:通关或者死亡之前先用这个方式卡半分钟以上,会导致游戏重复结算通关,获得的经验翻倍。卡越久翻倍越多,卡太久会掉线。 DNF 决斗场:被人浮空连招,拖拽窗口可以把对方的连招断掉。 后来 Windows 7 上不管用了。 |
25
ysc3839 2023-12-04 16:04:51 +08:00 via Android
@ShadowPower 这个问题是游戏自己的问题,直到 Win11 也存在。这是因为游戏把自己的逻辑和界面的消息循环放在了一起,打开标题栏菜单时,系统会进入另一个循环,游戏自己的循环是阻塞住的,也就导致游戏自己的逻辑无法运行。正确做法是把游戏自己的逻辑放到单独的线程中执行。
|
26
ysc3839 2023-12-04 16:19:25 +08:00 via Android
@kenvix @ShadowPower
Unix 终端也有类似特性,按 Ctrl+S 可以暂停输出。不过和 Windows 控制台不同,Unix 终端暂停输出后不是立刻阻塞,还有缓冲区可以写一段内容才会阻塞。 Windows 控制台立刻阻塞应该是因为设置文字颜色格式等是通过 API 调用实现的,不阻塞的话就会出现程序以为输出了内容,但实际没输出,然后程序又去调用 API 设置了颜色,此时再恢复输出,之前没输出的那部分就会用当前的颜色出现。 比如程序预期输出白色的 abc 和红色的 def ,实际的执行流程是输出 abc ,调用 API 设置颜色为红色,再输出 def 。假如输出 abc 之前用户暂停了输出,但是程序那里又没阻塞,程序执行完以上流程后,当前的文字颜色是红色,但是 abcdef 都还没输出,用户恢复输出后,就会导致 abcdef 都变成红色。 |
27
aLazarus 2023-12-04 16:19:29 +08:00
@ShadowPower #23 狂战士卡大吸也可以我记得
|
28
ysc3839 2023-12-04 16:25:56 +08:00 via Android
@ysc3839 另外从实际来看,Windows 控制台其实是在滥用“暂停输出”这个功能。因为从原理上讲完全可以实现选择文本时滚动条固定在当前位置,新的内容继续往后输出。Windows 控制台好像是不支持滚动条位置固定继续输出,有新内容都会滚动到最底下,于是就投机取巧直接暂停输出。如果换了其他终端比如 Windows Terminal ,就没有这样的问题。
|
29
flyup 2023-12-04 16:31:14 +08:00
|
30
Chancel 2023-12-04 16:32:13 +08:00
@adoal 是的
在`Linux`下跑后台一般也不用`nohup`,简单的`supervisor`,复杂的`systemd` Windows 下可以看看计划任务(类似 nohup ),`nssm`(这个类似`supervisor`) |
31
tomczhen 2023-12-04 16:39:15 +08:00 via Android
不管啥平台下面也不推荐用 python run server 来跑就是了。
|
32
chackchackGO 2023-12-04 17:01:11 +08:00
@Chancel 在`Linux`下跑后台***一般也不用***`nohup`?
|
33
boris1993Jr 2023-12-04 17:01:41 +08:00 via iPhone
@ShadowPower #11 直到 Windows 11 都有这个特性。我用这个特性卡 GTA5 的单人房间。
|
34
PrinceofInj 2023-12-04 19:21:07 +08:00
这都是祖传特性了,知道了 3 的话其实挺好用的,有时候输出内容过多,随便一点鼠标阻塞起来看起来比较方便。但是碰上不知道的真的就是天坑了,新的 wt.exe 没有这个行为了,还有点怪不习惯的
|
35
hez2010 2023-12-04 19:35:42 +08:00
你可以在系统设置的开发者模式下把默认终端从 cmd 改成 Windows terminal ,这样就会用上新的 conhost 没有这种问题了。
|
36
adoal 2023-12-04 20:43:59 +08:00
@chackchackGO 后台跑数据处理等一次性的、属于当前用户的计算任务还是适合用 nohup 的。这里说的是长期运行(理论上你不去停止它它就永远运行)的服务。
|
37
aisk 2023-12-04 20:55:01 +08:00
过几天你又会发现一个 Python 的“天坑”,如果一个接口没返回,这个时候整个服务器不就接收响应其他请求了,大家都只能排队慢慢等🐶
|
38
512357301 2023-12-04 21:52:29 +08:00 via Android
python 是跨平台的,还不如用 linux 跑,顺便装个 docker ,还能解决多版本和后台问题
|
39
hxy100 2023-12-04 23:02:20 +08:00
不需要终端交互的场景下,可以选择隐藏运行 CMD 窗口的方式来运行你的程序,即可规避问题。
---- 比如常见的 VBS 脚本实现: Set Wsh=CreateObject("Wscript.Shell") Wsh.run "D:\scripts\app_start.bat",vbHide |
40
opengps 2023-12-04 23:20:41 +08:00
这个功能一直有,选中了就是挂起暂停的效果,做命令行调试时候非常好用,但这个并不是给生产环境准备的,所以生产环境关掉即可
|
41
MrKrabs 2023-12-05 00:18:29 +08:00
就是鼠标不小心点一下就暂停这么弱智的哦
|
42
siweipancc 2023-12-05 07:59:54 +08:00 via iPhone
设计出来就不是给你这么用的……
|
43
Chancel 2023-12-05 11:37:36 +08:00 1
@chackchackGO 看程序类型了,nohup 的写法不是太友好
比如我需要记录程序的输出,那么 nohup 的写法就复杂了一点,如果希望切割日志,那么`nohup`就会很复杂了 就我的使用经验而言,写一个`supervisor`的配置单是最简便的 如果程序很简单,只需单纯的需要在后台跑,那我觉得`tmux`也比`nohup`要强 |
44
chackchackGO 2023-12-05 15:13:46 +08:00
@Chancel 我这个新手一直就是用的 tmux. nohup 确实感觉相比之下很不方便和难记语法.
但是看到很多文章和老手用 nohup, 所以有些自我怀疑... |
45
lsk569937453 2023-12-05 17:10:03 +08:00
被楼上喷的我都不敢在生产环境用 nohup 了。
例:比如我需要记录程序的输出,那么 nohup 的写法就复杂了一点,如果希望切割日志,那么`nohup`就会很复杂了 答:有没有可能根本不会在代码里写 System.out.println 或将日志输出到 stdout ,而是直接将日志写到文件,用日志工具自动切割。 |
46
sanzrolee 2023-12-05 17:55:05 +08:00
建议你用 Supervisor 跑 Python 服务,用 nohup ,终端就是会卡住的,我通常都是关闭窗口就算了。用 supervisor 就不会出现这个问题,还能监测服务的运行状况。
|
47
adoal 2023-12-06 19:00:33 +08:00
@lsk569937453 对的,比如用 logrotate 做切割,这玩意不但可以配置各种切割规则,而且还可以指定切割前执行任意外部操作做预处理、切割后执行任意外部工作做善后。最好是你的程序支持收到 HUP 信号或者别的触发条件时 reopen 日志文件,这样切割的事完全不用放在自己的程序中处理,只要闷头写就行了。
|
48
Chancel 2023-12-07 16:49:15 +08:00
@lsk569937453 首先我没喷`nohup`,强调了是个人体验,`nohup`存在即合理
其次,在代码中配置输出到文件是入门编程的常识,比`nohup`还简单多了,python 的`logging`、golang 的`logrus`,C#的`log4net`等等,一个了解`systemd`的人写代码用`print`是不可思议的 但日志库跟`nohup`有关系?因为有这些库做日志切割,所以`nohup`配置日志不方便就不存在了? `nohup`就比`systemd`和`supervisor`更好了,更遑论`nohup`不支持一键重启,自动重启,运行用户配置,系统环境单独定义等诸多功能,这些只有`systemd`和`supervisor`这类守护进程支持 开发和运维工作是分开的情况下,多个项目组各自定义自己的文件输出在各自的目录下有着各自的切割规则,运维更合适收集程序的 CLI 输出并按照实际服务器资源情况进行切割是更合理的 我的个人技术体验路线是:screen-nohup-supervisord-systemd 拧螺丝只要口对的上都行,但使得顺不顺手是另外一回事 |