Windows PowerShellTrabalhando sem script

Don Jones

Sempre que estou conversando com os colegas sobre o Windows PowerShell – seja em uma conferência, no grupo de notícias público Windows PowerShell ou mesmo no meu site –, encontro administradores que me dizem que "irão esperar" para aprender o Windows PowerShell. Por quê? A razão mais comum que eles apresentam é que

"não têm tempo para aprender como criar um script agora".

Trata-se de um sentimento comum. Nós, os administradores, formamos um grupo ocupado e realmente não temos muito tempo livre para aprender uma nova tecnologia. Mas temos que seguir em frente, aprendendo novos softwares como, por exemplo, o Windows Vista®, o Windows Server® 2008 e o Exchange Server 2007, para que possamos nos manter atualizados em relação às tecnologias essenciais para os nossos trabalhos. E o Windows PowerShell™ é parte importante dessas tecnologias.

Outra razão que eu costumo ouvir os administradores citarem para deixar de aprender a criar scripts no Windows PowerShell é que eles têm "medo de se tornar um programador", como disse um colega administrador. Bem, isso é algo no qual eu posso ajudá-lo. Você talvez se surpreenda ao saber que é possível fazer coisas verdadeiramente incríveis usando o Windows PowerShell, tudo isso sem escrever uma linha de código.

Preparando-se para pipeline

Eu já escrevi sobre a extrema flexibilidade e a eficiência do pipeline orientado a objeto usado pelo Windows PowerShell (mesmo que as palavras "orientado a objeto" possa fazer você suspeitar de que estou na direção da seara dos programadores, fique comigo). Uma das minhas coisas favoritas sobre o pipeline é como ele pode ser usado interativamente. Ele pode oferecer a você resultados instantâneos e permite que você os refine facilmente para poder obter exatamente o que deseja. Por exemplo, vamos supor que eu queira ter um inventário do espaço livre em disco destinado a vários computadores remotos. Agora digamos que os nomes dos computadores sejam listados em um arquivo de texto chamado C:\Computers.txt. Trata-se apenas de um arquivo de texto sem formatação com um nome de computador por linha – nada tão complicado quanto um banco de dados.

Para começar, verei se consigo recuperar essas informações do meu computador local. Afinal, se eu consigo descobri-las em um computador, realizar a tarefa em vários computadores deve ser bem fácil. E não se esqueça de que não há nenhum script envolvido aqui! Farei tudo interativamente no shell, obtendo os resultados assim que eu pressionar a tecla Enter.

Aqui está uma dica sobre esse tipo de tarefa. Sempre que quiser fazer um inventário das informações de gerenciamento dos computadores remotos, você provavelmente usará o WMI (Instrumentação de Gerenciamento do Windows®). Agora vamos supor que, para as finalidades desse exemplo, eu não saiba nada além de que preciso usar o WMI. Então, salto até o Live Search e digito "espaço livre em disco wmi windows" como meu termo de pesquisa. Vários resultados na lista apresentam a frase "Win32_LogicalDisk" em seus trechos. Para mim, isso parece uma classe do WMI e talvez seja a que eu estou procurando. Eu sequer me importo em clicar em algum desses resultados de pesquisa. Na verdade, digito "Win32_LogicalDisk" como novo termo de pesquisa e o resultado principal é de uma página de documentação Win32_LogicalDisk no site da MSDN® (msdn2.microsoft.com/aa394173.aspx). Dessa forma, acesso essa página e vejo se uma das propriedades da classe é FreeSpace, o que parece ser muito promissor.

Encontrando um Cmdlet

Na próxima etapa, preciso encontrar um cmdlet que recupere as propriedades de uma classe do WMI para mim. Um dos aspectos notáveis do Windows PowerShell é que ele conta com recursos de descoberta automática internos fantásticos – ou seja, o shell pode ajudá-lo a conhecer seus próprios recursos. Então, digito Help *wmi* para descobrir o que o shell sabe sobre o trabalho com o WMI. Os resultados, mostrados na Figura 1, são o alias Gwmi e o cmdlet para o qual ele aponta, Get-WMIObject. Basicamente, há duas formas de acessar a mesma funcionalidade, o que significa que eu não tenho que tomar uma decisão muito difícil sobre qual usar. Como elas fazem a mesma coisa e Gwmi é menor para digitar, eu usarei:

