Executar um script de arranque do serviço como uma conta de utilizador local ou conta de sistema

Antes de um executável de serviço do Service Fabric ser iniciado, pode ser necessário executar algum trabalho de configuração ou instalação. Por exemplo, configurar variáveis de ambiente. Você pode especificar um script a ser executado antes que o executável de serviço seja iniciado no manifesto de serviço para o serviço. Ao configurar uma política RunAs para o ponto de entrada de configuração do serviço, você pode alterar em qual conta o executável de instalação é executado. Um ponto de entrada de configuração separado permite que você execute a configuração com privilégios elevados por um curto período de tempo para que o executável do host de serviço não precise ser executado com privilégios altos por longos períodos de tempo.

O ponto de entrada de instalação (SetupEntryPoint no manifesto do serviço) é um ponto de entrada privilegiado que, por padrão, é executado com as mesmas credenciais do Service Fabric (normalmente a conta NetworkService) antes de qualquer outro ponto de entrada. O executável especificado pelo EntryPoint é normalmente o host de serviço de longa execução. O executável EntryPoint é executado depois que o executável SetupEntryPoint é encerrado com êxito. O processo resultante é monitorado e reiniciado, e começa novamente com SetupEntryPoint se ele for encerrado ou falhar.

Configurar o ponto de entrada da configuração do serviço

A seguir está um exemplo de manifesto de serviço simples para um serviço sem estado que especifica um script de instalação MySetup.bat no serviço SetupEntryPoint. Argumentos é usado para passar argumentos para o script quando ele é executado.

<?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>

Configurar a política para um ponto de entrada de configuração de serviço

Por padrão, o executável do ponto de entrada da configuração do serviço é executado com as mesmas credenciais do Service Fabric (normalmente a conta NetworkService ). No manifesto do aplicativo, você pode alterar as permissões de segurança para executar o script de inicialização em uma conta do sistema local ou em uma conta de administrador.

Configurar a política usando uma conta do sistema local

O exemplo de manifesto do aplicativo a seguir mostra como configurar o ponto de entrada de instalação do serviço para ser executado na conta de administrador do usuário (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>

Primeiro, crie uma seção Entidades com um nome de usuário, como SetupAdminUser. A conta de usuário SetupAdminUser é um membro do grupo de sistema Administradores.

Em seguida, na seção ServiceManifestImport , configure uma política para aplicar essa entidade a SetupEntryPoint. Esta política informa ao Service Fabric que, quando o arquivo MySetup.bat é executado, ele deve ser executado como SetupAdminUser (com privilégios de administrador). Como você não aplicou uma política ao ponto de entrada principal, o código no MyServiceHost.exe é executado na conta NetworkService do sistema. Esta é a conta padrão na qual todos os pontos de entrada de serviço são executados.

Configurar a política usando contas do sistema local

Muitas vezes, é preferível executar o script de inicialização usando uma conta de sistema local em vez de uma conta de administrador. A execução da política RunAs como membro do grupo Administradores normalmente não funciona bem porque os computadores têm o Controle de Acesso de Usuário (UAC) habilitado por padrão. Nesses casos, a recomendação é executar o SetupEntryPoint como LocalSystem, em vez de como um usuário local adicionado ao grupo Administradores. O exemplo a seguir mostra a configuração do SetupEntryPoint para ser executado como 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>

Nota

Para clusters Linux, para executar um serviço ou o ponto de entrada de configuração como root, você pode especificar AccountType como LocalSystem.

Executar um script a partir do ponto de entrada de configuração

Agora, adicione um script de inicialização ao projeto para ser executado com privilégios de administrador.

No Visual Studio, clique com o botão direito do mouse no projeto de serviço e adicione um novo arquivo chamado MySetup.bat.

Em seguida, verifique se o arquivo MySetup.bat está incluído no pacote de serviço. Por defeito, não é. Selecione o arquivo, clique com o botão direito do mouse para obter o menu de contexto e escolha Propriedades. Na caixa de diálogo Propriedades, verifique se Copiar para o diretório de saída está definido como Copiar se for mais recente. Veja a captura de ecrã abaixo.

Visual Studio CopyToOutput para arquivo em lote SetupEntryPoint

Agora edite o arquivo MySetup.bat e adicione os seguintes comandos: defina uma variável de ambiente do sistema e produza um arquivo de texto:

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

Em seguida, crie e implante a solução em um cluster de desenvolvimento local. Depois que o serviço for iniciado, conforme mostrado no Service Fabric Explorer, você poderá ver que o arquivo de MySetup.bat foi bem-sucedido de duas maneiras. Abra um prompt de comando do PowerShell e digite:

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

Em seguida, anote o nome do nó onde o serviço foi implantado e iniciado no Service Fabric Explorer. Por exemplo, Nó 2. Em seguida, navegue até a pasta de trabalho da instância do aplicativo para localizar o arquivo out.txt que mostra o valor de TestVariable. Por exemplo, se esse serviço foi implantado no Nó 2, você pode ir para este caminho para o MyApplicationType:

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

Executar comandos do PowerShell a partir de um ponto de entrada de configuração

Para executar o PowerShell a partir do ponto SetupEntryPoint , você pode executar PowerShell.exe em um arquivo em lotes que aponte para um arquivo do PowerShell. Primeiro, adicione um arquivo do PowerShell ao projeto de serviço - por exemplo, MySetup.ps1. Lembre-se de definir a propriedade Copy if newer para que o arquivo também seja incluído no pacote de serviço. O exemplo a seguir mostra um arquivo em lotes de exemplo que inicia um arquivo do PowerShell chamado MySetup.ps1, que define uma variável de ambiente do sistema chamada TestVariable.

MySetup.bat iniciar um arquivo do PowerShell:

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

No arquivo do PowerShell, adicione o seguinte para definir uma variável de ambiente do sistema:

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

Nota

Por padrão, quando o arquivo em lotes é executado, ele examina a pasta do aplicativo chamada trabalho para arquivos. Nesse caso, quando MySetup.bat é executado, queremos que ele encontre o arquivo MySetup.ps1 na mesma pasta, que é a pasta do pacote de código do aplicativo. Para alterar esta pasta, defina a pasta de trabalho:

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

Depurar um script de inicialização localmente usando o redirecionamento de console

Ocasionalmente, é útil para fins de depuração ver a saída do console da execução de um script de instalação. Você pode definir uma política de redirecionamento de console no ponto de entrada de instalação no manifesto do serviço, que grava a saída em um arquivo. A saída do arquivo é gravada na pasta do aplicativo chamada log no nó do cluster onde o aplicativo é implantado e executado, encontrado em C:\SfDeployCluster\_App\{application-name}\log. Você pode ver um número após o nome do aplicativo no caminho. Esse número aumenta em cada implantação. Os arquivos gravados na pasta de log incluem Code_{service-name}Pkg_S_0.err, que é a saída de erro padrão, e Code_{service-name}Pkg_S_0.out, que é a saída padrão. Você pode ver mais de um conjunto de arquivos, dependendo das tentativas de ativação do serviço.

Aviso

Nunca use a política de redirecionamento de console em um aplicativo implantado em produção, pois isso pode afetar o failover do aplicativo. Use isso apenas para fins de desenvolvimento local e depuração.

O exemplo de manifesto de serviço a seguir mostra a configuração do redirecionamento do console com um valor FileRetentionCount:

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

Se você alterar o arquivo MySetup.ps1 para escrever um comando Echo , isso gravará no arquivo de saída para fins de depuração:

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

Aviso

Depois de depurar o script, remova imediatamente essa política de redirecionamento de console.

Próximos passos