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

关于 NodeJS 在 Windows 上杀死启动的进程问题

  •  
  •   FakerLeung · 2022-12-19 20:35:04 +08:00 · 2853 次点击
    这是一个创建于 705 天前的主题,其中的信息可能已经有所发展或是发生改变。

    环境:Electron + NodeJS(windows10 ,不考虑 Linux)。

    程序是这样的:

    1. node 使用 spawn,传入 execFile (有可能只是个 xxx.bat 脚本)和 args ,启动了一个 java 进程(监听端口 8080 )。
    2. 返回的 child_process 有一个 PID (如 11111 ),但它是属于启动的 cmd 的 PID ,实际 java 进程的 PID 是 22222 。
    3. 退出前,使用 taskkill /T /F /PID 11111,能把这两个进程直接杀掉,但是!该 8080 端口还有很多状态为 TIME_WAIT 的连接没被一同 kill 掉,导致端口一直是被占用的状态。

    当然,如果我直接用任务管理器将 java 进程强制终止,那就就没有 TIME_WAIT 的连接了,但是好像没办法使用代码这么干。

    求教各位大佬,怎么才能一劳永逸的直接杀死进程。

    PS: 并不知道这个进程的名称(就没办法用 taskkill /F /IM ${name} 来杀进程)是啥。

    18 条回复    2022-12-21 20:06:11 +08:00
    ysc3839
        1
    ysc3839  
       2022-12-19 20:43:13 +08:00 via Android
    没理由用 taskkill 杀死后还存在 TIME_WAIT ,但用任务管理器杀死却不存在,这两个工具使用的 API 是一样的,建议仔细检查一下。
    macy
        2
    macy  
       2022-12-19 21:28:25 +08:00
    我有尝试过使用 fover 来启动这种进程,倒是没发现问题,没有尝试直接用子进程这种启动过,如楼上所说,理论上应该不会出现这种进程,spawn 都挂了,他启动 的进程应该也会挂才对
    xuyang2
        3
    xuyang2  
       2022-12-20 09:11:37 +08:00
    能用 Java Service Wrapper 将 java 程序设置为服务吗
    Java 的服务没必要用 node 管理
    FakerLeung
        4
    FakerLeung  
    OP
       2022-12-20 10:28:20 +08:00
    @xuyang2 暂时不能,我们软件是基于 electron 开发的。

    @ysc3839 确实是这样子的,就很奇怪。而且如果用 exec 执行 taskkill 有时会出现这种问题:
    ```
    错误:无法终止 PID 11111 (属于 PID 22222 子进程)的进程。
    原因:拒绝访问。
    错误:无法终止 PID 22222 (属于 PID 33333 子进程)的进程。
    原因:拒绝访问。
    ```

    @macy 不知道会不会跟我的 electron 程序会一直请求该 java 程序的心跳接口导致的?
    ysc3839
        5
    ysc3839  
       2022-12-20 10:34:29 +08:00
    @FakerLeung 此时用任务管理器结束进程情况如何呢?管理员身份运行试试呢?
    FakerLeung
        7
    FakerLeung  
    OP
       2022-12-20 11:21:31 +08:00
    @ysc3839 #5
    此时这 11111 22222 PID 的进程都没了,但是端口还是占用状态。就是有很多 TIME_WAIT 的连接没释放。


    @xuyang2 #6
    唉,项目特殊性,不能随便使用没入库的三方件。
    ysc3839
        8
    ysc3839  
       2022-12-20 11:24:57 +08:00
    @FakerLeung 是任务管理器结束后没了,但仍然占用吗?还是 taskkill ?如果你确定任务管理器和 taskkill 的行为一致,那就是 TCP 栈相关的问题了。
    FakerLeung
        9
    FakerLeung  
    OP
       2022-12-20 11:31:15 +08:00
    @ysc3839 #8
    taskkill 后,还占用。
    任务管理器结束是没问题的。

    而且,用 process.kill ,仅能 kill 掉启动的 cmd 进程,无法 kill 掉关联的子进程。
    ysc3839
        10
    ysc3839  
       2022-12-20 11:33:15 +08:00
    @FakerLeung 那你试过管理员身份运行 taskkill 吗?你确定 taskkill 杀死了进程,而不是像前面那样提示拒绝访问?
    FakerLeung
        11
    FakerLeung  
    OP
       2022-12-20 11:46:03 +08:00
    @ysc3839 #10
    管理员没试过。

    刚试了一下,任务管理器结束也是会有大量 TIME_WAIT 。

    TCP 127.0.0.1:11111 127.0.0.1:57438 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57441 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57444 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57447 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57450 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57453 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57456 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57459 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57462 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57465 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57474 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57478 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57481 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57483 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57486 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57489 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57492 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57495 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57498 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57501 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57504 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57509 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57515 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57518 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57521 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57527 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57537 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57540 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57543 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57546 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57550 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57552 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57555 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57558 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57561 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57566 TIME_WAIT 0
    TCP 127.0.0.1:11111 127.0.0.1:57769 TIME_WAIT 0
    TCP 127.0.0.1:57537 127.0.0.1:11111 TIME_WAIT 0

    要等一会(比如 15s ),才会消失。
    FakerLeung
        12
    FakerLeung  
    OP
       2022-12-20 11:46:34 +08:00
    @ysc3839 #10
    而且 electron 也没办法用管理员运行 taskkill 命令吧。。。
    ysc3839
        13
    ysc3839  
       2022-12-20 11:55:05 +08:00
    @FakerLeung #11 那说明是 TCP 协议栈的问题了。可以试试这个 https://help.aliyun.com/document_detail/40701.html
    #12 测试时当然是手动开个管理员身份的 cmd 来测试。
    mmdsun
        14
    mmdsun  
       2022-12-20 13:20:35 +08:00 via iPhone
    time_wait 时间可以改小点,然后按端口号批量 kill 进程试试看?

    for /f "tokens=5" %%a in ('netstat -aon ^| find ":8080" ^| find "LISTENING"') do taskkill /f /pid %%a
    FakerLeung
        15
    FakerLeung  
    OP
       2022-12-20 14:01:32 +08:00
    @ysc3839 #13
    不报拒绝访问,但是还是会有 TIME_WAIT 。

    @mmdsun #14
    改注册表估计不好使哦,因为我们软件要给客户用的,不能随便修改客户机的设置。
    ysc3839
        16
    ysc3839  
       2022-12-20 14:22:41 +08:00
    还可以试试用 setsockopt 设置 SO_DONTLINGER 和 SO_REUSEADDR
    https://learn.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-setsockopt#remarks
    xyjincan
        17
    xyjincan  
       2022-12-20 16:19:29 +08:00
    留个接口让 java 程序自己 exit 0
    FakerLeung
        18
    FakerLeung  
    OP
       2022-12-21 20:06:11 +08:00
    @xyjincan
    不允许这么干。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2691 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 41ms · UTC 10:42 · PVG 18:42 · LAX 02:42 · JFK 05:42
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.