以本地用户或系统帐户身份运行服务启动脚本Run a service startup script as a local user or system account

在启动 Service Fabric 服务可执行文件之前,可能需要进行某种配置或设置工作。Before a Service Fabric service executable starts up it may be necessary to run some configuration or setup work. 例如,配置环境变量。For example, configuring environment variables. 可以在服务的服务清单中指定要在服务可执行文件启动前运行的脚本。You can specify a script to run before the service executable starts up in the service manifest for the service. 通过为服务安装程序入口点配置 RunAs 策略,可以更改在其下运行安装程序可执行文件的帐户。By configuring a RunAs policy for the service setup entry point you can change which account the setup executable runs under. 使用单独的安装程序入口点,可在短时间内运行高权限配置,因此服务主机可执行文件不需要长时间使用高权限运行。A separate setup entry point allows you to run high-privileged configuration for a short period of time so the service host executable doesn't need to run with high privileges for extended periods of time.

安装程序入口点(服务清单中的 SetupEntryPoint)是特权入口点,默认情况下以与 Service Fabric 相同的凭据(通常是 NetworkService 帐户)先于任何其他入口点运行。The setup entry point (SetupEntryPoint in the service manifest) is a privileged entry point that by default runs with the same credentials as Service Fabric (typically the NetworkService account) before any other entry point. EntryPoint 指定的可执行文件通常是长时间运行的服务主机。The executable that is specified by EntryPoint is typically the long-running service host. EntryPoint 可执行文件在 SetupEntryPoint 可执行文件成功退出后运行。The EntryPoint executable is run after the SetupEntryPoint executable exits successfully. 如果总是终止或崩溃,则将监视并重启所产生的进程(再次从 SetupEntryPoint 开始)。The resulting process is monitored and restarted, and begins again with SetupEntryPoint if it ever terminates or crashes.

配置服务安装程序入口点Configure the service setup entry point

下面是无状态服务的一个简单服务清单示例,该示例在服务 SetupEntryPoint 中指定了安装程序脚本 MySetup.batThe following is a simple service manifest example for a stateless service that specifies a setup script MySetup.bat in the service SetupEntryPoint. Arguments 用于在脚本运行时将参数传递给脚本。Arguments is used to pass arguments to the script when it runs.

<?xml version="1.0" encoding="utf-8"?>
<ServiceManifest Name="MyStatelessServicePkg"
                 Version="1.0.0"
                 xmlns="http://schemas.microsoft.com/2011/01/fabric"
                 xmlns:xsd="https://www.w3.org/2001/XMLSchema"
                 xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance">
  <Description>An example service manifest.</Description>
  <ServiceTypes>
    <StatelessServiceType ServiceTypeName="MyStatelessServiceType" />
  </ServiceTypes>

  <!-- Code package is your service executable. -->
  <CodePackage Name="Code" Version="1.0.0">
    <SetupEntryPoint>
      <ExeHost>
        <Program>MySetup.bat</Program>
        <Arguments>MyValue</Arguments>
        <WorkingFolder>Work</WorkingFolder>        
      </ExeHost>
    </SetupEntryPoint>
    <EntryPoint>
      <ExeHost>
        <Program>MyStatelessService.exe</Program>
      </ExeHost>
    </EntryPoint>
  </CodePackage>

  <ConfigPackage Name="Config" Version="1.0.0" />

  <Resources>
    <Endpoints>
      <Endpoint Name="ServiceEndpoint" />
    </Endpoints>
  </Resources>
</ServiceManifest>

配置服务安装程序入口点的策略Configure the policy for a service setup entry point

默认情况下,服务安装程序入口点可执行文件在与 Service Fabric 相同的凭据(通常为 NetworkService 帐户)下运行。By default, the service setup entry point executable runs under the same credentials as Service Fabric (typically the NetworkService account). 在应用程序清单中,可以将安全权限更改为在本地系统帐户或管理员帐户下运行启动脚本。In the application manifest, you can change the security permissions to run the startup script under a local system account or an administrator account.