Figura 1 O que o shell sabe sobre o trabalho com o WMI

Figura 1** O que o shell sabe sobre o trabalho com o WMI **(Clique na imagem para aumentar a exibição)

PS C:\> gwmi win32_logicaldisk

Observe que o Windows PowerShell não diferencia maiúsculas de minúsculas – ele sabe que nós, administradores, não temos tempo para detalhes como pressionar a tecla Shift.

Os resultados desse comando, mostrados na Figura 2, incluem todas as minhas cinco unidades locais e as propriedades FreeSpace, que aparecem listadas como bytes. Também está listada uma propriedade DriveType para cada uma dessas unidades, e estou vendo valores iguais a 2, 3 e 5 no meu computador.

Figura 2 Todas as minhas unidades locais e suas propriedades FreeSpace

Figura 2** Todas as minhas unidades locais e suas propriedades FreeSpace **(Clique na imagem para aumentar a exibição)

Cmdlet do mês

Você talvez tenha usado Get-Content para ler o conteúdo de um arquivo de texto. Ele trata cada linha do arquivo como sendo um objeto [string], passando esses objetos pelo pipeline para que funcionem com outros cmdlets. Mas Get-Content tem várias opções que o tornam mais flexível: o parâmetro –readCount, por exemplo, permite que você especifique quantos objetos [string] são passados pelo pipeline de uma só vez (o padrão é enviá-los todos) e o parâmetro –totalCount controla o número total de linhas lidas do arquivo. Ambos os parâmetros são úteis no trabalho com arquivos realmente grandes, quando você talvez queira processar todo o arquivo de uma só vez por motivos de desempenho.

Eis aqui outro que você achará útil. O parâmetro –encoding permite que vários tipos de codificação de arquivo sejam lidos corretamente, inclusive Unicode, ASCII, UTF7, UTF8 e muitos outros. Para ver uma lista completa dos tipos de codificação suportados, execute help gc (gc é um alias de Get-Content).

Refinando os dados

Tenho dois problemas nesse ponto. Primeiro, não me importo com todas as demais propriedades; quero apenas FreeSpace. Segundo, não quero saber do espaço livre das unidades óticas, unidades removíveis ou de rede; estou preocupado apenas com os discos rígidos locais. Talvez essa propriedade DriveType possa me ajudar a diferenciá-los. Retorno ao meu navegador da Web e vejo que a documentação contém uma tabela explicando o que os valores DriveType diferentes representam. Quero apenas os com DriveType igual a 3, o que indica que a unidade é um disco rígido local. Jamais tendo feito isso antes, eu optei por ver se o comando Gwmi pode fazer algum tipo de filtragem para mim. Executar Help Gwmi –full recupera os detalhes sobre como funciona o comando, incluindo vários exemplos. Encontrei um parâmetro que parece ser útil, –filter, e decidi tentar executá-lo:

gwmi win32_logicaldisk -filter "drivetype = 3"

E funcionou! Agora a minha lista de unidades contém apenas os discos fixos locais. O segundo problema foi resolvido; agora eu preciso resolver o primeiro – me livrar de todas as propriedades que não me preocupam.

Executo Get-Command para listar todos os cmdlets do Windows PowerShell e acabo recorrendo a Select-Object. A descrição diz que isso "selecionará as propriedades específicas de um objeto ou conjunto de objetos". Então, eu tentei isso:

gwmi win32_logicaldisk -filter "drivetype = 3" | select freespace

Orientando os resultados de Gwmi para Select (o alias de Select-Object), consigo exatamente a propriedade que quero. Opa! Esses resultados não são tão bons, uma vez que tudo o que tenho é uma lista de números – não preciso mais saber qual unidade está relacionada a que lista de espaço livre. Então, volto à documentação e vejo que a propriedade DeviceID contém a letra da unidade. Reviso rapidamente o meu comando e tento novamente:

gwmi win32_logicaldisk -filter "drivetype = 3" | select deviceid,freespace

Perfeito! E como apenas duas propriedades estão sendo listadas, o shell é capaz de colocar as informações em uma tabela de aparência agradável (no mês que vem, eu explicarei quando o Windows PowerShell opta por usar listas e tabelas).

