Objetos en scripts de Bash, obsesión, quimera o... ¿la pastilla azul? Filosofada Infernal y chapa de la muerte

+1
0
-1

Hace ya unos meses, empecé a filosofarme a mí mismo sobre la posibilidad de hacer scripts en bash mediante programación orientada a objetos. Daba vueltas en mi cabeza y no podía dormir por las noches, la idea no me dajaba.

Así que, a ratos perdidos en el fondo de mi habitación, empecé a pensar seriamente sobre ello. ¿Por qué, si se llevaba a cabo, íba a ser mejor que lo que ya había? ¿qué me motivaba a pensar tan irresistiblemente en ello? ¿qué tenía? ¿qué necesitaba?

Me hice un script que pretendía ser una clase, anidé varias funciones y añadí ejecutores en la cabeza de cada función, una especie de "mórula de funciones" Lo importé en otro script y rápidamente empecé a ver las carencias de bash a la hora de cargar scripts en memoria. No era posible instanciar objetos del mismo tipo, ya que compartían variables y funciones.... y todas las variables eran públicas.

El tema era serio, si no podía separar funciones o privatizar variables, podría darse el caso de que tipos distintos sobreescribieran sus funciones o variables. Necesitaba un wrapper.

Pasaron las semanas y viendo el tinglado lo dejé de lado hasta que un día, haciendo un script de copias de seguridad, ví la luz.

Podía invocar a los ficheros "mórula de funciones" (a partir de ahora clases) desde el wrapper, de modo que sus funciones quedarían siempre separadas.

Así lo hice, la función que instanciaba la clase (New) creaba una copia del script que era llamada desde el wrapper cada vez que se invocaba la función. Pero todo no podía ser tan bonito y me dí cuenta de que las variables tanto públicas como privadas no eran persistentes entre ejecución y ejecución. Era obvio.

Qué podía hacer yo ante semejante problema ¿cómo iba a hacer que las variables fueran persistentes?

Dejé pasar el tiempo una vez más y un día, trabajando con java beans me vino la inspiración. La respuesta estaba en el wrapper. El wrapper creaba una copia del script de clase cada vez que una clase era instanciada, luego entonces, podía declarar las variables en las clases, de algún modo especial, y hacer que el wrapper las manejase cada vez que un objeto fuese referenciado.

A éstas alturas, mi cabeza daba vueltas y espumosas ideas brotaban de mi cerebro intentando retener las posibles implementaciones, que no es que estuviera borracho, sólo un poco mareado despues de una noche de juerga.

¿Cómo implementarlo? Ésa era la buena, la pregunta que engordaría mis ojeras. Dios, que lío. Probé haciendo una declaración de las variables, algo así como una directiva al principio de cada clase (mórula de funciones) e hice que el wrapper parseara éstas "directivas" cada vez que el objeto era referenciado y.... éxtio. No me lo podía creer.

Ahora los scripts de funciones se comportaban como "cosas" muy parecidas a los objetos de la POO. Ahora sólo quedaba impelementar objetos. Un objeto para manejar cadenas de carácteres, para operar con números decimales, operaciones sobre las redes, sockets....

Y en éso estamos. A ratos, me voy implementando objetos hasta que tenga los suficientes como para empezar a substituir mis antiguos scripts por la tenología punta en OOPScripting (sí le he puesto nombre, que pasa)

¿Os imagíais lo bueno que sería poder trabajar con éso? xDD os haré una demostración:

Se necesita un script que obtenga la IP, la MAC y si es posible la Puerta de enlace de cada interfaz conectada al equipo. Después la puerta enlace predeterminada.

Acepto sugerencias. Yo lo he solucionado así (13 líneas efectivas):

. objectWrapper.sh

New Interfaces ifaces
New Route ro


pr $ifaces.getIfaceNames | while read -d " " i
do
	ip=$(pr $ifaces.getIfaceIP $i)
	mac=$(pr $ifaces.getIfaceMAC $i)
	gw=$(pr $ro.getGateway $i)
	echo -e "\nIface: $i\t IP: $ip\tMAC: $mac \c"
	echo -e "\tGateway: $gw"
done

echo Pasarela por Defecto: $(pr $ro.getDefaultGateway)

Unload $ifaces
Unload $ro

¿En cuántas líneas lo haríais?

objectWrapper es el wrapper de objetos, Interfaces y Route son clases, $ifaces y $ro representan los objetos instanciados. New instancia los objetos y Unload los descarga (borra todos los ficheros intermedios que se generan) "pr" sería la llamada al wrapper. Sin ésto, de momento, no funciona nada.

Contadme cualquier cosa que se os ocurra, si queréis el "framewrok" postead y profundizaré en el tema.

Suerte a todos!

Comentarios

Imagen de slap

Profundiza, profundiza... ;)

Saludos.


0000 start out (+FD),A
           ld  BC, +7FFF
           jp 03CB, RAM-CHECK

