将Pm2安装为Windows服务

问题描述

如何将Pm2作为Windows服务运行。Pm2将启动nodejs应用。 我尝试使用pm2-windows-service 但这不起作用。

https://www.npmjs.com/package/pm2-windows-service

解决方法

使用pm2-service-install将变量Pm2服务 将以下脚本(ps1)放入源代码文件夹

# Deploys application as an app within a PM2 service
# Run from root of Node application

param(
    [string] $Pm2Home = $env:PM2_HOME,[string] $AppStart = "app.js"
)
    
$ErrorActionPreference = "Stop"

function Install-Node-Modules
{
    Write-Host "Running npm install"
    & "npm" i
}

function Create-Pm2-Home
{
    Write-Host "Attempting to create $Pm2Home and give FullControl to LOCAL SERVICE"
    New-Item -ItemType Directory -Force -Path $Pm2Home

    $rule = New-Object System.Security.AccessControl.FileSystemAccessRule(
        "LOCAL SERVICE","FullControl","ContainerInherit,ObjectInherit","None","Allow")

    try {
      $acl = Get-Acl -Path $Pm2Home -ErrorAction Stop
        $acl.SetAccessRule($rule)
        Set-Acl -Path $Pm2Home -AclObject $acl -ErrorAction Stop
        Write-Host "Successfully set FullControl permissions on $Pm2Home"
    } catch {
        throw "$Pm2Home : Failed to set permissions. Details : $_"
    }
}

function Install-Pm2-Service
{
    $UserPath = $env:userprofile
    Write-Host "Installing pm2"
    & "npm" i "pm2@latest" "-g"
    Write-Host "Installing pm2-windows-service npm module"
    & "npm" i pm2-windows-service "-g"
    & "npm" install "-g" npm-check-updates
    & "cd" \
    & "cd" $UserPath\AppData\Roaming\npm\node_modules\pm2-windows-service
    & "ncu" inquirer "-u"
    & "npm" install
    & "pm2-service-install" "--unattended"
    
    # Create wrapper log file,otherwise it won't start
    $wrapperLogPath = "$(npm config get prefix)\node_modules\pm2-windows-service\src\daemon\pm2.wrapper.log"
    
    if (Test-Path $wrapperLogPath) {
        Write-Debug "PM2 service wrapper log file already exists"
    } else {
        Out-File $wrapperLogPath -Encoding utf8
    }
}

function Create-Pm2-Service-Config
{
    param([string] $ConfigPath,[string] $CmdPath)

    $configContent = @"
{
    "apps": [{
        "name": "node-app","script": "$($CmdPath -replace "\\","\\")","args": [],"cwd": "$((Split-Path $CmdPath) -replace "\\","merge_logs": true,"instances": 4,"exec_mode": "cluster_mode","env": {
            "NODE_ENV": "development"
        }
    }]
}
"@

    # Write out config to JSON file
    Write-Host "Writing PM2 service configuration to $ConfigPath"
    $configContent | Out-File $ConfigPath -Encoding utf8
}

# From http://stackoverflow.com/a/4370900/964356
function Set-ServiceAcctCreds
{
    param([string] $serviceName,[string] $newAcct,[string] $newPass)

    $filter = "Name='$serviceName'"

    $tries = 0
    
    while (($service -eq $null -and $tries -le 3)) {
        if ($tries -ne 0) {
            sleep 2
        }
        $service = Get-WMIObject -namespace "root\cimv2" -class Win32_Service -Filter $filter
        $tries = $tries + 1
    }

    if ($service -eq $null) {
        throw "Could not find '$serviceName' service"
    }

    $service.Change($null,$null,$newAcct,$newPass)

    $service.StopService()

    while ($service.Started) {
        sleep 2
        $service = Get-WMIObject -namespace "root\cimv2" -class Win32_Service -Filter $filter
    }
    $service.StartService()
}

function Change-Pm2-Service-Account
{
    Write-Host "Changing PM2 to run as LOCAL SERVICE"
    Set-ServiceAcctCreds -serviceName "pm2.exe" -newAcct "NT AUTHORITY\LocalService" -newPass ""
}

$env:PM2_HOME = $Pm2Home
$env:PM2_SERVICE_SCRIPTS = "$Pm2Home\ecosystem.json"

[Environment]::SetEnvironmentVariable("PM2_HOME",$env:PM2_HOME,"Machine")
[Environment]::SetEnvironmentVariable("PM2_SERVICE_SCRIPTS",$env:PM2_SERVICE_SCRIPTS,"Machine")

& Install-Node-Modules
& Create-Pm2-Home
& Create-Pm2-Service-Config -ConfigPath $env:PM2_SERVICE_SCRIPTS -CmdPath $AppStart
& Install-Pm2-Service
& Change-Pm2-Service-Account

执行以下命令。

.\install.ps1 -Pm2Home "C:\Users\Admin\.pm2" -AppStart "C:\SourceCode\app.js"

In it:
C:\Users\Admin\.pm2  : .pm2 path
C:\SourceCode\app.js : App.js path

在Promt中输入以下内容。

? Perform environment setup (recommended)? Yes 
? Set PM2_HOME? Yes 
? PM2_HOME value (this path should be accessible to the service user and should not contain any “user-context” variables [e.g. %APPDATA%]): c:\etc\.pm2\ 
? Set PM2_SERVICE_SCRIPTS (the list of start-up scripts for pm2)? No 
? Set PM2_SERVICE_PM2_DIR (the location of the global pm2 to use with the service)
? [recommended] Yes ? Specify the directory containing the pm2 version to be used by the service C:\USERS\<USER>\APPDATA\ROAMING\NPM\node_modules\pm2\index.js

通过访问服务启动服务 enter image description here