V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
vituralfuture
V2EX  ›  Windows

吐槽一下 windows 的终端的一个天坑

  •  
  •   vituralfuture · 358 天前 · 6388 次点击
    这是一个创建于 358 天前的主题,其中的信息可能已经有所发展或是发生改变。

    一个 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 友们有没有遇到这个问题?都是怎么解决的?

    48 条回复    2023-12-07 16:49:15 +08:00
    Worldispow
        1
    Worldispow  
       358 天前 via Android
    你程序咋启动的,没跑在后台吗?
    即便是 linux ,程序也要跑到后台啊。。。
    vituralfuture
        2
    vituralfuture  
    OP
       358 天前
    补充一下,上面的链接的内容就是,当 cmd 窗口处于选中模式下时,进程会被 halt (原文是这个词,我猜是阻塞的意思),直到进程尝试往终端打印。
    我测试出的情况就是,当窗口处于选择模式下,终端没有任何的输出。然后随便点击一下窗口,退出选择模式,终端 会一口气输出之前被卡住的所有信息。
    我在项目里是负责前端的,给后端同学反映这个问题,他并没有发现问题的原因,只是点击了一下窗口发现莫名其妙好了,然后 django 输出了一个错误`Broken Pipe`,然后他以为是这个原因。很显然这不是根本原因,因为浏览器超时自动断开了连接,然而这个接口恢复执行后拿到了一个另一方已经断开连接的管道,自然就会出现`Broken Pipe`
    vituralfuture
        3
    vituralfuture  
    OP
       358 天前
    @Worldispow 负责后端的同学打开了一个 cmd 窗口,然后执行`python manage.py runserver 0.0.0.0:8080`

    我对 windows 也不太了解,不过刚刚看后端的同学似乎在尝试用 windows 的 IIS 。

    如果我用 linux 的话,我应该是`nohup python xxxx &`
    cwcc
        4
    cwcc  
       358 天前
    这个问题应该是 conhost 本身的默认配置导致的。因为有时候确实会不小心点一下窗口内,然后出现个白色的光标,程序就被卡住了。最简单的办法就是不用 conhost 作为持久化程序运行的本体,使用 WT 或者别的守护方式,服务什么的也行。
    vituralfuture
        5
    vituralfuture  
    OP
       358 天前
    @vituralfuture #3 本科生参加的很多项目基本都是灌水,菜,见谅
    maggch97
        6
    maggch97  
       358 天前   ❤️ 9
    遇到不能理解的问题先想想为什么会这样设计,而不是在什么都不会的时候这也吐槽那也吐槽。
    Hellert
        7
    Hellert  
       358 天前
    这种控制台的最好是用 WinSW 把所有开机启动的程序安装为服务,它同时会将控制台输出保存为文件,方便你查看。

    我印象中 conhost 还有一个问题,就是如果你按住鼠标拖动控制台窗口,你的程序也会暂停运行。具体我记不清了,现在现在基本用 Windows Terminal 了。
    zenghx
        8
    zenghx  
       358 天前   ❤️ 5
    这不是 cmd 祖传的设定吗
    flyqie
        9
    flyqie  
       358 天前 via Android
    @zenghx #8

    确实。。。很祖传了
    kenvix
        10
    kenvix  
       358 天前   ❤️ 2
    这怎么就天坑了?控制台程序进入选择模式时,控制台输出流阻塞以便于你选取,这是预期行为。你应该思考下为什么你打个 log 都能把整个程序阻塞住?
    ShadowPower
        11
    ShadowPower  
       358 天前
    Windows 曾经还有另一个天坑,Windows XP 有,和这个相似。
    如果拖动窗口或者右键单击窗口标题栏,弹出菜单,整个窗口都会被暂停。

    这玩意可以用来卡游戏 bug……
    8153
        12
    8153  
       358 天前
    祖传特性,不要惊讶。cmd 开的东西,不要选中,不然可能阻塞了
    8153
        13
    8153  
       358 天前
    这个时候一直按照 enter 就行了
    wetalk
        14
    wetalk  
       357 天前
    祖传特性,cmd 下启动 run 脚本一直是这样
    kenvix
        15
    kenvix  
       357 天前
    @vituralfuture 那你直接跟后端骂他写的什么垃圾东西,打 log 能卡住 web 服务,正常人干不出来这事。今天能因为 conhost 阻塞导致整个程序卡死,明天就能因为 log 打太快导致业务缓慢
    murmur
        16
    murmur  
       357 天前
    选择的时候标题会变

    选择:命令提示符

    到底是天坑还是你看的不仔细
    ak47iej
        17
    ak47iej  
       357 天前
    这不是 windows cmd 祖传特性吗....
    ShadowPower
        18
    ShadowPower  
       357 天前
    对了,Windows 的 cmd 一直以来都不是用来兼容 Unix 的东西,而是兼容 DOS 用的。
    不少设计来自 IBM ,一直传承下来。

    在标准 IBM PC 键盘上其实还有个 Pause Break 按钮,按一下就可以让程序暂停下来。

    如果想要一个和 Unix 兼容的终端,过去有 MinTTY ,现在有 Windows Terminal 。
    cc666
        19
    cc666  
       357 天前
    windows cmd 很早之前就这样了,以至于这是成为了一个 feature ,能实现一些疑难的调试工作
    leeyuzhe
        20
    leeyuzhe  
       357 天前
    一直这样啊,这叫什么天坑。阻塞输出流方便选择不是一个很正常的逻辑么。。
    aLazarus
        21
    aLazarus  
       357 天前
    @ShadowPower #11 听上去似乎可以在 dnf 上卡技能?
    tool2d
        22
    tool2d  
       357 天前
    我也遇到过,也是远程开发控制台程序。

    结论是,不要用控制台输出就可以了,改成日志输出。
    adoal
        23
    adoal  
       357 天前   ❤️ 1
    顺便说一下,如果是 Linux 下正经的生产环境里跑的业务系统,并不建议用交互登录的用户 nohup & 挂后台。至少要写个 systemd unit 或者别的服务管理器下的配置,用不能交互登录的服务专用用户来运行。
    ShadowPower
        24
    ShadowPower  
       357 天前
    @aLazarus 我记忆里有两个:
    QQ 堂冒险模式:通关或者死亡之前先用这个方式卡半分钟以上,会导致游戏重复结算通关,获得的经验翻倍。卡越久翻倍越多,卡太久会掉线。
    DNF 决斗场:被人浮空连招,拖拽窗口可以把对方的连招断掉。

    后来 Windows 7 上不管用了。
    ysc3839
        25
    ysc3839  
       357 天前 via Android
    @ShadowPower 这个问题是游戏自己的问题,直到 Win11 也存在。这是因为游戏把自己的逻辑和界面的消息循环放在了一起,打开标题栏菜单时,系统会进入另一个循环,游戏自己的循环是阻塞住的,也就导致游戏自己的逻辑无法运行。正确做法是把游戏自己的逻辑放到单独的线程中执行。
    ysc3839
        26
    ysc3839  
       357 天前 via Android
    @kenvix @ShadowPower
    Unix 终端也有类似特性,按 Ctrl+S 可以暂停输出。不过和 Windows 控制台不同,Unix 终端暂停输出后不是立刻阻塞,还有缓冲区可以写一段内容才会阻塞。
    Windows 控制台立刻阻塞应该是因为设置文字颜色格式等是通过 API 调用实现的,不阻塞的话就会出现程序以为输出了内容,但实际没输出,然后程序又去调用 API 设置了颜色,此时再恢复输出,之前没输出的那部分就会用当前的颜色出现。
    比如程序预期输出白色的 abc 和红色的 def ,实际的执行流程是输出 abc ,调用 API 设置颜色为红色,再输出 def 。假如输出 abc 之前用户暂停了输出,但是程序那里又没阻塞,程序执行完以上流程后,当前的文字颜色是红色,但是 abcdef 都还没输出,用户恢复输出后,就会导致 abcdef 都变成红色。
    aLazarus
        27
    aLazarus  
       357 天前
    @ShadowPower #23 狂战士卡大吸也可以我记得
    ysc3839
        28
    ysc3839  
       357 天前 via Android
    @ysc3839 另外从实际来看,Windows 控制台其实是在滥用“暂停输出”这个功能。因为从原理上讲完全可以实现选择文本时滚动条固定在当前位置,新的内容继续往后输出。Windows 控制台好像是不支持滚动条位置固定继续输出,有新内容都会滚动到最底下,于是就投机取巧直接暂停输出。如果换了其他终端比如 Windows Terminal ,就没有这样的问题。
    flyup
        29
    flyup  
       357 天前
    我遇到过,解决方法: https://www.cnblogs.com/qy1234/p/12613887.html
    Chancel
        30
    Chancel  
       357 天前
    @adoal 是的

    在`Linux`下跑后台一般也不用`nohup`,简单的`supervisor`,复杂的`systemd`

    Windows 下可以看看计划任务(类似 nohup ),`nssm`(这个类似`supervisor`)
    tomczhen
        31
    tomczhen  
       357 天前 via Android
    不管啥平台下面也不推荐用 python run server 来跑就是了。
    chackchackGO
        32
    chackchackGO  
       357 天前
    @Chancel 在`Linux`下跑后台***一般也不用***`nohup`?
    boris1993Jr
        33
    boris1993Jr  
       357 天前 via iPhone
    @ShadowPower #11 直到 Windows 11 都有这个特性。我用这个特性卡 GTA5 的单人房间。
    PrinceofInj
        34
    PrinceofInj  
       357 天前
    这都是祖传特性了,知道了 3 的话其实挺好用的,有时候输出内容过多,随便一点鼠标阻塞起来看起来比较方便。但是碰上不知道的真的就是天坑了,新的 wt.exe 没有这个行为了,还有点怪不习惯的
    hez2010
        35
    hez2010  
       357 天前
    你可以在系统设置的开发者模式下把默认终端从 cmd 改成 Windows terminal ,这样就会用上新的 conhost 没有这种问题了。
    adoal
        36
    adoal  
       357 天前
    @chackchackGO 后台跑数据处理等一次性的、属于当前用户的计算任务还是适合用 nohup 的。这里说的是长期运行(理论上你不去停止它它就永远运行)的服务。
    aisk
        37
    aisk  
       357 天前
    过几天你又会发现一个 Python 的“天坑”,如果一个接口没返回,这个时候整个服务器不就接收响应其他请求了,大家都只能排队慢慢等🐶
    512357301
        38
    512357301  
       357 天前 via Android
    python 是跨平台的,还不如用 linux 跑,顺便装个 docker ,还能解决多版本和后台问题
    hxy100
        39
    hxy100  
       357 天前
    不需要终端交互的场景下,可以选择隐藏运行 CMD 窗口的方式来运行你的程序,即可规避问题。

    ----
    比如常见的 VBS 脚本实现:

    Set Wsh=CreateObject("Wscript.Shell")
    Wsh.run "D:\scripts\app_start.bat",vbHide
    opengps
        40
    opengps  
       357 天前
    这个功能一直有,选中了就是挂起暂停的效果,做命令行调试时候非常好用,但这个并不是给生产环境准备的,所以生产环境关掉即可
    MrKrabs
        41
    MrKrabs  
       357 天前
    就是鼠标不小心点一下就暂停这么弱智的哦
    siweipancc
        42
    siweipancc  
       357 天前 via iPhone
    设计出来就不是给你这么用的……
    Chancel
        43
    Chancel  
       357 天前   ❤️ 1
    @chackchackGO 看程序类型了,nohup 的写法不是太友好

    比如我需要记录程序的输出,那么 nohup 的写法就复杂了一点,如果希望切割日志,那么`nohup`就会很复杂了

    就我的使用经验而言,写一个`supervisor`的配置单是最简便的

    如果程序很简单,只需单纯的需要在后台跑,那我觉得`tmux`也比`nohup`要强
    chackchackGO
        44
    chackchackGO  
       356 天前
    @Chancel 我这个新手一直就是用的 tmux. nohup 确实感觉相比之下很不方便和难记语法.
    但是看到很多文章和老手用 nohup, 所以有些自我怀疑...
    lsk569937453
        45
    lsk569937453  
       356 天前
    被楼上喷的我都不敢在生产环境用 nohup 了。

    例:比如我需要记录程序的输出,那么 nohup 的写法就复杂了一点,如果希望切割日志,那么`nohup`就会很复杂了
    答:有没有可能根本不会在代码里写 System.out.println 或将日志输出到 stdout ,而是直接将日志写到文件,用日志工具自动切割。
    sanzrolee
        46
    sanzrolee  
       356 天前
    建议你用 Supervisor 跑 Python 服务,用 nohup ,终端就是会卡住的,我通常都是关闭窗口就算了。用 supervisor 就不会出现这个问题,还能监测服务的运行状况。
    adoal
        47
    adoal  
       355 天前
    @lsk569937453 对的,比如用 logrotate 做切割,这玩意不但可以配置各种切割规则,而且还可以指定切割前执行任意外部操作做预处理、切割后执行任意外部工作做善后。最好是你的程序支持收到 HUP 信号或者别的触发条件时 reopen 日志文件,这样切割的事完全不用放在自己的程序中处理,只要闷头写就行了。
    Chancel
        48
    Chancel  
       354 天前
    @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

    拧螺丝只要口对的上都行,但使得顺不顺手是另外一回事
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5507 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 07:11 · PVG 15:11 · LAX 23:11 · JFK 02:11
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.