如何使用PM2向应用程序传递执行参数?

104

我正在使用pm2启动我的应用程序,但我无法将参数传递给它。我使用的命令是pm2 start app.js -- dev,虽然在forever中可以正常工作。

11个回答

200
如果你想从CLI传递node参数,那么可以这样做:
pm2 start myServer.js --node-args="--production --port=1337"

已编辑

您可以在--后添加任何参数

pm2 start app.js -- --prod --second-arg --third-arg

Sails文档关于部署


1
这很好。但是当传递到Docker时,它不起作用。有人可以帮我吗?ENTRYPOINT ["pm2"] CMD ["start", "msg/myServer.js", "--node-args='--firstarg'", "--no-daemon"] - Raj Rajen
1
@RajRajen:如果你正在使用Docker,我觉得运行PM2不是最佳选择。要么让Docker监控你的应用程序,并使用其重启策略来保持应用程序的活动状态,要么使用类似supervisord的东西,这样你的容器就不必在每次应用程序崩溃时重新启动。当你在docker中运行PM2时,你会失去PM2许多有用的功能,它真正做的只是让你的应用程序保持活动状态。此时使用forever或一个init系统同样可以做到,并且可能更容易。对于运行超过1个服务的docker容器,Supervisord非常常见。 - tsturzl
3
对于Docker,您可以使用专门的PM2命令pm2-docker。更多信息请参见:http://pm2.keymetrics.io/docs/usage/docker-pm2-nodejs/ - Unitech
只想指出在json配置文件中,字段名是argsnode-args - Dave
2
根据http://pm2.keymetrics.io/docs/usage/quick-start/的说明,您只需要添加 -- ,其后的所有内容都将作为参数传递;不需要使用 -x 选项;-x 的意思是使用 fork 系统执行命令。 - Nick Steele
只是想强调一下,仅仅因为你可以在 Docker 中使用 PM2,并不意味着你必须这样做。不同的用例需要不同的工具。 - Cameron Wilby

28
你可以按照这张票据上的说明操作:https://github.com/Unitech/pm2/issues/13 虽然,如果你正在传递环境变量,你可能想考虑利用环境变量。这样你可以创建一个变量,并通过process.env.*在该环境中的任何进程中访问该变量。
所以你有一个配置文件 config.json:
{
   "dev": {
        "db": {
            "hosts":["localhost"],
            "database": "api"
        },
        "redis": {
            "hosts": ["localhost"]
        }
   },
   "staging": {
        "db": {
            "hosts":["1.1.1.1"],
            "database": "api"
        },
        "redis": {
            "hosts": ["2.2.2.2"]
        }
   },
   "production": {
        "db": {
            "hosts":["1.1.1.1", "1.1.1.2", "1.1.1.3"],
            "database": "api"
        },
        "redis": {
            "hosts": ["2.2.2.2", "2.2.2.3"]
        }
   }
}

然后您导入配置:

var config=require('./config.json')[process.env.NODE_ENV || 'dev'];

db.connect(config.db.hosts, config.db.database);

然后你可以通过shell在你的环境中设置变量:

export NODE_ENV=staging
pm2 start app.js

环境变量将持续到您的会话结束。因此,您必须在~/.bashrc文件中为该用户设置它以使变量持久化。这将在每个会话中都设置该变量。

PM2具有一个部署系统,允许您在应用程序守护进程化之前每次设置环境变量。这是POSIX系统中守护进程通常接受参数的方式,因为这些参数不会随着进程而丢失。考虑到您的情况,这可能并不重要,但这是一个好的实践。

此外,在生产环境中,应考虑尽可能在本地停止/启动,并在集群模式下重新启动以防止停机时间。


我使用AWS Code Deploy和我的Node.JS应用程序进行了设置,它运行得非常好。我在本地使用端口4040,在AWS上使用端口80。这是一个优雅的解决方案,确保我的端口设置正确。谢谢! - BuffMcBigHuge
在你的例子中,你只将NODE_ENV设置为staging,并且该环境下的数据库主机是1.1.1.1。但是如果我们在生产环境中不知道数据库主机,这种情况经常发生,我们该如何在启动时设置数据库主机呢?我还是很困惑。 - xbmono
@xbmono 我想你会做某种服务发现,或者通过环境变量读取。一个技巧是将您的配置文件作为实际的js文件,并从环境或发现服务(如consul)中提取某些配置。 - tsturzl
@TobiasFeil 链接中已经提到了那个解决方案。通过环境变量和文件提供配置通常是更好的做法。我提到了这两种解决方案,并选择详细说明我认为更好的解决方案。没有必要无礼。 - tsturzl
@xbmono,这个例子应该能够向你展示如何轻松地将环境变量引入到配置文件中。这是我在还在使用nodejs时经常做的事情,我认为这是相当普遍的。 - tsturzl
显示剩余2条评论

