PowerShell
El intérprete con el que se administra Windows hoy: por qué devuelve objetos y no texto, cómo se descubre un comando que no se conoce, cómo se encadena una canalización y cómo se consulta o se manda sobre una máquina remota.
El cmdlet y por qué la canalización lleva objetos
La unidad de trabajo de PowerShell es el cmdlet, una orden escrita en .NET y agrupada en módulos. Su nombre sigue siempre el mismo patrón: un verbo, un guion y un sustantivo, es decir la acción delante y el objeto detrás. Esa regla no es estética, es lo que permite adivinar órdenes que uno no ha visto nunca.
Get-Service # obtener servicios
Stop-Service # parar un servicio
New-Item # crear un elemento
Export-Alias # exportar los alias definidosLa diferencia de fondo con un intérprete clásico es qué viaja por la tubería. En una consola de Unix o en el símbolo del sistema, lo que pasa de un comando al siguiente es texto, y el segundo tiene que recortarlo por columnas para entenderlo. En PowerShell lo que pasa es un objeto .NET completo, con sus propiedades y sus métodos intactos.
La consecuencia práctica es que no hace falta cortar cadenas: se filtra por el nombre de la propiedad. Y como el objeto conserva sus métodos, se pueden invocar directamente, algo impensable con texto plano.
$cola = Get-Process notepad
$cola.Kill()
(Get-ChildItem C:\LLC\temario.json).CopyTo("D:\copia\temario.json")Casi todos los cmdlets llevan alias, nombres cortos pensados para teclear rápido. Muchos imitan a propósito los de Unix o los del símbolo del sistema, para que quien viene de otra consola no se pierda. Get-Alias los enumera, y gal es el alias del propio Get-Alias.
| Cmdlet | Alias habituales |
|---|---|
| Get-ChildItem | gci, ls, dir |
| Get-Content | gc, cat |
| Copy-Item | cpi, cp, copy |
| Get-Process | gps, ps |
| Get-Service | gsv |
| Get-Location | gl, pwd |
| Where-Object | where, el signo de interrogación |
| ForEach-Object | foreach, el signo de porcentaje |
| Select-Object | select |
Un cmdlet es siempre verbo y sustantivo. Si una opción del test propone un nombre con otro formato, ya se puede descartar sin saber qué hace.
Para el examen
Forma del nombre: siempre Verbo-Sustantivo
Qué transporta la canalización: OBJETOS, no texto
Descubrir el sistema: Get-Command, Get-Help y Get-Member
Nadie se aprende de memoria los miles de cmdlets que hay instalados. La forma de trabajar es otra: preguntarle al propio intérprete. Tres cmdlets bastan para orientarse en una máquina desconocida.
| Cmdlet | Responde a la pregunta |
|---|---|
| Get-Command | Qué órdenes hay disponibles y de qué módulo salen |
| Get-Help | Qué hace una orden concreta y con qué parámetros |
| Get-Member | Qué propiedades y métodos trae el objeto que devuelve |
Get-Command lista de todo: cmdlets, funciones, alias, filtros y ejecutables sueltos del sistema. Admite comodines sobre el nombre, que es la forma natural de buscar cuando se conoce el sustantivo pero no el verbo.
Get-Command *Service*
Get-Command -Module ActiveDirectory
Get-Command -CommandType CmdletGet-Help es el manual, y sus tres modificadores marcan la diferencia: -Full da la página completa, -Examples salta directamente a los ejemplos, que es lo que se busca el noventa por ciento de las veces, y -Online abre la documentación actualizada en el navegador.
Get-Help Stop-Service -Full
Get-Help Get-ChildItem -Examples
Get-Help Restart-Computer -OnlineGet-Member es el menos conocido y el más útil. Se le canaliza la salida de cualquier cmdlet y responde qué tipo de objeto es y qué se le puede pedir. Sin él, filtrar por una propiedad es adivinar.
Get-ChildItem | Get-Member
Get-ChildItem | Get-Member -MemberType Properties
Get-Service | Get-Member -MemberType MethodsEl orden de trabajo es Get-Command para encontrar la orden, Get-Help para saber usarla y Get-Member para saber qué devuelve y por dónde filtrarla.
Para el examen
Get-Command: encontrar la orden
Get-Help: saber usarla
Get-Member: ver qué devuelve y por dónde filtrar
La canalización: filtrar, seleccionar, ordenar y dar formato
Una tarea de administración en PowerShell casi siempre es una cadena de cuatro pasos: obtener los objetos, quedarse con los que interesan, quedarse con las propiedades que interesan y presentarlos. Cada paso tiene su cmdlet y siempre van en ese orden.
| Paso | Cmdlet | Qué recorta |
|---|---|---|
| Filtrar | Where-Object | Elimina objetos que no cumplen la condición |
| Seleccionar | Select-Object | Se queda con algunas propiedades de cada objeto |
| Ordenar | Sort-Object | Reordena la colección por una propiedad |
| Recorrer | ForEach-Object | Ejecuta un bloque por cada objeto que llega |
| Presentar | Format-Table, Format-List | Decide cómo se pinta en pantalla |
Dentro del bloque de Where-Object o de ForEach-Object hace falta referirse al objeto que se está tratando en ese momento, y para eso existe una variable especial: el símbolo de dólar seguido de guion bajo. Es la pieza que más cuesta al principio y la que más aparece en los enunciados.
Get-Process |
Where-Object { $_.WorkingSet -gt 200MB } |
Sort-Object WorkingSet -Descending |
Select-Object -Property Name, Id, WorkingSet |
Format-Table -AutoSizeLas comparaciones no usan símbolos sino palabras precedidas de guion, porque los signos de mayor y menor ya estaban ocupados por la redirección. Conviene tenerlas a mano.
| Operador | Significado |
|---|---|
| -eq | Igual a |
| -ne | Distinto de |
| -gt | Mayor que |
| -lt | Menor que |
| -like | Coincide con un patrón de comodines |
| -match | Coincide con una expresión regular |
ForEach-Object sirve para repetir una acción sobre cada elemento de una colección, y se combina bien con un rango numérico para generar cosas en serie.
1..5 | ForEach-Object { New-Item -ItemType File -Name "simulacro$_.log" }Where-Object quita filas y Select-Object quita columnas. Los cmdlets Format van siempre los últimos: después de darles formato ya no hay objetos que filtrar, solo texto para pintar.
Para el examen
Where-Object: quita FILAS
Select-Object: quita COLUMNAS
Los cmdlets Format: van siempre los últimos: después ya no hay objetos, solo texto
Los cmdlets del día a día
Con el patrón de verbo y sustantivo, aprenderse el catálogo es aprenderse los sustantivos. Estos son los que salen en cualquier sesión de administración, agrupados por lo que administran.
| Cmdlet | Qué administra |
|---|---|
| Get-Service | Los servicios del sistema |
| Get-Process | Los procesos en ejecución |
| Get-ChildItem | El contenido de un directorio, o de una unidad virtual |
| New-Item | Crea un elemento: fichero, directorio o clave |
| Get-Content, Add-Content | Lee y añade contenido a un fichero |
| Copy-Item, Clear-Item | Copia y vacía elementos |
| Get-ItemProperty | Lee una propiedad, incluidas las claves del registro |
| Get-Date, Get-History | Fecha del sistema e histórico de la sesión |
| Get-EventSubscriber, Get-Event | La cola de eventos de la sesión |
| Add-Computer | Une el equipo a un dominio o a un grupo de trabajo |
| Checkpoint-Computer | Crea un punto de restauración del sistema |
| Get-ComputerRestorePoint | Enumera los puntos de restauración existentes |
| Get-AppxPackage | Los paquetes de aplicación instalados |
| Get-ADUser | Consulta usuarios del directorio activo |
| Set-TimeZone, Get-TimeZone | La zona horaria del equipo |
| Compare-Object | Compara dos conjuntos de objetos |
| ConvertTo-Csv, ConvertTo-Html, ConvertTo-Xml | Exporta objetos a otros formatos |
Dos cmdlets merecen atención aparte porque explican una idea propia de PowerShell. Get-PSDrive no lista solo las letras de unidad: enumera todas las unidades del proveedor, incluidas las virtuales. El registro, los certificados o las variables de entorno se recorren como si fueran carpetas.
Get-PSDrive
Get-ChildItem HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion
Get-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion
Get-ChildItem Env:Y Get-Location, con alias pwd, dice en qué punto de esa jerarquía se está, sea una carpeta del disco o una rama del registro. Cambiar de sitio es Set-Location, con alias cd.
En PowerShell el registro es una unidad más: HKLM: y HKCU: se recorren con los mismos cmdlets que C:. Esa es la razón de ser de Get-PSDrive.
Para el examen
El registro en PowerShell: es una unidad más: HKLM: y HKCU:
Cómo se recorre: con los mismos cmdlets que C:
Get-PSDrive: lista las unidades disponibles
Scripts .ps1 y la política de ejecución
Un guion de PowerShell es un fichero con extensión .ps1. Por defecto no se puede ejecutar: la instalación viene con la ejecución de guiones restringida, precisamente porque un fichero de texto que llega por correo no debería poder administrar la máquina.
Esa restricción es la política de ejecución, y se cambia con Set-ExecutionPolicy. Tiene varios valores y elegir el correcto es una decisión de seguridad, no un trámite.
| Política | Qué permite |
|---|---|
| Restricted | Nada: no se ejecuta ningún guion. Es el valor de partida |
| AllSigned | Solo guiones firmados por un editor de confianza |
| RemoteSigned | Los locales sin firma; los descargados, solo si están firmados |
| Unrestricted | Todos, con un aviso para los que vienen de fuera |
| Bypass | Todos y sin aviso. Pensado para casos muy concretos |
Get-ExecutionPolicy
Set-ExecutionPolicy RemoteSigned -Scope CurrentUserLa política que se usa en la práctica es RemoteSigned: deja trabajar con guiones propios y sigue exigiendo firma a lo que viene de internet. Unrestricted quita la protección entera y no debería ser la respuesta por defecto.
La política de ejecución no es un mecanismo de seguridad infranqueable y Microsoft nunca la ha presentado como tal: es una red de protección contra la ejecución accidental. Quien tiene acceso a la consola puede saltársela de varias formas. Lo que evita es el doble clic desafortunado.
Para el examen
RemoteSigned: la política habitual: guiones propios sí, lo descargado exige firma
Unrestricted: quita la protección entera
Restricted: no permite ejecutar ningún guion
Inventariar la máquina: CIM y WMI
Para preguntar por el hardware y por la configuración profunda del sistema, PowerShell se apoya en CIM, el modelo común de información, que es la versión estandarizada de lo que en Windows se llamaba WMI. El cmdlet es Get-CimInstance y se le indica la clase que se quiere consultar.
| Clase | Qué devuelve |
|---|---|
| Win32_OperatingSystem | Versión, arquitectura y datos del sistema instalado |
| Win32_Processor | Modelo, núcleos y frecuencia del procesador |
| Win32_LogicalDisk | Unidades lógicas y espacio libre de cada una |
| Win32_SystemDriver | Controladores, su estado y su modo de inicio |
| Win32_QuickFixEngineering | Actualizaciones y parches instalados |
Get-CimInstance -ClassName Win32_LogicalDisk |
Select-Object -Property DeviceID, FreeSpace
Get-CimInstance -ClassName Win32_SystemDriver |
Where-Object { $_.State -eq "Running" -and $_.StartMode -eq "Manual" } |
Format-Table -Property Name, DisplayNameConviene saber que la herramienta antigua para esto, wmic, está en desuso y en retirada desde las versiones recientes de Windows. Los cmdlets CIM son su sustituto y son lo que hay que responder hoy.
Al lado de CIM hay un puñado de cmdlets que hacen en Windows lo que en Linux hacen órdenes muy conocidas, y las equivalencias caen en el examen.
| En Linux | En PowerShell |
|---|---|
| tail -n 7 fichero | Get-Content -Tail 7 fichero |
| grep patrón fichero | Select-String -Path fichero -Pattern patrón |
| find . -type f -iname "*x*" | Get-ChildItem -Filter "*x*" -Recurse -File |
| cp -R origen destino | Copy-Item -Path origen -Destination destino -Recurse |
| touch fichero | New-Item -ItemType File -Name fichero |
| ping equipo | Test-Connection equipo |
| curl con datos por POST | Invoke-RestMethod con -Method Post y -Body |
| uname -a | Get-CimInstance Win32_OperatingSystem |
Select-String es el grep de PowerShell y trabaja sobre texto. Where-Object no es su equivalente: filtra objetos por propiedades, no líneas por patrón.
Para el examen
Select-String: el grep de PowerShell: trabaja sobre TEXTO
Where-Object: filtra OBJETOS por sus propiedades
Módulos, ejecución remota y entorno de trabajo
Los cmdlets vienen agrupados en módulos, y cada producto instalado aporta el suyo. Un módulo puede estar disponible sin estar cargado, y por eso hay dos cmdlets distintos: uno enumera y otro carga.
Get-Module # los cargados en esta sesión
Get-Module -ListAvailable # los instalados, cargados o no
Get-Module -All # incluidos los internos
Import-Module ActiveDirectoryLa administración remota se hace con Invoke-Command, que envía un bloque de órdenes a una o varias máquinas y devuelve el resultado ya convertido en objetos. Es lo que permite administrar cien equipos sin abrir cien escritorios remotos.
Invoke-Command -ComputerName SRV-TEMARIO { Stop-Service Spooler }
Invoke-Command -ComputerName SRV-A, SRV-B { Get-Service W3SVC }La versión del intérprete se consulta de tres formas equivalentes, y las tres aparecen en enunciados: la propiedad Version del objeto que devuelve Get-Host, la misma propiedad a través de la variable automática del host, y la tabla de versiones de la sesión.
(Get-Host).Version
$host.Version
$PSVersionTable.PSVersionPowerShell no es solo una consola: es un lenguaje. Tiene variables, que se declaran con el símbolo de dólar delante y no necesitan tipo, y las sentencias de control habituales, con las que un guion deja de ser una lista de órdenes y pasa a decidir.
- Condicionales: if con sus else, y switch para muchos casos.
- Bucles: for, while y do mientras se cumpla una condición.
- Recorrido de colecciones: foreach, y su forma canalizada ForEach-Object.
Para escribir esos guiones existió un entorno integrado propio, el ISE, con editor, depurador y ayuda en la misma ventana. Sigue incluido en Windows por compatibilidad, pero ya no recibe funciones nuevas: hoy el entorno recomendado es un editor de código con la extensión de PowerShell.
Get-Module enseña lo cargado y Get-Module -ListAvailable lo instalado. Que un cmdlet no aparezca no significa que no esté: puede faltar el Import-Module.
Para el examen
Get-Module: enseña lo cargado
Get-Module -ListAvailable: enseña lo instalado
Si un cmdlet no aparece: puede faltar solo el Import-Module