Introducción a Powershell

Publicado el 11 septiembre 2017 por Aprendiendoexchange

Trabajando con Exchange en algún punto nos vamos a encontrar con que no queda alternativa que recurrir a la línea de comando, específicamente al Shell de Exchange.

El shell de Exchange funciona sobre Windows Powershell por lo que antes de entrar en este tema es recomendable estar familiarizado con los principales conceptos o al menos los que a mi entender pueden resultar de mayor utilidad.
Powershell es una interfaz de línea de comando incluida en el sistema operativo desde Windows 7 o en el caso de servidores Windows Server 2008 R2. En versiones anteriores es posible su descarga.

Este es un entorno basado en objetos, es decir que no trabajamos con texto sino que lo hacemos con objetos del .Net Framework.

En general utilizamos Powershell cuando tenemos que realizar una operación avanzada donde en muchos casos no existe una opción gráfica o por ejemplo para automatizar tareas o realizar actividades en bulk ( de forma masiva).

En todos los casos la sintaxis utiliza un verbo (o acción) por un lado seguido por un guion y luego un sustantivo o sujeto. Cada cmdlet ( comando en Powershell) realiza una tarea administrativa y es posible combinar múltiples comandos para llevar a cabo tareas complejas. Cuando vemos un comando en el shell que no usa esta sintaxis es porque seguramente sea un alias.

Por ejemplo para traer la lista de servicios corriendo en un equipo podemos utilizar el cmdlet Get-Service.

Para definir el comportamiento de un cmdlet utilizamos parámetros, cada parámetro comienza con un guion y en caso de utilizar múltiples parámetros es necesario dejar un espacio entre medio. Para declarar variables usamos el signo de pesos ($) cosa que si armamos un script vamos a usar en múltiples ocasiones. Adicionalmente tenemos a disposición características programáticas y la posibilidad de utilizar loops y estructuras como foreach, If y where entre otras.

A lo largo de este artículo vamos a ver algunas de las interrogantes más comunes al trabajar con Powershell y cómo poner en práctica los conceptos. Para hacer el tema interesante te recomiendo ir abriendo Windows Powershell ( powershell.exe) y probar los ejemplos planteados.

Para qué usar el PIPE (|) en Powershell?

Este es uno de los conceptos más importantes.

Al igual que en muchos otros tipos de shell, el pipe nos permite enviar la salida de un comando a otro. En el caso particular de Powershell en lugar de enviar la salida en texto plano se trabaja con objetos.

Por qué nos podría interesar que trabaje con objetos en lugar de texto plano?

Porque cuando pasamos un objeto lo estamos haciendo junto a todas sus propiedades en lugar de tener que trabajar con una salida de texto en "crudo".

Dependiendo del idioma del teclado cómo realizar el pipe, lo más sencillo es recordar como hacerlo en ASCII: ALT + 124.

Dentro de una misma línea podemos utilizar varias veces el pipe y si bien lo podemos usar para modificar múltiples objetos en una sola línea, también lo podríamos utilizar para dar formato o filtrar la salida.

Formato de la salida en Powershell

Al ejecutar un cmdlet nos devuelve la salida en un formato predeterminado, esta salida la podemos adaptar a nuestros requerimientos.

Por ejemplo, para obtener un listado de los servicios:

Get-Service

Este cmdlet de forma predeterminada nos devuelve 3 columnas:

Si solo quisiéramos obtener el estado y el nombre a mostrar podríamos hacer lo siguiente:

Get-Service | Format-Table DisplayName, Status

De este modo solo traería 2 columnas. Esto sería en formato tabla ( Format-Table o FT).

De forma predeterminada el formato tabla nos devuelve pocas propiedades, claro que podríamos especificar que propiedades queremos, pero cómo saber que propiedades tiene un objeto?

Siempre podemos recurrir a technet o al sistema de ayuda entre otras opciones, pero lo más rápido en general es utilizar el formato en lista, por ejemplo:

Get-Service | Format-List

Esto devolvería la salida en formato lista ( alias: FL) mostrando más propiedades que en el caso de formato tabla, entonces podríamos ver el nombre de cada propiedad y posteriormente especificarla a continuación del tipo de formato, por ejemplo para ver el nombre a mostrar, estado y servicios de los que depende podríamos hacer:

