Saltar al contenido

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.

powershell
Get-Service      # obtener servicios
Stop-Service     # parar un servicio
New-Item         # crear un elemento
Export-Alias     # exportar los alias definidos

La 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.

powershell
$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.

CmdletAlias habituales
Get-ChildItemgci, ls, dir
Get-Contentgc, cat
Copy-Itemcpi, cp, copy
Get-Processgps, ps
Get-Servicegsv
Get-Locationgl, pwd
Where-Objectwhere, el signo de interrogación
ForEach-Objectforeach, el signo de porcentaje
Select-Objectselect

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.

CmdletResponde a la pregunta
Get-CommandQué órdenes hay disponibles y de qué módulo salen
Get-HelpQué hace una orden concreta y con qué parámetros
Get-MemberQué 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.

powershell
Get-Command *Service*
Get-Command -Module ActiveDirectory
Get-Command -CommandType Cmdlet

Get-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.

powershell
Get-Help Stop-Service -Full
Get-Help Get-ChildItem -Examples
Get-Help Restart-Computer -Online

Get-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.

powershell
Get-ChildItem | Get-Member
Get-ChildItem | Get-Member -MemberType Properties
Get-Service | Get-Member -MemberType Methods

El 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.

PasoCmdletQué recorta
FiltrarWhere-ObjectElimina objetos que no cumplen la condición
SeleccionarSelect-ObjectSe queda con algunas propiedades de cada objeto
OrdenarSort-ObjectReordena la colección por una propiedad
RecorrerForEach-ObjectEjecuta un bloque por cada objeto que llega
PresentarFormat-Table, Format-ListDecide 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.

powershell
Get-Process |
  Where-Object { $_.WorkingSet -gt 200MB } |
    Sort-Object WorkingSet -Descending |
      Select-Object -Property Name, Id, WorkingSet |
        Format-Table -AutoSize

Las 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.

OperadorSignificado
-eqIgual a
-neDistinto de
-gtMayor que
-ltMenor que
-likeCoincide con un patrón de comodines
-matchCoincide 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.

powershell
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.

CmdletQué administra
Get-ServiceLos servicios del sistema
Get-ProcessLos procesos en ejecución
Get-ChildItemEl contenido de un directorio, o de una unidad virtual
New-ItemCrea un elemento: fichero, directorio o clave
Get-Content, Add-ContentLee y añade contenido a un fichero
Copy-Item, Clear-ItemCopia y vacía elementos
Get-ItemPropertyLee una propiedad, incluidas las claves del registro
Get-Date, Get-HistoryFecha del sistema e histórico de la sesión
Get-EventSubscriber, Get-EventLa cola de eventos de la sesión
Add-ComputerUne el equipo a un dominio o a un grupo de trabajo
Checkpoint-ComputerCrea un punto de restauración del sistema
Get-ComputerRestorePointEnumera los puntos de restauración existentes
Get-AppxPackageLos paquetes de aplicación instalados
Get-ADUserConsulta usuarios del directorio activo
Set-TimeZone, Get-TimeZoneLa zona horaria del equipo
Compare-ObjectCompara dos conjuntos de objetos
ConvertTo-Csv, ConvertTo-Html, ConvertTo-XmlExporta 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.

powershell
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íticaQué permite
RestrictedNada: no se ejecuta ningún guion. Es el valor de partida
AllSignedSolo guiones firmados por un editor de confianza
RemoteSignedLos locales sin firma; los descargados, solo si están firmados
UnrestrictedTodos, con un aviso para los que vienen de fuera
BypassTodos y sin aviso. Pensado para casos muy concretos
powershell
Get-ExecutionPolicy
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser

La 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.

ClaseQué devuelve
Win32_OperatingSystemVersión, arquitectura y datos del sistema instalado
Win32_ProcessorModelo, núcleos y frecuencia del procesador
Win32_LogicalDiskUnidades lógicas y espacio libre de cada una
Win32_SystemDriverControladores, su estado y su modo de inicio
Win32_QuickFixEngineeringActualizaciones y parches instalados
powershell
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, DisplayName

Conviene 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 LinuxEn PowerShell
tail -n 7 ficheroGet-Content -Tail 7 fichero
grep patrón ficheroSelect-String -Path fichero -Pattern patrón
find . -type f -iname "*x*"Get-ChildItem -Filter "*x*" -Recurse -File
cp -R origen destinoCopy-Item -Path origen -Destination destino -Recurse
touch ficheroNew-Item -ItemType File -Name fichero
ping equipoTest-Connection equipo
curl con datos por POSTInvoke-RestMethod con -Method Post y -Body
uname -aGet-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.

powershell
Get-Module                     # los cargados en esta sesión
Get-Module -ListAvailable      # los instalados, cargados o no
Get-Module -All                # incluidos los internos
Import-Module ActiveDirectory

La 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.

powershell
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.

powershell
(Get-Host).Version
$host.Version
$PSVersionTable.PSVersion

PowerShell 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