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.