Windows PowerShellComandos sencillos. Administración eficaz

Don Jones

Este artículo se basa en una versión preliminar de Windows PowerShell. Toda la información que aquí se menciona está sujeta a cambios.

Ha sido un proceso largo, pero Windows PowerShell está casi listo para su lanzamiento. Esto significa que los administradores de Windows deben comenzar a familiarizarse con la aplicación. Windows PowerShell ofrece lo que es posiblemente la manera más fácil y flexible de automatizar una variedad de tareas de administración, con lo que mejoran su productividad y eficacia en el trabajo.

Pero lo más importante es que Microsoft está creando las consolas administrativas gráficas de productos como Exchange Server 2007 y System Center 2007 sobre Windows PowerShell™. Esto significa que podrá realizar casi cualquier tarea administrativa desde Windows PowerShell. Microsoft tiene planeado hacer lo mismo con las capacidades administrativas de un mayor número de productos en el futuro. Por lo tanto, Windows PowerShell podría convertirse en la primera herramienta completa para la administración de casi todos los productos de servidor de Microsoft. Para ayudarle a comenzar, hablaré sobre Windows PowerShell con frecuencia en esta nueva columna. Asegúrese de descargar una copia del software.

Eficacia y sencillez

Como indica el nombre, Windows PowerShell es un shell, similar al símbolo del sistema (Cmd.exe) que existe desde Windows NT® 3.1. Cmd.exe no desaparece, pero con la disponibilidad de Windows PowerShell, habrá pocos motivos por seguir usando Cmd.exe.

El uso de Windows PowerShell no difiere mucho del uso de Cmd.exe, excepto que Windows PowerShell es, bueno, más eficaz. Como Cmd.exe, Windows PowerShell cuenta con un lenguaje incorporado de secuencias de comandos, aunque es mucho más flexible que el primitivo lenguaje por lotes de Cmd.exe. ¿Qué grado de flexibilidad tiene? Con Windows PowerShell, puede automatizar tareas muy complejas en un lenguaje que incluye tan solo una media docena de palabras claves incorporadas.

Puesto que he mencionado la creación de secuencias de comandos, debería hablar un poco sobre la seguridad. Windows PowerShell aprovecha lo que Microsoft ha aprendido sobre la seguridad durante los últimos diez años y más. De forma predeterminada, Windows PowerShell no ejecutará secuencias de comandos y sólo se podrá usar de manera interactiva para ejecutar comandos individuales. Si no habilita la secuencia de comandos, puede indicar a Windows PowerShell que ejecute solamente secuencias de comandos con firmas digitales. Todo esto sirve para ayudar a que Windows PowerShell no se convierta en el próximo VBScript, un lenguaje estupendo que se ha usado de manera abusiva para crear secuencias de comandos malintencionadas. VBScript tampoco desaparecerá, pero es probable que considerará que Windows PowerShell es más fácil de usar en un gran número de tareas distintas.

Con Windows PowerShell puede hacer casi todo lo que puede hacer con Cmd.exe. Por ejemplo, puede ejecutar ipconfig y obtendrá el mismo resultado conocido. Sin embargo, Windows PowerShell presenta un nuevo conjunto completo de comandos que no son archivos ejecutables externos. Estos cmdlets (pronunciado "command-let" en inglés) están incorporados en Windows PowerShell. Para conocer algunos de los cmdlets más útiles y poder comenzar a usar Windows PowerShell, consulte la barra lateral "Los 10 cmdlets principales para comenzar a usar inmediatamente".

Los 10 cmdlets principales para comenzar a usar inmediatamente

  • El comando Get-Command recupera una lista de todos los cmdlets disponibles.
  • El comando Get-Help muestra la información de ayuda acerca de los cmdlets y los conceptos.
  • El comando Get-WMIObject recupera información de administración mediante WMI.
  • El comando Get-EventLog recupera los registros de eventos de Windows.
  • El comando Get-Process recupera un proceso o una lista de procesos activos.
  • El comando Get-Service recupera un servicio de Windows.
  • El comando Get-Content realiza la lectura de archivos de texto y trata cada línea como un objeto secundario.
  • El comando Add-Content anexa contenido a un archivo de texto.
  • El comando Copy-Item copia archivos, carpetas y otros objetos.
  • El comando Get-Acl recupera listas de control de acceso (ACL).

