Apesar de trabalhar com uma sessão PowerShell, você pode modificar o seu estado (ou ambiente) de várias maneiras: Você pode importar módulos, criar funções, especificar aliases, ou definir variáveis, para citar algumas. Mas todas elas são transitórias: os seus efeitos desaparecem assim que fecha a sessão PowerShell. No entanto, PowerShell fornece um mecanismo, chamado perfil PowerShell, que lhe permite recriar quaisquer construções e configurações ambientais desse tipo cada vez que inicia uma nova sessão PowerShell. E se um perfil é bom, mais não seria melhor? Acontece que qualquer sessão PowerShell pode usar qualquer um (ou todos) de quatro perfis diferentes, e diferentes anfitriões PowerShell fornecem ainda mais escolhas de perfil: Mas na verdade é muito mais simples de usar do que tudo isso pode parecer, uma vez que você aprecia onde todas as partes móveis cabem. Vamos dar uma olhada.
A Shell no PowerShell
Existe uma distinção entre a shell e o hospedeiro no PowerShell. Don Jones, em seu post apropriadamente intitulado The Shell vs. The Host, explica que você – como um usuário digitando no teclado – não interage diretamente com o shell (ou motor) do PowerShell. Mais precisamente, você interage com um aplicativo hospedeiro (como powerhell.exe ou powerhell_ise.exe) que cria um runspace (uma instância do motor PowerShell). Você pode realmente ver a distinção ao exibir o conteúdo da propriedade Name da variável de sistema $Host
ao lado da variável $ShellId
. Você verá que, se examinar os valores para os três hosts PowerShell mais comuns, todos eles usam o mesmo motor (shell) enquanto cada um apresenta uma interface de utilizador (host) diferente.
Host | $Host.Nome | $ShellId |
PowerShell | ConsoleHost | Microsoft.PowerShell |
PowerShell ISE | Windows PowerShell ISE Host | Microsoft.PowerShell |
Console do Gerenciador de Pacotes Visual Studio | Package Manager Host | Microsoft.PowerShell |
Outros hosts PowerShell podem potencialmente ter valores $ShellId
diferentes (por exemplo, alguns dos IDEs PowerShell disponíveis livremente incluem PowerGUI, PowerShell Analyzer e PowerShell Plus, mas não verifiquei os seus valores $ShellId
).
O Perfil PowerShell
Um perfil PowerShell nada mais é do que um nome extravagante para um script que corre quando uma máquina PowerShell é iniciada. Citando a ajuda padrão do PowerShell em about_profiles, “Você pode usar o perfil como um script de logon para personalizar o ambiente. Pode adicionar comandos, alias, funções, variáveis, snap-ins, módulos e unidades PowerShell do Windows. Pode também adicionar outros elementos específicos da sessão ao seu perfil para que estejam disponíveis em cada sessão sem ter de os importar ou recriar”
Cada máquina PowerShell suporta realmente dois perfis, um é ao nível do utilizador, distinto para cada utilizador, e o outro é ao nível do sistema, comum a todos os utilizadores. Este deve ser um paradigma familiar que você terá visto com muitas aplicações Windows. PowerShell adiciona a sua própria reviravolta única, no entanto: distingue de forma semelhante entre o nível da máquina (um perfil para cada máquina) e o nível do sistema (um perfil comum para todas as máquinas).
Assim, tomando todas as combinações de usuários e hosts, você poderia potencialmente usar qualquer um (ou todos) de quatro perfis diferentes:
- AllUsersAllHosts
- AllUsersCurrentHost
- CurrentUserAllHosts
- CurrentUserCurrentHosts
Estes perfis todos coexistem pacificamente, então você precisa estar ciente da precedência-eles estão listados acima na ordem de execução. Se você definir a mesma variável em todos os quatro perfis, a variável terá, uma vez que você lançar uma máquina PowerShell e finalmente receber um prompt, o valor atribuído pelo último perfil, CurrentUserCurrentHost
, porque cada perfil processado sucessivamente irá sobrescrever essa variável com seu valor. Outro exemplo, mostrando cooperação entre perfis ao invés de contenção, pode ser o de incrementar uma variável. Primeiro defina-a e inicialize-a para um valor inicial (por exemplo $someVar
= 0) em AllUsersAllHosts
, depois incremente-a em cada um dos outros perfis (por exemplo $someVar++
ou talvez $someVar += 5
dependendo do que você quer fazer com ela).
Como qual dos quatro usar, isso depende em grande parte das suas próprias necessidades: se você usar um computador dedicado (ou seja, não compartilhado com mais ninguém) você não precisa se preocupar com os perfis “todos os usuários”. Se você usar vários hosts, você pode querer diferenciar algumas coisas entre um perfil “todos os hosts” e um perfil de host específico. Eu estarei dando mais detalhes sobre isso abaixo em “Quantos perfis você precisa?”
A Variável $Profile
Para criar ou editar qualquer um dos perfis, é claro, você precisa saber onde encontrá-los. O próprio PowerShell pode facilmente dizer-lhe, mas também pode apenas abrir um para editar sem ter de se preocupar explicitamente com o caminho. Para ver o caminho, exiba o valor da variável $Profile
. Ele revela um único caminho de arquivo, que é o caminho para o perfil CurrentUserCurrentHost
. Em um host PowerShell padrão, o meu mostra isto:
1
2
|
PS> $Profile
C:\Users\msorens\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
|
Note que isto não faz nenhuma reivindicação sobre se o arquivo existe, apenas que esse é o caminho que ele deve ter se ele existir. Para verificar a existência, use Test-Path
:
1
2
|
PS> Test-Path $Profile
True
> |
Se o perfil não existir, você pode facilmente criá-lo:
1
|
PS> New-Item -Type file -Path $Profile -Force
|
E se você quiser ter isso em um script, você pode então combinar o acima, criando o arquivo somente se necessário:
1
2
|
PS> if (!(Test-Path $Profile)) {
New-Item -Type file -Path $Profile -Force }
|
Finalmente, para editar o perfil, basta invocar o seu editor favorito no ficheiro, ou pode sempre usar o editor de bloco de notas ubíquo:
1
|
PS> notepad $Profile
|
Todos os exemplos acima são para o perfil “padrão” (CurrentUserCurrentHost
), como mencionado. Mas você pode aplicar todos os mesmos comandos a qualquer um dos quatro perfis por referência específica; qualquer um destes produz o mesmo resultado:
1
2
|
PS> notepad $Profile
PS> notepad $Profile.CurrentUserCurrentHost
|
Substituir qualquer um dos outros três nomes de propriedades de perfil para aceder a um dos perfis não predefinidos.
Nota que pode ser complicado criar ou guardar ficheiros nos directórios do sistema (onde os perfis “todos os utilizadores” são guardados).
Você pode fazer isso com certas ferramentas Microsoft (ex. notepad) mas não pode com certas ferramentas que não são da Microsoft (ex. meu editor favorito, vim). Curiosamente, o vim fingiu trabalhar para mim, mas na verdade não funcionou: Eu podia criar um ficheiro, fechar completamente o editor, depois reabrir o editor e chamar de volta o ficheiro – ainda assim o ficheiro não apareceu no Windows Explorer nem foi visto pelo PowerShell ao arrancar! (Não conheço bem a causa raiz deste problema, mas não é devido à falta de privilégios elevados).
Por outro lado, o bloco de notas aparentemente conhece o encantamento secreto, como funciona como esperado. Outra alternativa é criar o seu perfil “todos os utilizadores” no seu próprio directório de utilizadores e depois copiá-lo ou movê-lo para o directório do sistema apropriado.
Nomes de Ficheiros de Ficheiros de Perfil & Localizações
A secção anterior explicava como editar qualquer um dos seus perfis sem realmente saber onde estão no sistema de ficheiros, mas você é um programador; você tem uma compulsão inata para saber onde estão escondidos! A tabela mostra o caminho de cada um deles. ( HostId é um placeholder, explicado em apenas um pouco)
Perfil | Localização |
AllUsersAllHosts | $PsHome\profile.ps1 |
AllUsersCurrentHost | $PsHome\profileHostId_profile.ps1 |
CurrentUserAllHosts | $Home\Documentos\WindowsPowerShell\profile.ps1 |
CurrentUserCurrentHost | $Home\Documentos\WindowsPowerShell\HostId_profile.ps1 |
Um erro que vi em vários artigos disponíveis na web é que os perfis de “todos os usuários” estão em $env:WinDir\System32
. Isso é incorrecto ! $PsHome
pode coincidir em $env:WinDir\System32
para alguns hosts mas não para todos. Como exemplo, no meu sistema o Visual Studio Package Manager Console armazena seus perfis de “todos os usuários” em $env:WinDir\SysWOW64
. (Este erro aparece mesmo em artigos de fontes muito respeitáveis, como este artigo MSDN.)
Revendo os locais, é simples entender as convenções de nomenclatura. Os perfis em nível de sistema – aqueles para todos os usuários – estão no diretório do sistema apontados por $PsHome
. Os perfis em nível de usuário estão sob o diretório home de cada usuário. O único ponto que precisa de explicação é o HostId
mostrado para os perfis específicos do host na tabela. Infelizmente, este id do host não tem nenhuma semelhança direta com a descrição do host nem com a propriedade $Host.Name
! A maneira de descobrir o HostId
é simplesmente exibir o valor da variável $Profile
, já que ela faz parte do caminho. Por conveniência, aqui estão os valores HostId
para os hosts mais comuns:
Host | HostId | $Host.Nome |
PowerShell | Microsoft.PowerShell | ConsoleHost |
PowerShell ISE | Microsoft.PowerShellISE | Windows PowerShell ISE Host |
ConsoleVisual Studio Console Manager Package Manager | NuGet | Package Manager Host |
>
Outro erro lá fora na natureza, embora menos comum, é que HostId
é equivalente à variável $ShellId
mencionada anteriormente. Isso é incorreto! Como você viu, todos os três hosts comuns mostrados logo acima têm o mesmo $ShellId
, e isso coincidentemente corresponde ao HostId
apenas para o host padrão PowerShell. (Este erro aparece, por exemplo, no livro Windows PowerShell Unleashed.)
How Many Profiles Do You Need?
Any standard Windows system has two profiles for the standard PowerShell host, two for the PowerShell ISE host, and two for all hosts-six in all as a minimum. Adicione no gerenciador de pacotes VS que eu mostrei, são mais dois. Adicione outras IDEs PowerShell – mais duas para cada uma. Como você gerencia tantos perfis?
Interpretando a doutrina oficial MSDN ( about_profiles) considere uma solução tripartida.
- Primeiro, coloque coisas verdadeiramente comuns em
AllUsersAllHost
. - Segundo, se houver algumas peculiaridades em hosts particulares, use
AllUsersCurrentHost
para esses hosts mal-intencionados. - Finalmente, deixe cada usuário gerenciar suas próprias preferências e configurações em perfis específicos do usuário.
Mas, novamente, pode haver muitos perfis diferentes para “host atual”, tanto no nível do sistema quanto no nível do usuário. Uma boa referência, já que você está remoendo as suas escolhas aqui, é o post de Ed Wilson (The Scripting Guy) Decidindo entre um ou vários perfis PowerShell. Ele inclui aí uma lista de vantagens e desvantagens para escolher entre um perfil e vários perfis. Mas para mim, as vantagens de um único perfil superam de longe as vantagens de múltiplos perfis. É preciso um pouco mais de trabalho para configurar, mas você ainda pode levar em conta as diferenças específicas do host enquanto tem tudo em um só lugar, tornando muito mais simples a manutenção ao longo do tempo.
A maior parte do seu perfil provavelmente será comum a qualquer host, então usar um único perfil significa que qualquer mudança no caminho será feita em exatamente um arquivo. Para as coisas que diferem entre hosts, inclua apenas uma seção específica para cada host que você se importa. O meu inclui algo como isto:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
if ($Host.Name -eq ‘ConsoleHost’)
{
Import-Module PSReadline
# diferenciar verbosidade de avisos!
$privData = (Get-Host).PrivateData
$privData.VerboseForegroundColor = “cyan”
}
> elseif ($Host.Name -like ‘*ISE Host’)
{
Start-Steroids
Import-Module PsIseProjectExplorer
}
if (!$env:github_shell)
{
# não sei bem porquê, mas isto falha num hospedeiro com sabor a git
Add-PSSnapin Microsoft.TeamFoundation.PowerShell
}
|
Notem como identifico o hospedeiro actual com $Host.Name
e depois executam selectivamente o código. Você vê exemplos acima para o host PowerShell padrão bem como para o host PowerShell ISE. Para o primeiro, carrega a extensão PSReadline que só funciona na máquina PowerShell. Para o segundo, carrega o PsISEProjectExplorer e o módulo ISE Steroids, ambos só podem funcionar no ambiente ISE.
Finalmente, se você usar Git e o instalador particular que você usou criou um host Git PowerShell para você, note que ele não pode ser distinguido do host PowerShell padrão pelo $Host.Name
. Ao invés disso, eu identifiquei uma variável exclusivamente definida, $env:github_shell
, que só está presente no host com sabor de Git.
What to Put in your Profile
A resposta a esta pergunta depende das suas necessidades individuais, então tem que ser muito abstrata: coloque no seu perfil o que você pode usar para ser mais produtivo. Não há, portanto, uma resposta única para isso, mas eu posso certamente dar algumas sugestões para que seus sucos criativos fluam. Você acabou de ver acima alguns exemplos de importação de módulos de terceiros para adicionar funcionalidade ao hospedeiro dado. Além das importações de módulos, as seções seguintes fornecem apenas algumas idéias para que você pense no que você possa querer colocar lá dentro. Além disso, dê uma olhada no que há no seu arquivo PowerShell `profile.ps1`? (no StackOverflow) para muitos mais exemplos.
Aliases
Muitos cmdlets PowerShell integrados têm alias; alguns têm múltiplas alias. Você pode, por exemplo, usar ls
ou dir
ou gci
em vez de digitar Get-ChildItem
. Para aqueles que você usa regularmente que não fornecem aliases (ou para suas próprias funções personalizadas e cmdlets) você pode criar seus próprios aliases com Set-Alias
. Set-Alias
é apropriado se você quiser apenas abreviar o nome da cmdlet ou função. Mas às vezes você pode querer que um alias inclua, por exemplo, um nome cmdlet mais um parâmetro que você tende a usar sempre. Para estes, você pode emular um alias com uma função simples. Para ilustrar, considere a cmdlet Import-Module
. Eu utilizo-a frequentemente e prefiro todas as minhas cmdlets de uso frequente a utilizar apenas a primeira letra de cada componente. Isto configura o alias im
para fazer isso:
1
|
Set-Alias im Import-Module
|
Mas sendo um desenvolvedor, eu também preciso usar frequentemente Import-Module
com a chave -Force
. Portanto, para isso, preciso recorrer a uma função. Para minha convenção de nomenclatura, eu adiciono a primeira letra do switch, portanto imf
aqui:
1
|
função imf($name) { Import-Module $name -force }
|
Pode então usar, por exemplo im foobar
para fazer uma importação de baunilha, ou imf foobar
para importar com -Force
aplicado.
Funções simples
Funções foram apenas mencionadas como um meio para criar pseudo-aliases, ou seja, essencialmente para salvar você digitando. Mas, claro, elas não estão limitadas a esse propósito. Você pode querer incluir no seu perfil uma variedade de “one-liners” que tanto salvam a digitação como salvam ter que lembrar de detalhes de cmdlets que você usa menos vezes. Rápido, como você mostra os últimos 50 itens no seu histórico de comando? Não tem certeza? A cmdlet a usar é Get-History
(tem um apelido padrão de apenas a letra h). É fácil de lembrar Get-History -Count 50
ou apenas h50? Aqui está a minha definição para h50 (e um h10 atirado apenas para uma boa medida):
1
2
|
função h50 { Get-History -Count 50 }
função h10 { Get-History -Count 10 }
|
Aqui está uma função mais interessante. Como você revelaria o cmdlet atrás de um alias, o caminho para um executável dado apenas o nome do programa, os conjuntos de parâmetros disponíveis para um determinado cmdlet, ou o conteúdo de uma função definida pelo usuário? Eu uso este one-liner para fazer tudo isso (nomeado após o comando unix/linux que executa de forma similar):
1
|
função que($cmd) { (Get-Command $cmd).Definição }
|
Aqui estão alguns resultados da sua utilização:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
> |
PS> que h
>Get-História
PS> que bloco de notas
C:\Sistema de Janelas32: Bloco de notas.exe
PS> que
param($cmd)
(Get-Command $cmd).Definição
PS> que importa-módulo
Import-Modulo <string> <string> -PSSessão <PSSessão >
Importar-Módulo <string > -CimSessão <CimSessão >
|
Finalmente, outro prático one-liner que funciona novamente como o comando unix/linux, reportando o seu nome de utilizador qualificado para o domínio:
1
|
função whoami { (get-content env:\userdomain) + “\” + (get-content env:\username }
|
Funções Completas
É provável que você crie algumas funções utilitárias no decorrer do seu trabalho que estão muito mais envolvidas do que um simples one-liner. Você poderia, é claro, apenas incorporá-las em seu perfil, mas isso tende a tornar seu perfil longo e confuso. Se você tem uma coleção de tais funções você sempre poderia organizá-las em um verdadeiro módulo PowerShell e então apenas adicionar um Import-Module
em seu perfil para trazê-las para dentro. Para algo entre esses dois extremos, considere esta abordagem. No meu profile eu tenho esta sequência de comandos que traz todos os scripts do meu diretório local profile_scripts para o escopo na inicialização:
1
2
3
|
Resolve-Path $PSScriptRoot\profile_scripts\*.ps1 |
Where-Object { -not ($_.ProviderPath.Contains(“.Tests.”)) } |
Objeto-Anterior { . $_.ProviderPath }
|
$PSScriptRoot
é uma variável padrão do sistema que só existe dentro do contexto de um script em execução. Ela resolve para $Home
>Documents\\WindowsPowerShell\. Assim, meu diretório profile_scripts está sob esse caminho. Qualquer script (sans qualquer script de teste) é dot-sourced, tornando-o visível no seu escopo atual assim que você tiver um prompt após a inicialização.
Perform Actions
Os itens anteriores nesta seção são todos passivos; eles definem coisas para você usar em algum momento futuro após a inicialização. Mas você também pode incluir itens ativos que são executados durante a inicialização. Eu recomendo altamente que você use o cmdlet “don’t let me shoot myself in the foot”:
1
|
Set-PSDebug -Strict
|
Línguas que são pouco dactilografadas (e.g. JavaScript, PowerShell) dão-lhe a opção de trabalhar com segurança ou não, enquanto as linguagens fortemente dactilografadas geralmente forçam-no a trabalhar com segurança. Primeiramente, segurança significa não permitir que você use uma variável antes que ela seja declarada. Isso evita que o erro de digitação inadvertido provoque uma dor incalculável ao tentar descobrir porque o seu código não está funcionando. (Presumivelmente, as pessoas de linguagem fraca acham que algumas pessoas podem achar que operar com segurança é uma sobrecarga, por isso fazem disso uma opção). Basta colocar o Set-PSDebug
no seu perfil. Fique seguro. Por favor.
Outros tipos de ações que você pode colocar no seu perfil são coisas como exibir algumas estatísticas, por exemplo, tempo de funcionamento, espaço em disco, ou política de execução PowerShell. Se você administra várias máquinas você pode querer ver detalhes sobre a máquina em que você ‘remoted’, para ter certeza que você está na caixa que você pensa que está (nome do domínio, nome do computador, endereço IP, etc.).
Segurar seu perfil
Quando se lida com computadores, a segurança deve ser sempre uma consideração. Você usa um firewall e um antivírus para tentar manter o seu sistema seguro. Da mesma forma, você precisa considerar os scripts PowerShell que você executa – incluindo seus próprios perfis. PowerShell tem um bom suporte para a segurança, começando pela sua configuração padrão de não deixar correr quaisquer scripts; fora da caixa só pode utilizar os comandos PowerShell interactivamente. Você precisa abrir seu sistema apenas o suficiente para permitir que você realize qualquer trabalho que precise fazer, definindo a política de execução do seu computador (veja Set-ExecutionPolicy).
Mas assim que você permitir a execução de scripts, há uma chance de que você inadvertidamente possa estar executando um script comprometido. Isto não é nada exclusivo dos scripts PowerShell por se- qualquer coisa no seu computador pode estar comprometida-é apenas que o PowerShell o ajuda a mitigar a situação. E ele faz isso permitindo que você defina a política de execução para diferentes níveis de segurança de acordo com suas próprias necessidades. Você pode exigir que cada script seja autenticado, ou que qualquer script que você baixe tenha que ser autenticado, entre outras opções. A autenticação, neste caso, refere-se a scripts de assinatura com uma assinatura digital (veja Set-AuthenticodeSignature) para que, se um arquivo for modificado (maliciosamente ou não), a assinatura digital detecte a adulteração e impeça que o script seja executado.
Gerenciar segurança para seus scripts PowerShell (incluindo seus perfis), entretanto, não é um esforço trivial. (Seria mais do dobro da duração deste artigo!) Mas muita informação boa já está por aí para o orientar. Eu recomendaria começar com outro artigo aqui no Simple-Talk, o PowerShell Day-to-Day SysAdmin Tasks do Nicolas Prigent: Securing Scripts. Existem também várias boas referências na própria documentação do PowerShell: about_signing dá uma boa introdução ao tópico; New-SelfSignedCertificate permite que você crie seus próprios certificados autoassinados, e Get-ChildItem for Certificate revela as diferenças pouco conhecidas em Get-ChildItem
quando se refere à sua loja de certificados. A Microsoft fornece uma referência antiga, mas ainda útil, sobre Melhores Práticas de Assinatura de Código. E Geoff Bard’s Signing PowerShell Scripts vale a pena dar uma olhada também.
Tire esse perfil do caminho!
Agora você sabe como configurar seu perfil, por que ele é útil, o que fazer com ele, e como salvaguardá-lo. Mas como qualquer super-poder, você tem que ser conhecedor do seu lado negro. Bem, não tanto um lado negro em si, mas que há momentos em que você simplesmente não quer que o(s) seu(s) perfil(s) fique(m) no seu caminho. Ou, mais pungentemente, os perfis de outras pessoas.
Há uma variedade de situações em que você pode querer realmente executar powerhell.exe ou com um comando literal ou um arquivo de script para executar. Aqui está apenas um exemplo: digamos que você criou um script PowerShell que você queira compartilhar com um colega. Ao contrário dos arquivos batch, você não pode simplesmente clicar duas vezes em um script PowerShell para executá-lo; isso é parte do modus operandi de segurança do PowerShell para manter seu sistema seguro. Mas isso é fácil de contornar (não que eu o recomende!) criando um atalho padrão do Windows com o arquivo de script PowerShell como parâmetro.
Um outro uso, talvez mais legítimo, seria executar um script ou comando PowerShell dentro de um arquivo de compilação. Como o MSBuild não sabe inatamente como executar scripts PowerShell, você normalmente executaria um script fornecendo-o como argumento para powerhell.exe.
Ainda que você execute powerhell.exe, você está abrindo uma nova máquina PowerShell. E o que acontece quando você abre uma máquina? Ele roda qualquer um (ou todos) os seus quatro perfis! Mas quase sempre que você estiver abrindo um host invocando diretamente powershell.exe você não quer que seus perfis rodem, nem para o overhead nem para os possíveis conflitos que possam surgir. Tenha em mente, se alguém está executando uma construção onde você introduziu um comando para executar powerhell.exe, é o perfil deles que será executado em sua máquina, e você não tem noção do que pode estar espreitando lá. Além disso, você não quer depender de algo em um perfil porque a primeira vez que alguém rodar sua build que não sabe da dependência, ela irá (possivelmente misteriosamente) falhar. Por isso, é mais seguro adoptar simplesmente a melhor prática de ignorar sempre os perfis quando se invoca powerhell.exe. (não quero dizer que devas ignorá-los, mas sim que deves dizer ao PowerShell para os ignorar, é claro!
Então depois de toda essa acumulação de suspense, o denouement pode ser um pouco anticlimático: simplesmente adicione um -NoProfile
como parâmetro ao powershell.exe.
Conclusion
O perfil PowerShell é seu amigo. Com o roteiro definido neste artigo, você viu os tipos de perfis disponíveis para você e pode selecionar os que funcionarão para você. Ou você pode escolher usar um único perfil, distinguindo quaisquer itens específicos do host, conforme necessário. O perfil é uma ferramenta simples mas poderosa à sua disposição, não é nada complicado de usar, e os seus usos são limitados apenas pela sua imaginação. A única desvantagem é o tempo todo que você vai passar procurando coisas úteis e inteligentes para adicionar ao seu perfil. (Eu mencionei que você deveria olhar para incluir o módulo Go-Shell…?)