使用本地系统帐户配置策略Configure the policy by using a local system account

下面的应用程序清单示例演示如何将服务安装程序入口点配置为在用户管理员帐户 (SetupAdminUser) 下运行。The following application manifest example shows how to configure the service setup entry point to run under user administrator account (SetupAdminUser).

<?xml version="1.0" encoding="utf-8"?>
<ApplicationManifest xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" ApplicationTypeName="MyApplicationType" ApplicationTypeVersion="1.0.0" xmlns="http://schemas.microsoft.com/2011/01/fabric">
  <Parameters>
    <Parameter Name="MyStatelessService_InstanceCount" DefaultValue="-1" />
  </Parameters>
  <ServiceManifestImport>
    <ServiceManifestRef ServiceManifestName="MyStatelessServicePkg" ServiceManifestVersion="1.0.0" />
    <ConfigOverrides />
    <Policies>
      <RunAsPolicy CodePackageRef="Code" UserRef="SetupAdminUser" EntryPointType="Setup" />
    </Policies>
  </ServiceManifestImport>
  <DefaultServices>
    <Service Name="MyStatelessService" ServicePackageActivationMode="ExclusiveProcess">
      <StatelessService ServiceTypeName="MyStatelessServiceType" InstanceCount="[MyStatelessService_InstanceCount]">
        <SingletonPartition />
      </StatelessService>
    </Service>
  </DefaultServices>
  <Principals>
    <Users>
      <User Name="SetupAdminUser">
        <MemberOf>
          <SystemGroup Name="Administrators" />
        </MemberOf>
      </User>
    </Users>
  </Principals>
</ApplicationManifest>

首先,以用户名(例如 SetupAdminUser)创建 Principals 节。First, create a Principals section with a user name, such as SetupAdminUser. SetupAdminUser 用户帐户是 Administrators 系统组的成员。The SetupAdminUser user account is a member of the Administrators system group.

接下来,在 ServiceManifestImport 节下面配置策略,以将此主体应用到 SetupEntryPointNext, under the ServiceManifestImport section, configure a policy to apply this principal to SetupEntryPoint. 此策略会告知 Service Fabric,当 MySetup.bat 文件运行时,它应该以 SetupAdminUser (具有管理员特权)身份运行。This policy tells Service Fabric that when the MySetup.bat file is run it should run as SetupAdminUser ( with administrator privileges). 由于尚未将策略应用到主入口点,因此 MyServiceHost.exe 中的代码将以系统 NetworkService 帐户运行。Since you have not applied a policy to the main entry point, the code in MyServiceHost.exe runs under the system NetworkService account. 这是用于运行所有服务入口点的默认帐户。This is the default account that all service entry points are run as.

使用本地系统帐户配置策略Configure the policy by using local system accounts

通常建议使用本地系统帐户,而不是管理员帐户运行启动脚本。Often, it's preferable to run the startup script using a local system account rather than an administrator account. 以 Administrators 组成员的身份运行 RunAs 策略通常效果不佳,因为计算机在默认情况下已启用用户访问控制 (UAC)。Running the RunAs policy as a member of the Administrators group typically doesn't work well because computers have User Access Control (UAC) enabled by default. 在这种情况下,建议将 SetupEntryPoint 以 LocalSystem 身份运行,而不是以添加到 Administrators 组的本地用户身份来运行。In such cases, the recommendation is to run the SetupEntryPoint as LocalSystem, instead of as a local user added to Administrators group. 以下示例演示如何将 SetupEntryPoint 设置为作为 LocalSystem 运行:The following example shows setting the SetupEntryPoint to run as LocalSystem:

