Windows PowerShellReplanteamiento de la canalización

Don Jones

Se ha hablado mucho acerca de cómo Windows PowerShell es diferente, nuevo y emocionante; aunque se base en conceptos de la interfaz de línea de comandos que han existido durante décadas, principalmente en sistemas operativos basados en UNIX y Linux. Pero la terminología común que Windows PowerShell comparte con sus antepasados puede llevar

a que se pase por alto la verdadera flexibilidad y exclusividad de Windows PowerShell™ y su eminente idoneidad en un entorno Windows®.

Una de las características más mencionadas de Windows PowerShell es su canalización, pero también es, desafortunadamente, una de las peor comprendidas. Esto se debe a que depende de terminología definida durante los comienzos de los años setenta, que representó alguna vez una funcionalidad enteramente diferente y menos eficaz.

Origen de las canalizaciones

Uno de los primeros shell de Unix que se crearon fue el shell de Thompson, que era muy primitivo y sólo ofrecía los elementos de lenguaje de scripting más elementales, sin incluir variables. El shell tenía un diseño deliberadamente modesto, porque su único propósito real era la ejecución de programas. Sin embargo, introdujo un concepto clave mejorado con respecto a otros shell de la época: las canalizaciones. A través del uso de los símbolos < and >, se podía instruir al shell para que redireccionara la entrada y salida hacia y desde diferentes comandos. Un usuario podía, por ejemplo, redireccionar la salida de comando a un archivo.

Esta sintaxis fue ampliada luego para que la salida de un comando también se pudiera canalizar a la entrada de otro, permitiendo que largos scripts se encadenaran para realizar las tareas más complicadas. En la versión 4 del shell, se adoptó para la canalización el carácter de línea vertical "|" y de ahí pasó a ser conocido como el carácter de canalización. Incluso las primeras versiones de MS-DOS® implementaban canalización básica a través de estos caracteres, permitiendo a un usuario, por ejemplo, canalizar la salida del comando type en la entrada del comando more, para crear una visualización de texto largo en una página a la vez.

Aunque el shell de Thompson se consideraba muy inadecuado en la época en que se lanzó al mercado la versión 6 de Unix en 1975, el concepto de canalizaciones permanecía en la memoria de desarrolladores y usuarios de shell y se ha traspasado a varias tecnologías que se usan actualmente.

Texto de canalización

Una limitación de casi todos los shell es su naturaleza intrínsecamente basada en texto. En sistemas operativos basados en Unix, esto no es realmente una limitación, sino un reflejo de cómo funciona el mismo sistema operativo. Prácticamente cualquier recurso en Unix se puede representar como un archivo de algún tipo, lo que significa que la capacidad de canalizar texto de un comando a otro ofrece mucha eficacia y flexibilidad.

Sin embargo, el texto definitivamente limita en lo que se refiere a información de administración. Por ejemplo, si se presentara una lista de servicios que se ejecutan en un equipo Windows, seguramente podría encontrar la explicación. Quizás colocaría el nombre de servicio en la primera columna y su modo de inicio en la segunda. Su eficaz cerebro humano analizaría o traduciría instantánea y transparentemente la pantalla de texto en información significativa con la que pudiera trabajar. Sin embargo, a los equipos les falta mucho para ser así de inteligentes: para hacer que un equipo haga algo significativo con esa lista, tendría que decirle que la primera columna consiste de los caracteres 1 a 20, quizás, y que los caracteres 22 a 40 componen la segunda columna, etc.

Durante años, este tipo de análisis de archivos de texto fue la única manera que tuvieron los administradores para encadenar múltiples comandos. En realidad, los lenguajes de scripting tales como VBScript y Perl se destacan en la manipulación de cadenas principalmente porque necesitan poder aceptar la salida de texto de un programa o comando y, a continuación, analizar y transformar esa salida en alguna clase de datos útiles que se puedan usar para alguna tarea subsiguiente. He escrito trabajos de VBScript que aceptaban, por ejemplo, la salida de texto del comando Dir, analizaban nombres de archivo y fechas en la salida y, a continuación, movían los archivos antiguos y no usados a una ubicación de archivo. El análisis de la cadena es sumamente complicado, porque las excepciones (variaciones en los datos de entrada) casi siempre suceden, y necesitará replantear la lógica en el script para resolver todas las permutaciones posibles.

