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

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

O ponto de entrada de configuração (SetupEntryPoint no manifesto do serviço) é um ponto de entrada privilegiado que, por predefiniçã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 anfitrião de serviço de execução prolongada. O executável entryPoint é executado depois de o executável SetupEntryPoint sair com êxito. O processo resultante é monitorizado e reiniciado e começa novamente com SetupEntryPoint se alguma vez terminar ou falhar.

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

Segue-se um exemplo de manifesto de serviço simples para um serviço sem estado que especifica um script de configuração MySetup.bat no serviço SetupEntryPoint. Os argumentos são utilizados para transmitir argumentos ao script quando é 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 predefinição, o executável do ponto de entrada de configuração do serviço é executado com as mesmas credenciais do Service Fabric (normalmente a conta NetworkService ). No manifesto da aplicação, pode alterar as permissões de segurança para executar o script de arranque numa conta de sistema local ou numa conta de administrador.

Configurar a política com uma conta de sistema local

O exemplo de manifesto de aplicação seguinte mostra como configurar o ponto de entrada de configuração do serviço para ser executado na conta de administrador de utilizador (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 secção Principais com um nome de utilizador, como SetupAdminUser. A conta de utilizador SetupAdminUser é membro do grupo de sistema Administradores.

Em seguida, na secção ServiceManifestImport , configure uma política para aplicar este principal ao SetupEntryPoint. Esta política indica ao Service Fabric que, quando o ficheiro MySetup.bat é executado, deve ser executado como SetupAdminUser ( com privilégios de administrador). Uma vez que 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 predefinida que todos os pontos de entrada de serviço são executados como.

Configurar a política com contas do sistema local

Muitas vezes, é preferível executar o script de arranque com uma conta de sistema local em vez de uma conta de administrador. Normalmente, a execução da política RunAs como membro do grupo Administradores não funciona bem porque os computadores têm o Controlo de Acesso de Utilizador (UAC) ativado por predefinição. Nestes casos, a recomendação é executar o SetupEntryPoint como LocalSystem, em vez de como um utilizador local adicionado ao grupo Administradores. O exemplo seguinte mostra a definição de 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 do Linux, para executar um serviço ou o ponto de entrada de configuração como raiz, pode especificar AccountType como LocalSystem.

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

Agora, adicione um script de arranque ao projeto para ser executado com privilégios de administrador.

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

Em seguida, certifique-se de que o ficheiro MySetup.bat está incluído no pacote de serviço. Por predefinição, não é. Selecione o ficheiro, clique com o botão direito do rato para obter o menu de contexto e selecione Propriedades. Na caixa de diálogo Propriedades, certifique-se de que Copiar para o Diretório de Saída está definido como Copiar se for mais recente. Veja a captura de ecrã abaixo.

Ficheiro de lote CopyToOutput do Visual Studio para SetupEntryPoint

Agora, edite o ficheiro MySetup.bat e adicione os seguintes comandos defina uma variável de ambiente de sistema e produza um ficheiro 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 implemente a solução num cluster de desenvolvimento local. Após o início do serviço, conforme mostrado no Service Fabric Explorer, pode ver que o ficheiro MySetup.bat foi bem-sucedido de duas formas. Abra uma linha de comandos do PowerShell e escreva:

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

Em seguida, anote o nome do nó onde o serviço foi implementado e iniciado no Service Fabric Explorer. Por exemplo, Nó 2. Em seguida, navegue para a pasta de trabalho da instância da aplicação para encontrar o ficheiro out.txt que mostra o valor testVariable. Por exemplo, se este serviço tiver sido implementado no Nó 2, pode aceder a este caminho para 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 , pode executar PowerShell.exe num ficheiro batch que aponte para um ficheiro do PowerShell. Em primeiro lugar, adicione um ficheiro do PowerShell ao projeto de serviço, por exemplo, MySetup.ps1. Lembre-se de definir a propriedade Copiar se for mais recente para que o ficheiro também esteja incluído no pacote de serviço. O exemplo seguinte mostra um ficheiro de lote de exemplo que inicia um ficheiro do PowerShell chamado MySetup.ps1, que define uma variável de ambiente de sistema denominada TestVariable.

MySetup.bat para iniciar um ficheiro do PowerShell:

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

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

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

Nota

Por predefinição, quando o ficheiro batch é executado, analisa a pasta da aplicação denominada trabalho para ficheiros. Neste caso, quando MySetup.bat é executado, queremos que este localize o ficheiro MySetup.ps1 na mesma pasta, que é a pasta do pacote de código da aplicação. Para alterar esta pasta, defina a pasta de trabalho:

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

Depurar um script de arranque localmente com o redirecionamento da consola

Ocasionalmente, é útil para fins de depuração ver o resultado da consola da execução de um script de configuração. Pode definir uma política de redirecionamento da consola no ponto de entrada de configuração no manifesto do serviço, que escreve o resultado num ficheiro. A saída do ficheiro é escrita na pasta da aplicação denominada log no nó de cluster onde a aplicação é implementada e executada, encontrada no C:\SfDeployCluster\_App\{application-name}\log. Poderá ver um número após o nome das aplicações no caminho. Este número incrementa em cada implementação. Os ficheiros escritos na pasta de registo 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 é o resultado padrão. Poderá ver mais do que um conjunto de ficheiros consoante as tentativas de ativação do serviço.

Aviso

Nunca utilize a política de redirecionamento da consola numa aplicação implementada em produção, uma vez que esta ação pode afetar a ativação pós-falha da aplicação. Utilize-o apenas para fins locais de desenvolvimento e depuração.

O exemplo de manifesto de serviço seguinte mostra a definição do redirecionamento da consola com um valor FileRetentionCount:

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

Se alterar o ficheiro MySetup.ps1 para escrever um comando Echo , este procedimento será escrito no ficheiro 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 esta política de redirecionamento da consola.

Passos seguintes