22

可以通过进程定义参数。

您可以在ecosystem.config.js中使用args关键字定义新进程,如下所示:

{
  name            : 'my-service',
  script          : './src/service.js',
  args            : 'firstArg secondArg',
},
{
  name            : 'my-service-alternate',
  script          : './src/service.js',
  args            : 'altFirstArg altSecondArg',
}

这里,两个进程使用同一个文件 (service.js),但传递不同的参数。

请注意这些参数在 service.js 中处理。 在我的情况下,我只使用了 process.argv[2] 来获取第一个参数,以此类推。


1
如果您想要持续(持久)配置,这是更好的解决方案。我认为您错过了如何使用 ecosystem.config.js 的部分。例如 pm2 start ecosystem.config.js - HankCa

13

您可以通过在 -- 后传递参数来将参数发送到您的脚本中。例如:pm2 start app.js -i max -- -a 23 // 将参数传递给 app.js


13
我已经测试过,在我的Windows机器上可以正常工作。以下是使用pm2将参数传递到nodejs应用程序的完整解决方案。
** 还有两种类型的参数:
1. node-args - 在npm start之前使用 2. args - 在你的Node程序中使用
使用pm2传递参数有两种方法:
选项1:使用pm2命令通过参数传递。 选项2:使用配置文件,例如ecosystem.config.js。
选项1(通过命令传递参数):
pm2 start app/myapp1.js --node-args="--max-http-header-size=80000" -- arg1 arg2

//Access the arg as below in your node program.
console.log(process.argv[2]); // arg1
console.log(process.argv[3]); // arg2

选项2(使用配置文件): 如果您正在使用ecosystem.config.js,可以使用以下配置进行定义:

    {
      name: 'my-app',
      script: 'app\\myapp1.js',
      env: {
        NODE_ENV: 'DEV',
        PORT : 5051
      },
      node_args: '--max-http-header-size=80000',
      args : 'arg1 arg2',
      instances: 1,
      exec_mode: 'fork'
    }

开始开发模式:

pm2 start --name myapp  app/myapp1.js -- .\ecosystem.config.js

想要以生产模式启动,只需添加 --env=production 命令参数。

pm2 start --name myapp  app/myapp1.js -- .\ecosystem.config.js --env=production 

//Access the arg as below in your node program.
console.log(process.argv[2]); // arg1
console.log(process.argv[3]); // arg2

3

我在Linux环境中经常使用PM2来运行我的Python脚本。所以考虑一个脚本只有一个参数,并需要在一段时间后持续运行,我们可以像这样传递它:

pm2 start <filename.py> --name <nameForJob> --interpreter <InterpreterName> --restart-delay <timeinMilliseconds> -- <param1> <param2>

filename.py 是 Python 脚本的名称,去掉<>符号后,我想要使用 PM2 运行它。
nameForJob 是任务的有意义的名称,去掉<>符号。
InterpreterName 是用于运行脚本的 Python 解释器,通常在 Linux 中是 python3
timeinMilliseconds 是我们的脚本需要等待并重新运行的时间,以毫秒为单位。
param1 是脚本的第一个参数。
param2 是脚本的第二个参数。


2

您可以通过两种方式将参数从pm2传递给CLI中的nodejs:

  • pm2 start app.js --dev --port=1234(请注意,在--和dev之间有一个额外的空格)
  • pm2 start app.js --node-args="dev --port=1234"

无论哪种方式,您都会发现这些值存在于process.argv中(['dev','--port=1234'])


1
当我运行第一个选项时,它显示:错误:未知选项--port - Salim Shamim

2

我将为npm脚本提供补充答案。

关于npm脚本

// package.json
{
  "scripts": {
    "start": "pm2 start --node-args=\"-r dotenv/config\" index.js"
  }
}

npm run start 运行 pm2 start 命令,启动 index.js 文件,并使用 node-args 参数 -r dotenv/config,该参数从 .env 文件中获取环境变量,dotenv 是一个工具包。


你如何将一个额外的自定义变量传递到这个脚本中? - Steve Tomlin

2
您可以像这样为节点传递参数:
NODE_TLS_REJECT_UNAUTHORIZED=0 NODE_ENV=dev pm2 start server.js --name web-server

1
pm2文档中:
//Inject what is declared in env_production
$ pm2 start app.js --env production 

//Inject what is declared in env_staging
$ pm2 restart app.js --env staging

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接