Como una forma de scripting o automatización administrativa en un entorno Windows, el análisis de cadenas no es tan útil. Esto se debe a que Windows no almacena mucha información en un formato de texto fácilmente accesible. En cambio, usa almacenes centrados en datos, tales como Active Directory®, el Registro de Windows y el almacén de certificados, para que los creadores de scripts tengan que usar primero una herramienta para generar alguna forma de salida de texto y, a continuación, un script para analizar ese texto y hacer algo con él.

Los objetos son más sencillos

Para los desarrolladores de software de Windows las cosas siempre han sido un poco más sencillas. Inicialmente, Microsoft desarrolló COM expresamente para representar el complejo funcionamiento interno de Windows de un modo más sencillo de usar. En la actualidad, Microsoft® .NET Framework continúa esa misma tarea; representar el funcionamiento interno de software de un modo estandarizado.

Genéricamente, tanto COM como .NET exponen los elementos como objetos. (Un desarrollador de software quizás se ofenda por esta simplificación, pero a los fines de nuestra discusión, un término sencillo es suficiente). Todos estos objetos tienen miembros de distintos tipos. A nuestros fines, las propiedades y los métodos de los objetos son aquello en lo que estamos más interesados. Una propiedad describe esencialmente un objeto de alguna manera, o bien modifica el objeto o su comportamiento. Por ejemplo, un objeto de servicio quizás tenga una propiedad que contiene el nombre del servicio y otra propiedad que contiene el modo de inicio del servicio. Los métodos hacen que un objeto tome alguna acción. Un objeto de servicio quizás tenga los métodos denominados Stop, Start, Pause y Resume, por ejemplo, que representan las diversas acciones que se pueden tomar con un servicio.

Desde el punto de vista de la programación o de scripting, se hace referencia a los miembros del objeto mediante una notación con puntos. Con frecuencia los objetos se asignan a variables, que le ofrecen una manera de manipular físicamente el objeto. Por ejemplo, si tengo un servicio asignado a la variable $service, puedo detener ese servicio mediante la sintaxis $service.Stop. O bien, puedo recuperar el nombre para mostrar del servicio al mostrar $service.Name.

Objetos en la canalización

Debido a que Windows es un sistema operativo grande y complejo, y puesto que no almacena sus datos de administración en representaciones de estilo texto, las técnicas más antiguas de shell no son muy convenientes para él. Por ejemplo, supongamos que tengo una herramienta de línea de comandos, denominada SvcList.exe que genera una lista con formato de servicios y sus modos de inicio. En el shell de línea de comandos de Windows (un shell que tiene firmemente sus raíces en el shell MS-DOS de antiguas décadas) quizás pueda ejecutar algo así:

SvcList.exe | MyScript.vbs 

Esta instrucción recupera una lista de servicios y canaliza esa lista en un archivo VBScript. Tendría que escribir el archivo VBScript para analizar la lista con formato y hacer cualquier cosa que desee que haga; quizás mostrar todos los servicios con un modo de inicio Deshabilitado. Esta tarea demandaría mucho tiempo. En última instancia, el problema es que SvcList.exe tiene una salida que es exclusiva; no comparte un formato común que otros comandos pueden consumir fácilmente para usar su salida.

Los objetos, sin embargo, pueden ofrecer ese formato común, y ese es el motivo por el cuál la canalización de Windows PowerShell funciona con objetos completos, no sólo con texto. Cuando ejecuta un cmdlet como Get-WMIObject, produce un grupo (o una colección, en términos de programador) de objetos. Cada objeto viene completo con propiedades y métodos que permiten su manipulación. Si canalizo los objetos al cmdlet Where-Object, los puedo filtrar para que se muestren sólo los objetos que deseo. Where-Object no necesita analizar ningún texto porque no recibe ningún texto, recibe objetos. Por ejemplo:

Get-WMIObject Win32_Service | Where-Object {$_.StartMode -eq “Disabled” }

O bien, si prefiere la sintaxis más corta disponible a través de alias:

gwmi Win32_Service | where {$_.StartMode -eq “Disabled” }