Para obtener una lista completa de los cmdlets que se incluyen en Windows PowerShell, vaya a windowssdk.msdn.microsoft.com/en-us/library/ms714408.aspx.

Todos los nombres de los cmdlets tienen un formato estándar de verbo-objeto, lo que nos facilita aprenderlos y recordarlos. Por ejemplo, si ejecuta el cmdlet Get-Command, aparecerá una lista de todos los cmdlets disponibles. Posiblemente, el cmdlet de mayor utilidad para un administrador es Get-WMIObject. Supongamos que desea saber qué service pack está ejecutando Server2. Simplemente ejecute:

Get-WMIObject Win32_OperatingSystem –Property ServicePackMajorVersion
 –Computer Server2

Para buscar la misma información mediante VBScript, debe escribir varias líneas de código. Otros cmdlets permiten trabajar con servicios (Start-Service, Stop-Service, etc.), procesos (Stop-Process, etc.), archivos (por ejemplo, Rename-Item, Copy-Item, Remove-Item, Move-Item) y mucho más. Un gran número de estos cmdlets incluso dispone de nombres de acceso directo, denominados alias. En el caso de Get-WMIObject, puede simplemente escribir gwmi. Si ejecuta Get-Alias, obtendrá una lista de los nombres de acceso directo.

Importancia de la capacidad orientada a objetos

Windows PowerShell, que se basa en Microsoft® .NET Framework, es una aplicación completamente orientada a objetos. Normalmente, únicamente un editor de software se entusiasmaría al saber esto, pero, en este caso, la capacidad orientada a objetos resulta en un gran ahorro de tiempo para los administradores. Esto se debe a que los administradores ahora pueden trabajar directamente con objetos enriquecidos dentro de un shell basado en texto. Considere el ejemplo siguiente:

Get-Process | Sort-Object pm –desc | Select-Object –first 10

Se trata de una línea sencilla con tres cmdlets distintos separados por barras verticales (se proporcionará información adicional sobre esto más adelante). El primer cmdlet recupera todos los procesos en ejecución y, a continuación, pasa (o canaliza) dichos objetos al comando Sort-Object. Este segundo cmdlet ordena en la propiedad de memoria física (pm) de cada objeto de proceso y los coloca en orden descendente. A continuación, la recopilación ordenada de objetos de proceso se canaliza hacia el comando Select-Object, que selecciona los primeros diez y los muestra. ¿Cuál es el resultado? Esta línea sencilla muestra los primeros diez consumidores de memoria en el equipo, tal como se muestra en la figura 1. Ésta es una manera muy eficaz de realizar comprobaciones rápidas durante la solución de problemas.

Figura 1 Uso de un cmdlet sencillo para la resolución de problemas

Figura 1 Uso de un cmdlet sencillo para la resolución de problemas(Hacer clic en la imagen para ampliarla)

El uso de barras verticales (el carácter que suele encontrarse en la tecla numérica 1 del teclado en español) es una parte esencial de la capacidad elevada de Windows PowerShell. Mediante este carácter, puede pasar (o canalizar) objetos de un cmdlet a otro; lo que permite refinar aún más los resultados, darles formato para su visualización, etc. Este mecanismo funciona porque todos los cmdlets devuelven uno o más objetos en lugar de sólo texto. De este modo, los cmdlets subsiguientes obtienen el objeto completo para realizar sus tareas.

El uso de objetos en Windows PowerShell es dominante hasta sus variables. Además, no es necesario declarar variables de antemano, simplemente puede empezar a usarlas colocando un símbolo de dólar ($) antes del nombre de una variable. Aunque no es necesario, también puede indicar a Windows PowerShell el tipo de datos que desea colocar en la variable. De este modo, Windows PowerShell puede asignar la variable a uno de los muy eficaces tipos de .NET Framework, lo que le proporciona una funcionalidad adicional incorporada. Por ejemplo, supongamos que desea solicitar un nombre de equipo y recuperar la versión del service pack de éste, pero no sabe si la persona que escribe el nombre del equipo incluirá dos barras invertidas (por ejemplo, \\Server2). Dado que sabe que el cmdlet Get-WMIObject no necesita barras invertidas, puede guardar el nombre del equipo en una variable de cadena y usar el método de reemplazo para remplazar las barras invertidas por cadenas vacías, tal como se indica a continuación:

[string]$c = Read-Host "Enter computer name"
$c = $c.Replace("\","")
    Get-WMIObject Win32_OperatingSystem
    –Property  ServicePackMajorVersion
    –Computer $c

El valor del parámetro –Computer se ha proporcionado en la variable $c. Originalmente, la variable se creó como una cadena, de modo que obtuvo toda la funcionalidad del tipo de cadena de .NET Framework, incluido el método de reemplazo. Evidentemente, el aprendizaje de todas estas capacidades llevará algo de tiempo, pero las encontrará fáciles de aprender a través de ejemplos. Windows PowerShell ayuda a simplificar el aprendizaje. Por ejemplo, si escribe $c = $c. (no olvide el punto final) y presiona la tecla de tabulador, Windows PowerShell mostrará Clone(), el primer método del tipo de cadena. Si sigue presionando la tecla de tabulador, Windows PowerShell pasará por todos los métodos disponibles. Esencialmente, cuando hace esto, Windows PowerShell está mostrando lo que sabe hacer con la cadena.

Ahora pasaremos a una tarea más difícil. Debemos leer una lista de nombres de equipo de un archivo, con un nombre por línea y mostrar el número del service pack de cada equipo. En VBScript, esta tarea necesitaría aproximadamente una docena de líneas de código. En Cmd.exe, necesitaría usar un complejo archivo por lotes. En Windows PowerShell, esta tarea se puede realizar con tan solo una línea:

Get-Content "c:\computers.txt" | foreach  
{ $_; gwmi Win32_OperatingSystem -prop 
ServicePackMajorVersion -comp $_ }

El cmdlet Get-Content lee el contenido de C:\Computers.txt. Cada línea del archivo se convierte en un objeto propio. La recopilación de objetos (es decir, los nombres de equipo) se canaliza hacia el comando foreach, que en realidad es un alias del cmdlet ForEach-Object. Los comandos entre las llaves se repiten una vez para cada objeto canalizado; en este ejemplo, significa que se ejecutan una vez para cada nombre de equipo. La variable especial $_ contendrá el objeto actual (es decir, el nombre del equipo actual).

En realidad, en el interior de las llaves hay dos comandos: El primero simplemente muestra el nombre del equipo actual proporcionando el contenido de $_. El segundo es el conocido comando gwmi. El resultado es una lista de las versiones de service pack para cada equipo que figura en el archivo. Todo esto se realiza con una línea clara de comandos.

Observe que el nombre de los parámetros –Property y –Computer se han abreviado. Windows PowerShell sólo requiere un número de caracteres suficiente para distinguir de manera única los nombres de los parámetros.

Legibilidad y reutilización

Sin embargo, la escritura de una única línea de comandos y parámetros no ayuda con la legibilidad. Windows PowerShell permite desglosar todo esto en un elemento más legible, que puede escribir directamente en el shell sin tener que escribir ninguna secuencia de comandos. Debe tener el aspecto siguiente:

PS C:\> $names = get-content "c:\computers.txt"
PS C:\> foreach ($name in $names) {
>> $name
>> gwmi Win32_OperatingSystem -prop ServicePackMajorVersion -comp $name
>> }
>>

Esta vez, el contenido del archivo se almacena en la variable $names. En este ejemplo aún se usa foreach, pero no se coloca a través de una canalización, de modo que hay que indicarle qué recopilación de objetos deben incluirse en el bucle y qué variable debe almacenarse en cada objeto; la parte que dice ($name in $names). El resto es casi igual y cuando presione la tecla Intro, el código se ejecutará y se mostrarán los resultados.

Si desea usar este mismo código de manera repetida, puede crear una función a partir de éste. De nuevo, esto se escribe directamente en el shell:

PS C:\> function Get-ServicePacks ($file) {
>> $names = get-content $file
>> foreach ($name in $names) {
>> $name
>> gwmi win32_operatingsystem -prop servicepackmajorversion -comp $name
>> }
>> }
>>

Como puede observar, no han cambiado demasiados elementos. Simplemente, esto cierra el ejemplo anterior en una función denominada Get-ServicePacks (según la convención de asignación de nombres verbo-objeto de Windows PowerShell). La funciona ahora tiene un parámetro de entrada denominado $file, que se ha sustituido en el comando Get-Content de modo que se pueda especificar un archivo distinto cuando se ejecute dicha función. Ahora que la función se ha definido, simplemente puede ejecutarla invocando su nombre, casi como un cmdlet, y pasando el parámetro de entrada:

PS C:\> Get-ServicePacks c:\computers.txt

La figura 2 muestra los resultados.

La desventaja aquí es que esta función sólo existirá mientras se ejecuta la instancia de Windows PowerShell. Cuando cierre el shell, la función desaparecerá. Puede copiar la función en el perfil de Windows PowerShell, que es como una secuencia de comandos de ejecución automática que se ejecuta cada vez que se inicia Windows PowerShell. De este modo, la función estará disponible en todas las ventanas de Windows PowerShell que abra. O bien, si lo desea, puede convertir la función en una secuencia de comandos independiente que puede ejecutar con tan solo escribir la ruta de acceso y el nombre de usuario de dicha secuencia de comandos.

Figura 2 Resultados de la ejecución de la función Get-ServicePacks

Figura 2 Resultados de la ejecución de la función Get-ServicePacks

El mundo es un archivo (o carpeta)

Windows PowerShell ofrece mucho más que funciones y cmdlets. Consideremos la administración de archivos como un ejemplo rápido de lo que puede hacer además. Es probable que esté más que familiarizado con la navegación de unidades de disco y carpetas en Cmd.exe: escriba C: para cambiar a la unidad C y escriba cd \test para cambiar a la carpeta C:\Test. Windows PowerShell funciona exactamente de la misma manera, aunque cd es simplemente un alias del cmdlet Set-Location.

Intente ejecutar Get-PSDrive, el cmdlet que proporciona una lista de todas las unidades disponibles. Además de las unidades C:, D: y posiblemente A: normales, también verá una denominada Cert, otra denominada Env y otras denominadas HKCU y HKLM. En realidad, Windows PowerShell expone varios tipos diferentes de recursos de almacenamiento como "unidades", lo que pone a la disposición del usuario elementos tales como el almacén local de certificados, variables de entorno y el registro, en una interfaz de navegación de tipo archivos que le resultará familiar.

Cambie al subárbol de registro HKEY_LOCAL_MACHINE. Para ello, escriba Set-Location HKLM: (o cd hklm: si prefiere el acceso directo) y presione la tecla Intro. A continuación, ejecute el comando cd software\microsoft para cambiar a la clave SOFTWARE\Microsoft. Puede usar dir (un alias del cmdlet Get-ChildItem) para obtener una lista de las subclaves de esta parte del registro. Si desea quitar una clave, use la tecla Supr como si fuese cualquier archivo o carpeta. Tenga mucho cuidado, la eliminación de claves requeridas o la modificación incorrecta del registro puede provocar problemas graves.

Toda esta flexibilidad procede de los proveedores, que asignan recursos (como el registro y el almacén de certificados) en un formato que tiene el aspecto de un sistema de archivos. Microsoft tiene planeado extender Windows PowerShell a través de proveedores adicionales, lo que le proporcionará la capacidad de, por ejemplo, navegar por un almacén de Exchange Server como si fuese un sistema de archivos. Esta técnica es muy importante en el sentido que recopila la enorme variedad de repositorios que usa Windows y hace que todos se puedan administrar a través de un sistema de comandos y técnicas ya conocidas.

Diseñado para la seguridad

Ya he mencionado que Windows PowerShell se diseñó teniendo en cuenta la seguridad. La principal función de seguridad de Windows PowerShell es su directiva de ejecución. De forma predeterminada, esta directiva se configura en Restringido, que puede comprobar mediante la ejecución del cmdlet Get-ExecutionPolicy. En el modo Restringido, las secuencias de comandos no se ejecutan en absoluto. Dado que se trata del modo predeterminado, Windows PowerShell no puede usarse para ejecutar secuencias en su estado original.

Puede especificar otros modos mediante el comando Set-ExecutionPolicy. Personalmente, yo prefiero el modo RemoteSigned. Esto permite a las secuencias de comandos locales (pero no las remotas) ejecutarse sin tener que disponer de firma digital, lo que proporciona la manera más sencilla de desarrollar y probar secuencias. El modo AllSigned no ejecuta ninguna secuencia de comandos a menos que ésta disponga de firma digital mediante un certificado emitido por un editor de confianza. Por último, la directiva Sin restricciones ejecuta cualquier elemento. No recomiendo el uso en absoluto de esta directiva, ya que permitirá que Windows PowerShell ejecute secuencias de comandos malintencionadas que puedan llegar al equipo. Observe que la directiva de ejecución también se rige por la directiva del grupo, la cual anula la configuración local. El comando Set-ExecutionPolicy le advertirá si un parámetro de la directiva del grupo está anulando la configuración local.

Además, Windows PowerShell no ejecutará secuencias de comandos desde el directorio actual, a menos que se especifique una ruta de acceso. Se ha diseñado de este modo para impedir la apropiación de comandos. Supongamos que alguien crea una secuencia de comandos denominada IPConfig.ps1 (PS1 es la extensión de nombre de archivo para los archivos de secuencia de comandos de Windows PowerShell). Si los archivos pudiesen ejecutarse desde la carpeta actual, existiría el riesgo de escribir ipconfig y ejecutar esta secuencia de comandos creada por un usuario, cuando, en realidad, deseaba ejecutar el programa de Windows Ipconfig.exe. Dado que Windows PowerShell no ejecuta secuencias de comandos desde la carpeta actual, este error no puede producirse. Si desea ejecutar una secuencia de comandos de la carpeta actual, deberá especificar la ruta de acceso: por ejemplo, .\myscript. La referencia explícita a la carpeta actual garantiza que el usuario sabe que está ejecutando una secuencia de comandos y no un comando de shell.

Windows PowerShell también cuenta con funciones que aumentan la seguridad en tareas de experimentación. Por ejemplo, considere (pero NO intente) esta combinación aterradora:

Get-Process | Stop-Process

El cmdlet Get-Process crea una recopilación de objetos de proceso y los canaliza hacia el cmdlet Stop-Process, que causará la detención de éstos. Transcurridos unos cinco segundos, el resultado será un error de detención de pantalla azul, ya que se están cerrando procesos críticos de Windows. Puede ver lo que sucedería, sin permitir en realidad que suceda, usando el parámetro –Whatif, que es muy práctico.

Get-process | Stop-Process -Whatif

La ejecución de este parámetro en Windows PowerShell da como resultado una serie de declaraciones que indican lo que los cmdlets hubieran realizado sin ejecutarse de verdad. El sistema de ayuda en pantalla de Windows PowerShell (al que se puede obtener acceso mediante el alias help) aún no ofrece información sobre el parámetro –Whatif, pero téngalo en cuenta. Se trata de una excelente herramienta para probar secuencias de comandos y cmdlets sin realizar ninguna operación que pueda llevar a errores o interrumpir el sistema.

Conclusión

Entre las características que no se incluyeron en esta versión de Windows PowerShell, posiblemente la más significativa es la compatibilidad con Active Directory® Services Interface (ADSI). Si bien Windows PowerShell puede emplear clases .NET muy sólidas que funcionan con Active Directory y otros servicios del directorio, aún no dispone de un cmdlet Get-ADSIObject apropiado. El resultado es que es un poco difícil trabajar con objetos del directorio.

Además, Windows PowerShell suele ofrecer varias maneras de realizar la misma tarea. Eso está muy bien, pero puede hacer que el aprendizaje de Windows PowerShell sea algo más confuso, ya que para cualquier tarea en particular, podrá observar una media docena de ejemplos de cómo realizarla.

Todo esto se arreglará con el paso del tiempo y el equipo de Windows PowerShell seguirá incorporando características y capacidades al producto. Para mantenerse informado, visite el blog del equipo.

Don Jones es fundador de ScriptingAnswers.com y coautor de Windows PowerShell: TFM (SAPIEN Press, 2006). Póngase en contacto con él en la dirección: don@scriptinganswers.com.

© 2008 Microsoft Corporation and CMP Media, LLC. Reservados todos los derechos; queda prohibida la reproducción parcial o total sin previa autorización.