Calculando

Eu recuperei as informações sobre o espaço livre, mas elas estão em bytes, e isso não ajuda tanto quanto se elas fossem em megabytes ou em gigabytes. Talvez eu não queira exatamente a propriedade FreeSpace, e sim um valor calculado a partir dela. O cmdlet ForEach-Object (ou um de seus muitos aliases como, por exemplo, %) pode ajudar nisso. Esse cmdlet me permite usar uma variável especial, $_, para fazer referência ao disco lógico atual e acessar as propriedades de cada disco individualmente e fazer algumas contas. Aqui é possível ver o meu comando revisado:

gwmi win32_logicaldisk -filter "drivetype = 3" | % { $_.deviceid; $_.freespace/1GB }

Tudo o que fiz aqui foi remover Select e substituí-lo pelo alias de ForEach-Object (%). Esse cmdlet apenas quer que eu o informe o que fazer com cada Win32_LogicalDisk obtido e eu já disse para ele obter a propriedade DeviceID e dividir a propriedade FreeSpace por um gigabyte – o Windows PowerShell "sabe" o que são KB, MB e GB – para que a minha saída seja informada em gigabytes.

Muitos computadores

Agora que isso está funcionando para um computador, é hora de fazê-lo funcionar para vários sistemas. Eu sei como obter o conteúdo de um arquivo de texto. Isso é feito da mesma forma como fazíamos no tempo do MS-DOS® – usando o comando Type, que, no Windows PowerShell, se transforma em um alias de Get-Content:

Type c:\computers.txt

O que eu quero fazer é pegar cada um desses computadores e, para cada um deles, executar o comando do WMI no qual eu já trabalhei. A frase "para cada um deles" deve fazê-lo se lembrar de um cmdlet – mais especificamente, ForEach-Object. Então, vamos ao grande truque, como dizem naqueles programas de televisão, e vejamos o meu comando final:

type c:\computers.txt | % { $_; 
gwmi –computername $_ win32_logicaldisk -filter "drivetype=3" | % { $_.deviceid; $_.freespace/1GB} }

Assustador, não é? Graças ao meu uso exclusivo de aliases, e não aos nomes de cmdlet, é difícil de ler. No entanto, é bem fácil decifrar se você acompanhá-lo bit a bit:

  • Começo "digitando" o conteúdo do meu arquivo de texto.
  • Oriento o conteúdo para ForEach-Object.
  • ForEach-Object produz o item atual, usando a variável $_. (Esse é o nome do computador atual.)
  • Em seguida, ForEach-Object executa o meu comando do WMI, que tem outra chamada ForEach-Object.

Expandir os nomes de alias em nomes de cmdlet pode ajudar. Aqui está o mesmo comando, mas desta vez eu escrevi os cmdlets e separei o comando em linhas individuais para que você possa examinar cada seção com mais facilidade:

Get-Content C:\Computers.txt | 
ForEach-Object { 
 $_; Get-WMIObject –computername $_ 
Win32_LogicalDisk -filter "DriveType=3" | 
 ForEach-Object { 
 $_.DeviceID; $_.FreeSpace/1GB
 }
}

Os resultados – que não são muito atrativos, embora sejam funcionais – são mostrados na Figura 3.

Figura 3 Os resultados finais

Figura 3** Os resultados finais **(Clique na imagem para aumentar a exibição)

Nenhum script necessário

A idéia desse acompanhamento é demonstrar que é possível usar o Windows PowerShell sem criar nenhum script. E, com apenas alguns exemplos como esse, além de explorar um pouco mais o próprio Windows PowerShell, é possível encontrar alguns dos bits necessários para a realização de qualquer tarefa à qual você tenha se proposto a fazer.

A idéia final é de que o Windows PowerShell veio para ficar. E por que não aprender a usá-lo agora mesmo? Você pode até mesmo se perguntar como viveu tanto tempo sem ele – e certamente não deixará que a palavra script o afaste de você.

Don Jones é o maior especialista em scripts da SAPIEN Technologies e instrutor do ScriptingTraining.com. Entre em contato com Don através do seu site, ScriptingAnswers.com.

© 2008 Microsoft Corporation e CMP Media, LLC. Todos os direitos reservados. A reprodução parcial ou completa sem autorização é proibida..