Lo que resulta interesante es que Windows PowerShell siempre pasa los objetos a la canalización. Recién al final de la canalización, cuando no hay ningún otro lugar adonde pasar los objetos, el shell genera una representación de texto de los objetos mediante sus reglas de formato integradas. Por ejemplo, considere lo siguiente:

Gwmi Win32_Service | where {$_.StartName –eq “LocalSystem” } | select Name,StartMode

Este conjunto de tres cmdlets recupera todos los servicios de mi equipo local, filtra todos los que no usan la cuenta LocalSystem para iniciar sesión y pasa el resto al cmdlet Select-Object, que sólo muestra dos propiedades (Name y StartMode) que he pedido que seleccione. El resultado es un informe sencillo de servicios que inician sesión como LocalSystem (quizás para fines de auditoria de seguridad).

Dado que todos los cmdlets comparten un formato común de datos (objetos), tienen la capacidad de compartir datos entre sí, sin ningún análisis complicado de cadena. Además, dado que Windows PowerShell tiene una capacidad nativa para crear la representación de texto de un objeto, el final de esta canalización seguro será una salida de texto que yo, una persona, pueda leer. La figura 1 muestra un ejemplo de la salida generada.

Figura 1 Salida del texto generada por una serie de cmdlets canalizados que pasan objetos

Figura 1** Salida del texto generada por una serie de cmdlets canalizados que pasan objetos **

La emoción de las canalizaciones

El motivo por el cuál la canalización en Windows PowerShell es tan asombrosa es que, en Windows PowerShell, todo es un objeto, completo con propiedades y métodos que puede usar. Incluso un archivo de texto es técnicamente una recopilación de objetos de cadena, donde cada línea en el archivo actúa como un objeto exclusivo e independiente de cadena. Por ejemplo, cree un archivo de texto (con el Bloc de notas) denominado C:\Computers.txt. Complete el archivo con texto y, a continuación, ejecute lo siguiente en Windows PowerShell:

Get-Content C:\Computers.txt | Select-Object Length | Format-List

O bien, nuevamente, si prefiere escribir menos, puede usar alias:

gc C:\Computers.txt | select Length | fl

Este código proporciona una lista que indica la longitud de cada línea del archivo de texto, en caracteres. Get-Content recupera los objetos de cadena del archivo, Select-Object toma la propiedad Length de cada uno y, a continuación, Format-List crea la salida de texto agradable y legible para el usuario. Aunque quizás esto no sea una herramienta administrativa práctica para usar, demuestra que incluso algo tan sencillo como una línea de texto es un objeto en Windows PowerShell.

Al poder canalizar objetos de cmdlet en cmdlet, o incluso de cmdlet en un script, se permite la creación de "frases de una línea" increíblemente eficaces. Son simples cadenas de cmdlets asociadas en una larga canalización que refina aún más un conjunto de objetos para darle exactamente lo que desea. Prácticamente sin scripting ni programación de ningún tipo, los cmdlets de Windows PowerShell, conectados en una canalización apropiada, pueden lograr resultados notables.

Compatibilidad con futuras generaciones

El hecho de que futuros productos de servidor de Microsoft se basen también en Windows PowerShell, extiende esta funcionalidad. Al implementar un nuevo equipo con Exchange Server 2007, por ejemplo, puede usar Windows PowerShell para recuperar todos los buzones, filtrar todos los buzones que no estén en la oficina donde estará ubicado el nuevo servidor y, a continuación, mover esos buzones al nuevo servidor, todo en una sola línea de texto sin scripting. El equipo de Exchange Server 2007 ha publicado una larga lista de eficaces frases de una línea. Estas líneas demuestran en realidad el poder de la canalización y las tareas administrativas que pueden realizar.

El truco con Windows PowerShell es entender que, aunque está basado en principios y filosofías establecidos desde hace tiempo en el mundo Unix, esta nueva herramienta es exclusivamente idónea para la administración de Windows. No permita que ninguna coincidencia de terminología le haga pensar equivocadamente que Windows PowerShell es sólo una imitación de shell de Unix para Windows. Windows PowerShell contiene conceptos completamente nuevos que aprovechan la plataforma de Windows, y están estrechamente asociados a la manera en que Windows hace las cosas.

Don Jones es MVP de Windows PowerShell y autor de Windows PowerShell 101 (ScriptingTraining.com). Puede ponerse en contacto con Don en la dirección www.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.