Get-Service | Format-Table DisplayName, Status, DependentServices

En este caso podríamos utilizar Format-Table o Format-List dependiendo de la salida deseada.

Si bien esto nos permite dar formato cuando trabajamos de forma interactiva, en algún caso podríamos querer exportar la salida a un CSV o HTML por ejemplo, en estos casos no podemos utilizar ni Format-Table ni Format-List, acá sería necesario utilizar Select-Object ( alias: Select):

Get-Service | Select DisplayName, Status

Esto devolvería una salida similar a la de formato tabla, la diferencia es que nos habilitaría a complementar con un cmdlet de exportación, por ejemplo:

Get-Service | Select DisplayName, Status | Export-CSV -Path c:\temp\servicios.csv

En este caso el CSV generado incluiría un encabezado seguramente no deseado (#TYPE ...):

Para que este encabezado no aparezca podemos usar Export-CSV incluyendo el parámetro NoTypeInformation:

Get-Service | Select DisplayName, Status | Export-CSV -Path c:\temp\servicios.csv -NoTypeInformation

En este caso quedaría del siguiente modo:

Filtrado de salida

El cmdlet Where-Object nos sirve para filtrar los datos devueltos por otros cmdlets. Lo podemos encontrar tanto como Where-Object o incluso como "where" o "?".

El código incluido dentro del "where" se ubica entre paréntesis de tipo llave: "{}" y este código es evaluado para cada objeto que pasa a través del pipeline. El resultado de la expresión puede ser verdadero ( true) o falso ( false). Si se evalúa "true" el objeto es devuelto, en caso contrario es ignorado.

Por ejemplo, si ejecutamos en Powershell "Get-Service", este devuelve todos los servicios del equipo. Si solo nos interesan los servicios que tengan la palabra "time" en el nombre podemos filtrar del siguiente modo:

Get-Service | Where {$_.displayname -like "*time*"}

Si traducimos al español la sentencia diríamos:

"Traer servicios donde el nombre a mostrar tenga la palabra time en cualquier parte".

En este caso también estamos utilizando el operador "like".

El operador "like" nos sirve para utilizar comodines como el "*". Si por ejemplo quisiera todo lo que empiece por time utilizaría "time*", si quisiera todo lo que finalice con time "*time" y en el caso del ejemplo anterior "*time*".

Del mismo modo podríamos utilizar a la inversa con "notlike", en este caso por ejemplo la línea anterior:

Get-Service | Where {$_.displayname -notlike "*time*"}

Se traduciría en:

"Traer servicios donde el nombre a mostrar no tenga la palabra time en ninguna parte".

Qué es "$_" ?

En el caso del ejemplo anterior el "$_" representa el servicio que en ese momento está pasando por el pipe.

Si queremos acceder a alguna propiedad del objeto que está pasando por el pipe podemos utilizar ".", entonces si un objeto que pasa por el pipe tiene una propiedad "name" podríamos utilizar "$_.name".

En un escenario simple podríamos hacer lo siguiente:

"1","2″,"3″ | foreach {$_}

Esto nos devuelve en una línea el "1" en otra el "2" y en otra el "3".

En definitiva "$_" lo vamos a utilizar para acceder al objeto que está siendo pasado por el pipe.

Estructura Foreach

El foreach nos permite procesar objetos dentro de una colección, por ejemplo:

foreach ($usuario in $usuarios)

En este caso en particular la colección estaría almacenada en $usuarios. Esta colección de usuarios puede ser generada de varias formas por ejemplo importando un listado en CSV.

La variable $usuario en este caso hace referencia a cada línea de un CSV y se pudo haber llamado de otro modo, por ejemplo:

foreach ($linea in $usuarios)

La idea es que para cada línea dentro de la colección de objetos almacenada en $usuarios se ejecute el bloque incluido entre llaves "{}". En el sitio vas a encontrar una demo sobre cómo usar el foreach dentrode un script de alta masiva de objetos en Exchange.

Uso de variables en Powershell

Las variables en Powershell comienzan por "$". Por ejemplo: $variable

Volviendo al ejemplo de servicios, podríamos almacenar en $servicios todos los servicios y en otra línea filtrar la salida de $servicios utilizando Where:

$servicios = Get-Service $servicios | Where {$_.displayname -like "*time*"}

O directamente podríamos almacenar en $servicios la salida ya filtrada:

$servicios = Get-Service | Where {$_.displayname -like "*time*"}

El nombre de la variable es opcional mientras no coincida con algo reservado para el sistema.

Operadores comunes en Powershell

En Powershell tenemos operadores aritméticos, lógicos, de comparación y asignación.

Veamos algunos de los que vamos a utilizar con más frecuencia:

"= " Este sería un operador de asignación y lo que estamos diciendo es que le asigne un determinado valor a una variable, en este caso almacenamos el nombre de un servidor en $servidor y posteriormente ejecutamos la variable para ver que devuelve:

$servidor = "servidor1"

" eq " (equal) Esto se leería "igual" pero no es de asignación sino que de comparación, por ejemplo:

"prueba" -eq "prueba"

Esto devuelve "true" porque la palabra "prueba" es igual a "prueba".

"prueba -eq "prueba1"

Esto devuelve "false" porque "prueba" no es igual a "prueba1".

" ne " (not equal) Por el contrario podríamos utilizar "no igual":

"prueba" -ne "prueba"

Esto devuelve "false" porque "prueba" es igual a "prueba", en cambio:

"prueba" -ne "prueba1"

Devuelve "true" porque "prueba" no es igual a "prueba1".

Otro operador de comparación muy utilizado es " like " y este nos sirve para utilizar comodines en busca de una coincidencia:

"prueba" -like "*ueba"

Esto devuelve "true", por el contrario con " notlike ":

"prueba" -notlike "*ueba"

Devuelve "false".

En adición tenemos operadores lógicos como "And" y "Not", por ejemplo para traer todos los servicios que se encuentren iniciados y en el nombre para mostrar incluyan la palabra "time" podríamos ejecutar:

Get-Service | Where {$_.displayname -like "*time*" -and $_.status -eq "Running"}

Sobre las comillas en Powershell

El tema de las comillas en muchos casos se puede prestar a la confusión. En este sentido podemos utilizar comillas dobles ("") o simples (´´).

Cuando utilizamos valores con espacio, por ejemplo Nombre Apellido, deben encontrarse entre comillas en todos los casos, estas pueden ser dobles o simples.

Veamos algunos ejemplos con y sin comillas:

$nombre = "Juan" $apellido = "Perez" $nombrecompleto = $nombre $apellido

En este caso $nombrecompleto da error, probemos nuevamente pero utilizando comillas simples:

$nombrecompleto = '$nombre $apellido'

En este caso si ejecutamos $nombrecompleto vemos que devuelve literalmente: $nombre $apellido

El objetivo sería que se muestre el valor de la variable y no la variable de forma literal, por lo que en lugar de comillas simples tendríamos que usar dobles:

$nombrecompleto = "$nombre $apellido"

Ahora al ejecutar $nombrecompleto se devuelve correctamente: Juan Perez

Ayuda en Powershell

Por último, saber manejarse con el sistema de ayuda de Powershell es muy importante, en lugar de ir a un buscador a ver cómo usar un determinado comando podemos acceder a esta misma información sin salir del shell.

Para esto usamos el cmdlet Get-Help o su alias "Help" seguido por el cmdlet en cuestión.

Tenemos varios parámetros para especificar el nivel de ayuda que deseamos, uno que utilizo con frecuencia es el de "Examples", este parámetro en lugar de devolver toda la ayuda del cmdlet devuelve ejemplos de casos de uso, muchas veces con esto es suficiente.

Get-Help Get-Service -Examples

En adición podemos obtener ayuda detallada o completa utilizando "Detailed" o "Full" y en caso de que no exista localmente la información, con el parámetro "Online" nos lleva directamente a la página oficial con el detalle del comando.

Con esto llegamos al final del artículo, para continuar aprendiendo Exchange ( o temas asociados) te recomiendo ver el siguiente recurso: