当前位置: 首页 > 知识库问答 >
问题:

Docker SIGTERM在使用标志启动时未交付到node.js/coffee应用程序

濮阳驰
2023-03-14

我已经在应用程序中设置了侦听器来捕获SIGTERM、SIGINT和SIGUSR2:

# kill
process.on 'SIGTERM', ->
    killExecutors 'SIGTERM'

# ctrl + c
process.on 'SIGINT', ->
    killExecutors 'SIGINT'

# nodemon signal
process.on 'SIGUSR2', ->
    killExecutors 'SIGUSR2'

它按预期工作。当我在docker实例中运行它时:

FROM node:4.4.7

MAINTAINER Newborns <newborns@versul.com.br>

COPY . /src

EXPOSE 7733

WORKDIR /src
RUN npm install

CMD ["./node_modules/.bin/coffee", "feeder.coffee"]

一切都很好。但是,当我向执行添加节点标志时

FROM node:4.4.7

MAINTAINER Newborns <newborns@versul.com.br>

COPY . /src

EXPOSE 7733

WORKDIR /src
RUN npm install

CMD ["./node_modules/.bin/coffee", "--nodejs", "--max_old_space_size=384", "feeder.coffee"]

它停止捕捉信号。我想把CMD的执行表格改成

CMD ./node_modules/.bin/coffee --nodejs --max_old_space_size=384 feeder.coffee

但还是不行。有标志和没有标志的执行之间有什么变化?

编辑:

实际上,docker在没有传递任何标志的情况下启动一个进程

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  4.2  1.0 960940 85424 ?        Ssl  20:21   0:01 node ./node_modules/.bin/coffee feeder.coffee
root        16  0.1  0.0  20220  2884 ?        Ss   20:22   0:00 bash
root        20  0.0  0.0  17500  2064 ?        R+   20:22   0:00 ps -aux

当传递标志时,有两个进程

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.1  0.3 707704 25272 ?        Ssl  20:17   0:00 node ./node_modules/.bin/coffee --nodejs --max_old_space_size=384 feeder.coffee
root        10  1.7  1.1 965900 90068 ?        Sl   20:17   0:01 /usr/local/bin/node --max_old_space_size=384 /src/node_modules/.bin/coffee feeder.coffee

问题是:为什么?

共有1个答案

裴永年
2023-03-14

当您需要使用扩展的节点选项来避免Docker下带有分叉进程的信号的技术细节时,请使用Javascript加载器文件而不是可执行文件。

require('coffee-script').register();
require('./whatever.coffee').run();

然后

node --max_old_space_size=384 app.js

现在,关于技术细节。。。

容器中的初始进程是容器命名空间中的PID 1。内核将PID 1(或初始化进程)视为信号处理方面的特例。

  1. 如果init进程没有安装信号处理程序,该信号将不会发送给它。
  2. 信号不会从init进程自动传播,进程必须对此进行管理

因此,docker进程需要自己处理信号。

正如您所注意到的,当caf具有能够传递额外选项的--nodejs选项时,它将分叉一个子节点进程。

这最初表现出docker之外的一些奇怪的信号处理行为(至少在osx上)。SIGINTSIGTERM将转发到子进程,但也会立即终止父进程coffee进程,无论您如何处理代码中的信号(该信号在子进程中运行)。

一个简单的例子

process.on 'SIGTERM', -> console.log 'SIGTERM'
process.on 'SIGINT', -> console.log 'SIGINT'

cb = -> console.log "test"
setTimeout cb, 5000

当您运行此命令和ctrl-c时,信号将转发到子进程并进行处理。但父进程会立即关闭并返回shell。

$ coffee --nodejs --max_old_space_size=384 block_signal_coffee.coffee 
^C
SIGINT
$ <5ish second pause> test

然后,带有代码的子进程在后台继续运行5秒钟,最终输出test

主要问题是父coffee进程不处理代码中的任何信号,因此信号不会到达,也不会转发到子进程。这可能需要修改coffeescript的启动程序代码才能修复。

Docker外部呈现的信号怪癖Coffee--nodejs也可能是坏的,如果它发生在Docker下。如果主容器进程(分叉的父进程)在您的信号处理程序有机会在子进程中完成之前退出,容器将在它们周围关闭。如果仅仅通过将信号转发到孩子上来解决上述问题,这种情况就不太可能发生。

使用建议的javascript加载程序或修复coffee脚本加载程序的替代方法是使用实际的初始化过程,如runit或supervisor,但这会在docker和您的服务之间增加另一层复杂性。

 类似资料:
  • 下面是上面文件引用的: 但当以的身份运行InteliJ时,问题就会消失。

  • 我有一个Spring Boot应用程序,其中有一个Kafka消费者和生产者。还有一个bean来创建主题。 我的Spring Boot应用程序和Kafka都是在Kubernetes的Docker启动的。有时Spring Boot应用程序在Kafka pod启动之前就启动了,因此无法启动,因为用户无法连接(参见stacktrace)。 有没有一种方法可以让我的应用程序以弹性的方式启动?例如,消费者应该

  • 我有一份Java申请。 应用程序有一个决定应用程序是否在启动时启动的设置。 目前,我通过在StartUp items文件夹中放置/删除快捷方式实现了这一点。 然而,我想知道是否有更好的方法来处理这种行为。 编辑 是的,是视窗。抱歉之前没有清除。 应用程序有一个UI,用户可以在其中触发操作,并且应用程序在运行时定期在后台运行一些任务。 @Peter,如何使用应用程序中的代码更改注册表?这种方法是否与

  • 问题内容: 我有一个Java应用程序。 该应用程序具有一个设置,该设置决定该应用程序是否在启动时启动。 目前,我可以通过在“启动项目”文件夹中放置/删除快捷方式来实现此目的。 但是,我想知道是否有更好的方法来处理此行为。 编辑 是的,它是Windows。抱歉,之前没有清除该内容。 该应用程序具有一个用户可以在其中触发动作的UI,并且该应用程序在运行时会定期在后台运行一些任务。 @Peter,如何在

  • 问题内容: 我有两个单独的节点应用程序。我希望其中一个能够在代码中的某个时刻启动另一个。我将如何去做? 问题答案: 使用。它与相似,但是用于创建V8的全新实例。因此,它专门用于运行Node的新实例。如果您只是执行命令,请使用或。 请注意,默认情况下使用时,流与父级关联。这意味着所有输出和错误都将在父进程中显示。如果您不希望与父级共享流,则可以在选项中定义属性: 然后,您可以将流程与主流程的流分开处

  • 问题内容: 我正在编写一个使用node.js访问本地文件系统的桌面Web应用程序。我目前可以使用node.js打开文件并将其复制到硬盘驱动器上的不同位置。我还想做的是允许用户使用与文件类型关联的应用程序打开特定文件。换句话说,如果用户在Windows环境中选择“ myfile.doc”,它将使用该文件启动MSWord。 我一定是术语的受害者,因为除了与node.js进行通信的子进程的生成之外,我什