http://7grados.injiniero.es

Saludos.

0000 start out (+FD),A
           ld  BC, +7FFF
           jp 03CB, RAM-CHECK

http://www.injiniero.es

Imagen de daniel_perella

Pretendo profundizar, pero la cosa iría más rápido si hubiera alguna alma caritativa que me quisiera echar un cable. Os dejo aquí una plantilla de objeto. Muchas gracias por leerte semejante ida de olla.

#!/bin/bash

# Importar el wrapper para objetos
. objectWrapper.sh

function objeto {

# Declaración de las propiedades que se usarán en 
# todo el objeto, serán públicas.

#Property=propiedad1
#Property=propiedad2

	function metodoUno {
		echo "Metodo Uno Ejecutado"
	}
	function metodoDos {
		echo "Metodo Uno Ejecutado"
	}
	function getterPropiedadUno {
		GETPROPERTY $0 propiedad1
	}
	function getterPropiedadDos {
		GETPROPERTY $0 propiedad2
	}
	function setterPropiedadUno {
		SETPROPERTY $0 propiedad1 $*
	}
	function setterPropiedadDos {
		SETPROPERTY $0 propiedad2 $*
	}
	$*
}
objeto $*

Como se puede observar, las propiedades se declaran mediante una directiva "#Property=nombre" y para hacerlas persistentes el wrapper (que lo pondré otro día, si a la gente le interesa) implementa los métodos SETPROPERTY y GETPROPERTY que manejan las variables.

Sorry for the chapa!

-----------------------------------------------------------------------------------------

Por favor, leed la documentación, que para algo la escribimos...

http://ubuntulinuxafondo.blogspot.com/

-----------------------------------------------------------------------------------------

Por favor, leed la documentación, que para algo la escribimos...

http://ubuntulinuxafondo.blogspot.com/

Imagen de Goyo

Otra cosa no sé, pero bonito es un rato. Y se entiende, excepto el pr que parece un poco arbitrario (¿lo es?). ¿Qué tal en un estilo más purista?

ip=$(send $ifaces getIfaceIP $i)

O algo así.

Imagen de daniel_perella

Pues estaría bien. Además me gustaría eliminar el "pr". El problema es en cómo está hecho el wrapper. De alguna manera hay que decirle al wrapper que tiene que ejecutar lo que tiene que ejecutar, así que de momento lo hago mediante ésta abstracción... Todas las sugerencias son bienvenidas. Gracias por comerte ése ladrillo-post.

Para vuestro disfrute, os dejo aquí el objectWrapper.sh:

#!/bin/bash

function SETPROPERTY {
	# objeto propiedad valor
	ob=$(echo $1 | cut -d "-" -f 2)
	if test -e $ob.var 
	then 
		cat $ob.var | grep -v "$2" > $1.var
	fi
	echo "$2=$3" >> $ob.var
}

function GETPROPERTY {
	# p=Objeto value=Propiedad
	ob=$(echo $1 | cut -d "-" -f 2)
	if test -e $ob.var; then r=$(cat $ob.var | grep -w "$2" | cut -d "=" -f 2); fi
	echo -e "$r \c"
}

function New {
	# Instancia un objeto
	nm=$(echo $* | cut -d " " -f 2)
	ty=$(echo $* | cut -d " " -f 1)
	if [[ -e $ty.sh ]]; then 
		cp $ty.sh $ty.sh-$nm 
		chmod a+x $ty.sh-$nm
		export $nm=$ty.sh-$nm
	else
		echo "El Objeto "$ty" no existe en" $(pwd)
	fi
}


function Unload {
	if test -e $1; then rm $1; fi
	if test -e $1.var; then rm $1.var; fi
	o=$(echo $1 | cut -d "-" -f 2)
	if test -e $o.var; then rm $o.var; fi
}

function pr {
	o=$(echo $1 | cut -d "-" -f 1)
	p=$(echo $1 | cut -d "-" -f 2 | cut -d "." -f 1)
	m=$(echo $* | cut -d "." -f 3)
	sm=$(echo $1 | cut -d "." -f 3)
	property=$(echo $m | cut -d "=" -f 1)
	property=$(echo $property | cut -d " " -f 2)
	value=$(echo $m | cut -d "=" -f 2)
	
	
	if [[ $sm = "GET" ]]
	then
		GETPROPERTY $o-$p $value
	else
		if [[ $sm = "SET" ]]
		then
			SETPROPERTY $o-$p $property $value
		else
			./$o-$p $m $4 $5 $6 $7 $8 $9
		fi
	fi
	
}

-----------------------------------------------------------------------------------------

Por favor, leed la documentación, que para algo la escribimos...

http://ubuntulinuxafondo.blogspot.com/

-----------------------------------------------------------------------------------------

Por favor, leed la documentación, que para algo la escribimos...

http://ubuntulinuxafondo.blogspot.com/