<?xml version="1.0" encoding="utf-8"?>
<ApplicationManifest xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" ApplicationTypeName="MyApplicationType" ApplicationTypeVersion="1.0.0" xmlns="http://schemas.microsoft.com/2011/01/fabric">
  <Parameters>
    <Parameter Name="MyStatelessService_InstanceCount" DefaultValue="-1" />
  </Parameters>
  <ServiceManifestImport>
    <ServiceManifestRef ServiceManifestName="MyStatelessServicePkg" ServiceManifestVersion="1.0.0" />
    <ConfigOverrides />
    <Policies>
         <RunAsPolicy CodePackageRef="Code" UserRef="SetupLocalSystem" EntryPointType="Setup" />
      </Policies>
  </ServiceManifestImport>
  <DefaultServices>
    <Service Name="MyStatelessService" ServicePackageActivationMode="ExclusiveProcess">
      <StatelessService ServiceTypeName="MyStatelessServiceType" InstanceCount="[MyStatelessService_InstanceCount]">
        <SingletonPartition />
      </StatelessService>
    </Service>
  </DefaultServices>
  <Principals>
      <Users>
         <User Name="SetupLocalSystem" AccountType="LocalSystem" />
      </Users>
   </Principals>
</ApplicationManifest>

备注

对于 Linux 群集,若要以根 身份运行服务或安装程序入口点,可以将 AccountType 指定为 LocalSystem 。For Linux clusters, to run a service or the setup entry point as root, you can specify the AccountType as LocalSystem.

从安装程序入口点运行脚本Run a script from the setup entry point

现在将启动脚本添加到项目,以便在管理员特权下运行。Now add a start up script to the project to run under administrator privileges.

在 Visual Studio 中,右键单击服务项目,并添加名为 MySetup.bat 的新文件。In Visual Studio, right-click the service project and add a new file called MySetup.bat.

接下来,请确保 MySetup.bat 文件已包含在服务包中。Next, ensure that the MySetup.bat file is included in the service package. 默认情况下未包含该文件。By default, it is not. 选择该文件,单击右键打开上下文菜单,并选择“属性”。Select the file, right-click to get the context menu, and choose Properties. 在“属性”对话框中,确保已将“复制到输出目录”设置为“有更新时才复制”。In the Properties dialog box, ensure that Copy to Output Directory is set to Copy if newer. 请参阅下面的屏幕截图。See the following screenshot.

SetupEntryPoint 批处理文件的 Visual Studio CopyToOutput

现在编辑 MySetup.bat 文件并添加以下命令,以设置系统环境变量和输出文本文件:Now edit the MySetup.bat file and add the following commands set a system environment variable and output a text file:

REM Set a system environment variable. This requires administrator privilege
setx -m TestVariable %*
echo System TestVariable set to > out.txt
echo %TestVariable% >> out.txt

REM To delete this system variable us
REM REG delete "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v TestVariable /f

接下来,构建解决方案并将其部署到本地开发群集。Next, build and deploy the solution to a local development cluster. 启动该服务之后(如 Service Fabric Explorer 中所示),可以看到 MySetup.bat 文件在两个方面都已成功。After the service has started, as shown in Service Fabric Explorer, you can see that the MySetup.bat file was successful in a two ways. 打开 PowerShell 命令提示符并键入:Open a PowerShell command prompt and type:

PS C:\ [Environment]::GetEnvironmentVariable("TestVariable","Machine")
MyValue

接下来,记下已在 Service Fabric Explorer 中部署并启动服务的节点名称,Then, note the name of the node where the service was deployed and started in Service Fabric Explorer. 例如“节点 2”。For example, Node 2. 接下来,导航到应用程序实例工作文件夹,找到显示 TestVariable 值的 out.txt 文件。Next, navigate to the application instance work folder to find the out.txt file that shows the value of TestVariable. 例如,如果此服务已部署到节点 2,则可以转到 MyApplicationType 的此路径:For example, if this service was deployed to Node 2, then you can go to this path for the MyApplicationType:

C:\SfDevCluster\Data\_App\Node.2\MyApplicationType_App\work\out.txt

