Vamos aprender Windows PowerShell? – Parte II
Por Rui Machado Engenheiro Software para o Pplware
Muitos serão certamente os nossos leitores, que usam Windows, mas que desconhecem a presença de uma ferramenta super poderosa que dá pelo nome de PowerShell. O Windows PowerShell apresenta-se à comunidade como uma extensão de nós próprios ao invés de uma extensão de um Sistema Operativo ou máquina, ao permitir automatizar diversas tarefas até aqui rotineiras e maçadoras que nos faziam perder, como programadores, o focos na nossa principal tarefa, produzir Software.
Depois da apresentação do PowerShell (aqui) hoje vamos aprender a fazer um simples script.
Após uma pequena introdução ao PowerShell, na parte um da rubrica “Vamos aprender PowerShell”, publicada na passada semana, chega a altura de mostrar um pouco as potencialidades desta tecnologia, com um exemplo passo a passo de um cenário de administração de sistemas.
Desta forma, uma das tarefas de um profissional desta área passa por, por exemplo, monitorizar o espaço em disco dos diversos servidores da sua empresa e tomar decisões, bem como ações que visem por exemplo disponibilizar mais espaço a esses mesmos discos.
Estou certo que esta atividade pode ser maçadora, dado necessitar de uma monitorização constante a fim de evitar problemas, assim aquilo que proponho neste primeiro tutorial é criar um script simples que permite saber o espaço disponível em disco, e armazenar este valor numa pasta do disco local. Aquilo que tento sempre incentivar é a que criem uma scheduled task, que corre todos os dias, para que indo a uma pasta saibam a informação toda dos discos das vossas máquinas na rede.
Passemos agora à construção do script passo a passo. É importante alertar para o facto do estilo do código ser há minha imagem, acredito que outros poderão ter estilos igualmente válidos.
Para começar, é necessário declarar as variáveis globais que dão suporte à execução do script. Para este cenário, as variáveis serão apenas um array com a lista de servidores sobre os quais invocaremos o comando pretendido ($listaServidores) :
#Lista de Computadores a monitorar $listaServidores = @("DEVSCOPE33") |
Tendo as variáveis definidas, vamos criar uma lógica que lê o array de servidores da variável $listaServidores e inicia o processamento com cada um dos seus elementos. A lógica para tal é como já devem estar a imaginar, um ciclo, neste caso vou utilizar um foreach:
foreach($servidor in $listaServidores) { #adicionar lógica aqui } |
Necessitamos agora de adicionar a lógica de processamento de cada máquina da lista de servidores. Tal como já foi dito acima, vamos utilizar um cenário no qual efetuamos operações baseadas no espaço disponível em disco de uma máquina, portanto chega a altura de invocar a classe de Windows Management Instrumentation (WMI) que nos permite obter dados acerca de uma drive lógica, Win32_LogicalDisk. Assim invocamos a cmdlet de powershell que permite obter os dados de classes WMI, Get-WMIObject, com o parâmetro –ComputerName, definido pelo item do ciclo foreach, a variável $computer, para obter os dados acerca das drives lógicas desta máquina:
foreach($servidor in $listaServidores) { Get-WMIObject -ComputerName $servidor Win32_LogicalDisk } |
Se corrermos neste momento este código, já conseguimos obter informação acerca das drives:
Apesar disso, o comando retorna informação sobre todo o tipo de drives e não só discos rigidos. Para restringir a drives deste tipo temos de filtrar os resultados a drives com o atributo DriverType =3, sendo que o 3 significa que é do tipo Hard Drive. Para efetuar esta restrição, temos de introduzir um conceito fundamental do PowerShell, as Pipelines, que permitem que o output de um comando seja utilizado como input de outro, assim no fim do nosso Get-WMIObject, colocamos uma pipeline seguida da clausula where com a devida restrição:
foreach($servidor in $listaServidores) { Get-WMIObject -ComputerName $servidor Win32_LogicalDisk | where{($_.DriveType -eq 3)} } |
Podemos ainda ver no script o uso de uma variável $_, esta serve para aceder ao objeto que está atualmente na Pipeline, no nosso caso o objeto da pipeline é o conjunto de resultados do comando. Aquilo que estamos a dizer é “De todos os servidores da lista, dá-me a informação das drives lógicas cujo tipo seja disco rígido”.
De seguida, introduzimos um novo comando que podemos utilizar para selecionar os atributos que queremos mostrar, o select, assim, vamos escolher os atributos que considero serem fundamentais para conhecer o estado de um disco:
- Nome da máquina
- Drive
- Capacidade (GB)
- Espaço Livre (GB)
- Percentagem Livre (%)
Em Powershell, o código ficaria:
Get-WMIObject -ComputerName $servidor Win32_LogicalDisk | # == OPCIONAL (Restringe a discos com espaço critico) == # -and (($_.freespace/$_.size*100) -lt $warningValue) where{($_.DriveType -eq 3)}| #seleciona os atributos a mostrar e faz a devida formatação select @{n='Servidor' ;e={"{0:n0}" -f ($servidor)}}, @{n='Drive' ;e={"{0:n0}" -f ($_.name)}}, @{n='Capacidade (Gb)' ;e={"{0:n2}" -f ($_.size/1gb)}}, @{n='Espaço Livre (Gb)';e={"{0:n2}" -f ($_.freespace/1gb)}}, @{n='Percentagem Livre';e={"{0:n2}%" -f ($_.freespace/$_.size*100)}} |
Nesta fração de código existem diversas novidades, a possibilidade de criarmos um HashMap, de chave valor, com o nome do dado (n) que estamos a selecionar e o seu valor (e), para que a apresentação dos dados seja mais correta e apresente não só o valor como uma Label representativa do que aquele valor significa (Podemos adicionar à label o texto que quisermos):
@{n='Servidor' ;e={"{0:n0}" -f ($servidor)} |
Ao analisar o código vemos ainda a utilização de um string format em PowerShell como sendo a string seguida da clausula –f, seguida dos valores a substituir, separados por virgula:
“{0} {1}” –f “Rui”, “Machado” |
Neste momento falta apenas um extra no nosso script, exportar o resultado para HTML, de forma a criarmos uma forma mais limpa de visualizar os dados. Para tal, basta apenas colocar uma pipeline no final do select, invocando a cmdlet ConvertTo-Html, seguida de um Out-File que guarda o ficheiro HTML no disco:
ConvertTo-Html | ` #Formata o nome do ficheiro Out-File ("C:\Temp\AnaliseDisco_{0}_{1}.html" -f $servidor,(Get-Date -Format "ddMMyyyy")) #coloca no nome do ficheiro o servidor e a data |
Temos assim o nosso script criado, o código final é o seguinte
foreach($servidor in $listaServidores) { Get-WMIObject -ComputerName $servidor Win32_LogicalDisk | where{($_.DriveType -eq 3)}| #seleciona os atributos a mostrar e faz a devida formatação select @{n='Servidor' ;e={"{0:n0}" -f ($servidor)}}, @{n='Drive' ;e={"{0:n0}" -f ($_.name)}}, @{n='Capacidade (Gb)' ;e={"{0:n2}" -f ($_.size/1gb)}}, @{n='Espaço Livre (Gb)';e={"{0:n2}" -f ($_.freespace/1gb)}}, @{n='Percentagem Livre';e={"{0:n2}%" -f ($_.freespace/$_.size*100)}} | ` #Exporta os dados em HTML para um ficheiro ConvertTo-Html | ` #Formata o nome do ficheiro Out-File ("C:\Temp\AnaliseDisco_{0}_{1}.html" -f $servidor` ,(Get-Date -Format "ddMMyyyy")) } #coloca no nome do ficheiro o servidor e a data |
Executando o script, o resultado é um documento criado no disco local, sendo que no meu caso guardei na pasta temp do disco C, com um nome formatado, nome da máquina seguida do dia em que correu.
Abrindo o ficheiro, o conteúdo é uma tabela HTML com os dados obtidos:
Poderiam ainda adicionar folhas de estilo ao HTML, bem como implementar lógicas com comportamentos diferenciados mediante o valor percentual de espaço disponível em disco.
Download Script: EspacoEmDisco_RM
Este artigo tem mais de um ano
Muito Bom gostei bastante no artigo. Muito bem explicado.
Desconhecia o ConvertTo-Html 😀
Ótimo trabalho! Parabéns! Espero que continue e com regularidade a orientar os leitos do Pplware.
Parabéns Rui Machado e Pplware por este fantástico tópico sobre iniciação em powershell!
Não percebendo nada sobre construção de scripts queria testar o exemplo apresentado e o resultado foi este: http://sdrv.ms/Vosj6K
Cump’s
Delfim, falta a declaração da variável lista de computadores. Lê o inicio do post. Obrigado e cumprimentos
Olá Rui como faço para incluir uma lista de servidores?
O Rui Machado esqueceu-se de fechar o ciclo For com }. Se colocares a chaveta no final do ciclo For, tens o problema resolvido.
Culpa do Editor de sintaxe que comeu o } 🙂
Ja alterei. Thanks pela observação
Boas pessoal, sou estudante de engenharia informática e li o primeiro artigo e fiquei curioso. Agora que li este segundo acho que já não vou acompanhar os próximos capitulos. Esta linguagem é maçuda. A sintax é horrível. Há coisas bem mais práticas.
Ainda assim,os meus parabéns pela iniciativa! 😉
A sintaxe é simplesmente diferente, realmente não é fácil para quem está habituado a outras linguagens, mas devo alertar que utilizei a sintaxe mais “Advanced”, para mostrar o verdadeiro PowerShell, mas podem na mesma fazer código sem pipelines ou outro artefacto que não gostem.
José Pedro, tu como estudante de engenharia Informática, não devias de tomar essa posição –> “Agora que li este segundo acho que já não vou acompanhar os próximos capítulos. Esta linguagem é maçuda.”
No mundo do trabalho essa posição não é tolerável. Eu tive de recentemente aprender a programar em PowerShell devido a necessidade de tal. Apesar de ser algo parecido ao mundo do DOS (como muitos dizem) e estão enganados, PowerShell abre-te muitas portas a simplificação e optimização de muitos processos. Acredita que faz fiz coisas em Powershell que em C# demoraria muito mais tempo.
Acredita que se começares aprender ou pelo menos ter algumas noções de como isto funciona só te vai ficar bem.
“O saber nunca ocupa lugar!”
Like
Mas isto não é “mais uma linguagem” que podes escolher ou não, Powershell está na base de praticamente todas as funcionalidades do Windows e programas da Microsoft. É a maneira recomendada de interagir com o sistema, imprescindível para administradores.
Não é para criar apps.
Concordo, é imprescindível para quem lida com administração de sistemas Windows.
Com essa motivação, vais longe 😛
Falta-te o } no fim 🙂
Like :p
Continuem com estes tutoriais que estão 5* 😉
cumps
Parabéns pelo artigo, muito útil. Será que era possível ir mais longe neste script ou seja, para além de dar o espaço em disco será possível que dê também o espaço ocupado por determinadas pastas especificadas por nós?
Obg
Olá João, obrigado pelo comentário. Esse pedido é simples de implementar e interessante, das duas uma, ou poderás ver a resposta aqui num próximo artigo ou eu proprio publicarei um post no meu blog com esse script.(powershellpt.wordpress.com)
Muito bom, obrigado.
Uma dúvida, para que serve o caractere ` depois do pipeline? Notei que só nos dois últimos pipelines é que foi usado.
Cumprimentos
Boas Jony, obrigado pela observação, esse caracter e de quebra de linha, no fundo indica ao powershell que o código da pipeline continua na linha seguinte. E tambem caráter de sufixo para operações como quebra de linha (‘n) ou tab (‘t), etc… Obtem-se combinando Shift+’
Obrigado
Um gestor de pacotes com instalação a partir do Powershell muito útil e parecido ao apt-get do linux.
http://chocolatey.org/
Instala, git, ruby, python e muito mais através de simples comandos.
Cumprimentos.
Isto parece que a M$ está a fazer com que a linha de comandos do windows fique mais potente, tipo linux…
Grande Post Rui, é de pessoas como tu que precisamos para isto andar para frente!!! gostei muito, continua estou contigo 😀
Escrevo scripts em Perl, Batch, Bash e VBScript. Ainda acho o Powershell o mais complicado de entender entre eles.
Parabéns Rui, Excelente artigo! Powershell é realmente uma linguagem fantástica que merece ser divulgada.
PS – Gosto particularmente da ponte que faz entre o scripting e o .Net, espero ver mais artigos sobre este tema… por exemplo “PowerShell vs Console Utils”
Abraço!
Em grande Rui, continua com esses excelentes artigos que bem faz falta conteúdos sobre Powershell em Português! 🙂
Para melhor mostrar o poder do Powershell em que o .NET está presente, proponho a clássica demonstração de como fazer download de ficheiros com o WebClient! 😉
Muito bom o artigo, parabéns. Encontrei ele por ter iniciado meus estudos sobre o PowerShell, motivado pela seguinte situação que estou enfrentando e gostaria de receber ajuda se possível:
Preciso monitorar as conexões nos servidores Windows e detectar se um determinado IP realiza um número exagerado de conexões, e então tomar uma providência, como bloquear o IP caso não seja um dos meus servidores ou o IP do próprio servidor.
De início estou tentando filtrar a saída do comando netstat -n
Se puder me ajudar neste ponto, ficarei muito grato.
Boa tarde Rui.
Parabéns pelo artigo.
Como fazer para inserir num só HTML quando temos vários servidores para monitorar?
Abraço.
Melhor Explicando: Tem exportar para um só HTML quando temos vários servidores?
Abraço
Porque usar o nome da nossa empresa se já não trabalha conosco Rui?
Se não trabalha, está removida a referência.
Boa noite,
Não sei quem escreveu esta resposta mas um olhar mais atento mostraria que este post e de 30 de Janeiro data a qual trabalhava na Devscope. De facto neste momento trabalho para a Primavera BSS, além do mais foi uma republicaçao do pplware a quem agradeço duplamente pela oportunidade de contribuir para esta comunidade.
Obrigado a todos inclusive aos amigos que deixei na Devscope, pelos viste o autor não é um deles 🙂
Excelente comentário caro Rui Machado.
Este comentário não veio da DevScope obviamente. Neste tipo de fórum, qualquer um pode forjar (ou tentar simular) que é quem bem quiser.
Grande abraço Rui Machado 😉
Tentar José, só tentar 😉 ainda por cima porque trabalhei com algumas pessoas da Devscope. Um abraço ao Miguel.
Obrigado Zé To 🙂 Abraço
Pessoal!
O que preciso alterar no script pra funcionar, sou novo em PSH.
Alguem sabe de algum script para retorar temperatura do processador?
Olá Rui, muito boa as dicas do script.
Podes ajudar-me, como conseguiria definir nesse script que toda vez que o espaço em disco for de 10% livre ele apague de determinada localização no disco os arquivos com datas mais antigas?
Não percebo muito de script e por isso, gostaria de contar com sua ajuda.
Obrigado!