从安装程序入口点运行 PowerShell 命令Run PowerShell commands from a setup entry point

若要从 SetupEntryPoint 点运行 PowerShell,可以在指向 PowerShell 文件的批处理文件中运行 PowerShell.exeTo run PowerShell from the SetupEntryPoint point, you can run PowerShell.exe in a batch file that points to a PowerShell file. 首先,将 PowerShell 文件添加到服务项目(例如 MySetup.ps1)。First, add a PowerShell file to the service project--for example, MySetup.ps1. 请记住设置“如果较新则复制”属性,以便文件还包括在服务包中。Remember to set the Copy if newer property so that the file is also included in the service package. 下面的示例演示一个示例批处理文件,可启动名为 MySetup.ps1 的 PowerShell 文件,该文件用于设置系统环境变量 TestVariableThe following example shows a sample batch file that starts a PowerShell file called MySetup.ps1, which sets a system environment variable called TestVariable.

MySetup.bat 可启动 PowerShell 文件:MySetup.bat to start a PowerShell file:

powershell.exe -ExecutionPolicy Bypass -Command ".\MySetup.ps1"

在 PowerShell 文件中,添加以下内容来设置系统环境变量:In the PowerShell file, add the following to set a system environment variable:

[Environment]::SetEnvironmentVariable("TestVariable", "MyValue", "Machine")
[Environment]::GetEnvironmentVariable("TestVariable","Machine") > out.txt

备注

默认情况下,当批处理文件运行时,它查找名为 work 应用程序文件夹中的文件。By default, when the batch file runs, it looks at the application folder called work for files. 在此示例中,当 MySetup.bat 运行时,我们希望它在同一文件夹(即应用程序代码包文件夹)中找到 MySetup.ps1 文件。In this case, when MySetup.bat runs, we want this to find the MySetup.ps1 file in the same folder, which is the application code package folder. 若要更改此文件夹,请按如下所示设置工作文件夹:To change this folder, set the working folder:

<SetupEntryPoint>
    <ExeHost>
    <Program>MySetup.bat</Program>
    <WorkingFolder>CodePackage</WorkingFolder>
    </ExeHost>
</SetupEntryPoint>

使用控制台重定向本地调试启动脚本Debug a startup script locally using console redirection

有时,需要查看运行安装程序脚本的控制台输出以便进行调试。Occasionally, it's useful for debugging purposes to see the console output from running a setup script. 可以在服务清单中的安装程序入口点上设置控制台重定向策略,以便将输出写入文件。You can set a console redirection policy on the setup entry point in the service manifest, which writes the output to a file. 文件输出将写入到部署和运行应用程序的群集节点上名为 log 的应用程序文件夹中。The file output is written to the application folder called log on the cluster node where the application is deployed and run.

警告

永远不要在生产中部署的应用程序中使用控制台重定向策略,因为这可能会影响应用程序故障转移。Never use the console redirection policy in an application that is deployed in production because this can affect the application failover. 将其用于本地开发和调试目的。Only use this for local development and debugging purposes.

下面的服务清单示例演示如何使用 FileRetentionCount 值设置控制台重定向:The following service manifest example shows setting the console redirection with a FileRetentionCount value:

<SetupEntryPoint>
    <ExeHost>
    <Program>MySetup.bat</Program>
    <WorkingFolder>CodePackage</WorkingFolder>
    <ConsoleRedirection FileRetentionCount="10"/>
    </ExeHost>
</SetupEntryPoint>

如果现在更改 MySetup.ps1 文件以写入 Echo 命令,该命令会写入到输出文件以进行调试:If you now change the MySetup.ps1 file to write an Echo command, this will write to the output file for debugging purposes:

Echo "Test console redirection which writes to the application log folder on the node that the application is deployed to"

警告

调试脚本后,请立即删除此控制台重定向策略。After you debug your script, immediately remove this console redirection policy.

后续步骤Next steps