tag:blogger.com,1999:blog-27201954216027511852024-03-08T06:25:40.720-03:00Recetas con Debian"¿Cómo fué que hice tal o cual cosa..?" ahora lo documentaré aqui! y estaré feliz de hacer mi aporte, como agradecimiento a la comunidad.Analía Lorenzattohttp://www.blogger.com/profile/07923900145462112039noreply@blogger.comBlogger22125tag:blogger.com,1999:blog-2720195421602751185.post-72008905822712169862010-05-24T09:01:00.002-03:002010-05-24T09:03:35.976-03:00"Brevity is Beautiful"Analía Lorenzattohttp://www.blogger.com/profile/07923900145462112039noreply@blogger.com0tag:blogger.com,1999:blog-2720195421602751185.post-85713696088875204592010-05-02T13:02:00.002-03:002010-05-02T13:03:33.299-03:00Cómo concatenar archivos en bash<span style="font-weight:bold;">Concatenar archivos con bash</span><br /><br />Muchas veces tengo, por ej., los archivos guia1.txt guia2.txt... guian.txt en el directorio guias y los quiero concantenar a todos en un único archivo:<br /><br />Utilizaremos como estándar de documentación:<br /># para referirnos a superusuario (root)<br />$ para referirnos a un usuario<br /><br /><span style="font-weight:bold;">$ for i in $(ls /guias/guia*.scm); do<br />> cat $i >> guia_completa.txt; <br />> done<br /><br />$less guia_completa.txt</span><br /><br />Finalmente el archivo "guia_completa.txt" tiene todos las guias concatenadas en orden.Analía Lorenzattohttp://www.blogger.com/profile/07923900145462112039noreply@blogger.com2tag:blogger.com,1999:blog-2720195421602751185.post-34134473642827042482010-05-02T12:16:00.008-03:002010-05-02T12:47:32.982-03:00Programación Funcional con Scheme parte III;;----------------------------------------------------------------;;<br />;; Ejercicio 1 <br />;; Contrato: dada una posición en una lista,<br />;; devuelve el elemento en ESA posición, sin <br />;; modificar la lista. <br />;;-----------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">obtener_elemento</span> (lambda (n lista)<br /> (letrec(<br /> (devolver_n (lambda (cont n lista) <br /> (if (null? lista)<br /> "null"<br /> (if (= n cont)<br /> (car lista)<br /> (devolver_n (+ cont 1) n (cdr lista))<br /> );if<br /> );if<br /> );lambda<br /> );devolver_n<br /> )<br /> (devolver_n 1 n lista)<br /> );let <br /> );lambda<br />);define <br /><br />(obtener_elemento 1 (list '11 '12 '13 '14 '())) ;=> 11<br /><br /><br />;;---------------------------------------------------------------------------;;<br />;; Contrato: dada una posicion en una lista, <br />;; devuelve el lado izquierdo de la misma.<br />;;---------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">devolver_l_izquierdo</span> (lambda (posicion lista)<br /> (letrec( <br /> (largo (length lista))<br /> (devolver_lista (lambda (cont pos lista) <br /> (if (null? lista)<br /> "null"<br /> (if (= pos cont)<br /> (car lista)<br /> (cons (car lista) (devolver_lista (+ cont 1) pos (cdr lista)))<br /> <br /> );if<br /> );if<br /> );lambda<br /> );devolver_n<br /> )<br /> <br /> (devolver_lista 1 posicion lista)<br /> );letrec<br /> );lambda<br />);define <br /><br />(devolver_l_izquierdo 3 (list '11 '12 '13 '14 '5 '7)) ;=> (11 12 . 13)<br />(devolver_l_izquierdo 9 (list '11 '12 '13 '14 '5 '7)) ;=> (11 12 13 14 5 7 . "null")<br /><br /><br />;;---------------------------------------------------------------------------;;<br />;; Contrato: eliminar de la lista el elemento en <br />;; la posicion indicada, y devolver el resto de la <br />;; lista.<br />;;---------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">extraer_elemento</span> (lambda (pos listado)<br /> (letrec (<br /> (funcion (lambda (contador posicion lista)<br /> (if (null? lista)<br /> '()<br /> (if (= contador posicion)<br /> (cdr lista) <br /> (cons (car lista) (funcion (+ contador 1) posicion (cdr lista)))<br /> );if<br /> );if<br /> );lambda<br /> );funcion<br /> )<br /> (funcion 1 pos listado)<br /> );letrec <br /> );lambda<br />);define<br /><br />(extraer_elemento 5 (list 10 20 30 40 50));=>(10 20 30 40)<br /><br /><br />;;---------------------------------------------------------------------------;;<br />;; Contrato: dada una lista, devolver un nueva <br />;; lista con los elementos de la primera <br />;; invertidos.<br />;; Requiere de: OBTENER_ELEMENTO(N LISTA), <br />;; EXTRAER_ELEMENTO(N LISTA). <br />;;---------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">invertir_lista </span>(lambda (listado)<br /> (letrec (<br /> (invertir (lambda (contador lista)<br /> (if (null? lista)<br /> '()<br /> (cons (obtener_elemento (length lista) lista) (invertir_lista (extraer_elemento (length lista) lista)))<br /> );if <br /> );lambda<br /> );invertir <br /> )<br /> (invertir 1 listado)<br /> );letrec<br /> );lambda<br />);define<br /><br />(invertir_lista (list 5 4 3 2 1 0));=>(0 1 2 3 4 5)<br /><br /><br />;;---------------------------------------------------------------------------;;<br />;; Contrato: dadas dos listas, concatenarlas. <br />;; Donde la segunda lista aparezca en orden <br />;; inverso.<br />;;---------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">concat-inv</span> (lambda (lista1 lista2)<br /> (letrec(<br /> (concatenar (lambda (l1 l2) <br /> (if (and (null? l1) (null? l2))<br /> '()<br /> (if (null? l1)<br /> (cons (car l2) (concatenar l1 (cdr l2)))<br /> (if (null? l2) <br /> (cons (car l1) (concatenar (cdr l1) '()))<br /> (cons (car l1) (concatenar (cdr l1) l2))<br /> );if<br /> );if<br /> );if<br /> ) ;lambda<br /> );concatenar<br /> )<br /> ;(concatenar lista1 (reverse lista2)); REVERSE es una función de Scheme.<br /> (concatenar lista1 (invertir_lista lista2))<br /> );let*<br /> );lambda <br />);define <br /><br />(concat-inv '(1 2) '(8 7 6 5 4 3)) ;=> (1 2 3 4 5 6 7 8 )<br /><br /><br />;;--------------------------------------------------------------------------;;<br />;; Ejercicio 2 <br />;; Contrato: dados una lista y un elemento. Si el <br />;; elemento se encuentra en la lista devuelve #t, <br />;; caso contrario #f.<br />;;---------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">elemento_en_lista</span> (lambda (elemento lista)<br /> (if (null? lista)<br /> #f<br /> (if (eqv? elemento (car lista))<br /> #t<br /> (elemento_en_lista elemento (cdr lista))<br /> );if<br /> );if<br /> );lambda<br />);define<br /><br />;(elemento_en_lista '5 (list 1 2 3 4 5 6)) ;=> #t<br /><br /><br />;;---------------------------------------------------------------------------;;<br />;; Contrato: dadas dos listas y un elemento. <br />;; Si el elemento se encuentra en AMBAS listas <br />;; devuelve #t, caso contrario #f.<br />;;---------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">n_en_2_listas</span> (lambda (elemento lista1 lista2)<br /> (if (or (null? lista1) (null? lista2))<br /> #f<br /> (if (and (n_en_lista elemento lista1) (n_en_lista elemento lista2))<br /> #t<br /> #f<br /> );if<br /> );if<br /> );lambda<br />);define<br /><br />;(n_en_2_listas '5 (list 3 4 2 1) (list 1 2 3 4 6));=> #f<br />;(n_en_2_listas '5 (list 3 4 5 2 1) (list 1 2 3 6));=> #f<br />;(n_en_2_listas '5 (list 3 4 2 1) (list 1 2 3 4 5 6));=> #f<br />;(n_en_2_listas '5 (list 5 3 4 2 1) (list 5 1 2 3 4 5 6))=> #t<br /><br /><br />;;--------------------------------------------------------------------------;;<br />;; Ejercicio 3 <br />;; Dado una lista y un elemento, devolver la cantidad <br />;; de atomos a la izquierda del elemento.<br />;;---------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">posicion_de_elemento</span> (lambda (elem listado)<br /> (letrec (<br /> (devolver_posicion (lambda (posicion elemento lista)<br /> (if (null? lista)<br /> "null"<br /> (if (eqv? (car lista) elemento)<br /> posicion<br /> (devolver_posicion (+ posicion 1) elemento (cdr lista))<br /> );if<br /> );if<br /> );lambda<br /> );devolver_posicion<br /> )<br /> (devolver_posicion 0 elem listado)<br /> );letrec<br /> );lambda<br />);define<br /><br />(posicion_de_elemento 0 (list 'a 'b 'c 4 5 1 'd));=> "null"<br />(posicion_de_elemento 1 (list 'a 'b 'c 4 5 1 'd));=> 5<br /><br /><br />;;---------------------------------------------------------------------------;;<br />;; Ejercicio 4 <br />;; Contrato: dados una lista y un elemento. Si el <br />;; elemento no se encuentra en la lista es agregado <br />;; al final de la misma.<br />;;---------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">agregar_en_lista_si_no_esta</span> (lambda (elemento lista)<br /> (if (null? lista)<br /> '()<br /> (if (eqv? (car lista) elemento)<br /> (agregar_en_lista_si_no_esta (cdr lista))<br /> (cons lista elemento)<br /> );if<br /> );if<br /> );lambda<br />);define<br /><br />(agregar_en_lista_si_no_esta 42 (list '38 '39 '40 '41 )) ;=> (38 39 40 41 42)<br /><br /><br />;;---------------------------------------------------------------------------;;<br />;; Ejercicio 5 <br />;; Contrato: en caso de que el año sea bisiesto <br />;; devuelve 29, caso contrario devuelve 28.<br />;;---------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">bisiesto</span> (lambda (año)<br /> (if (= (modulo año 400) 0)<br /> 29<br /> (if (and (= (modulo año 4) 0) (not(= (modulo año 100) 0)))<br /> 29;es bisiesto<br /> 28;no bisiesto<br /> );if<br /> );if<br /> );lambda<br />);define<br /><br />;(bisiesto 1900);=> 28<br />;(bisiesto 1700);=>28<br />;(bisiesto 1600);=>29<br />;(bisiesto 2004);=>29<br /><br /><br />;;---------------------------------------------------------------------------;;<br />;; Contrato: dada una posición en una lista, <br />;; devuelve el elemento en ESA posición.<br />;;---------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">obtener_elemento</span> (lambda (n lista)<br /> (letrec(<br /> (devolver_n (lambda (cont n lista)<br /> (if (null? lista)<br /> "null"<br /> (if (= n cont)<br /> (car lista)<br /> (devolver_n (+ cont 1) n (cdr lista))<br /> );if<br /> );if<br /> );lambda<br /> );devolver_n<br /> )<br /><br /> (devolver_n 1 n lista)<br /> );let <br /> );lambda<br />);define <br /><br />;;---------------------------------------------------------;;<br />;; Contrato: determinar si una fecha <br />;; ingresada es valida. <br />;;---------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">fecha_es_valida</span>( lambda (lista)<br /> (let* ( <br /> (año (caddr lista))<br /> (mes (cadr lista))<br /> (dia (car lista))<br /> (meses (list 31 (bisiesto año) 31 30 31 30 31 31 30 31 30 31))<br /> ) <br /> (if (null? lista)<br /> #f<br /> (if (< año 0) <br /> (display "Ingresaste un año que no es válido")<br /> (if (and (> dia 0) (< dia (+ (obtener_elemento mes meses) 1)))<br /> #t<br /> (display "Cantidad de días no válido para ese mes")<br /> );if<br /> );if<br /> );if<br /> );let*<br /> );lambda<br />);define <br /> <br />(fecha_es_valida (list 12 12 1986)) ;=> #t<br />(fecha_es_valida (list 29 02 1900)) ;=> #f (1900 no fue año bisiesto)<br /><br /><br />;;---------------------------------------------------------------------;;<br />;; Ejercicio 6 <br />;; Contrato: Insertar un elemento en una lista en<br />;; la posición indicada.<br />;;---------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">insertar_elemento </span>(lambda (pos elem listado)<br /> (letrec (<br /> (largo (length listado))<br /> (insertar (lambda (contador posicion elemento lista)<br /> (if (null? list)<br /> (cons lista elemento)<br /> (if (= contador posicion)<br /> (cons elemento lista)<br /> (cons (car lista)(insertar (+ contador 1) posicion elemento (cdr lista)))<br /> );if<br /> );if<br /> );lambda<br /> );insertar<br /> )<br /> (insertar 1 pos elem listado)<br /> );letrec<br /> );lambda<br />);define <br /><br />;(insertar_elemento 6 '6 (list 1 2 3 4 5));<br /><br /><br />;;---------------------------------------------------------------------------;;<br />;; Contrato: dados una lista y un elemento. <br />;; Si el elemento se encuentra en la lista <br />;; devuelve su posicion, caso contrario "null".<br />;;---------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">posicion_en_lista </span>(lambda (elem listado)<br /> (letrec (<br /> (devolver_posicion (lambda (posicion elemento lista)<br /> (if (null? lista)<br /> "null"<br /> (if (eqv? elemento (car lista))<br /> posicion<br /> (devolver_posicion (+ posicion 1) elemento (cdr lista))<br /> );if<br /> );if<br /> );lambda<br /> );devolver_lista<br /> )<br /> (devolver_posicion 1 elem listado)<br /> );letrec<br /> );lambda <br />);define<br /><br />;(posicion_en_lista 's (list 'a 'n 'a 'l 'i 'a 's))<br /><br /><br />;;---------------------------------------------------------------------------;;<br />;; Contrato: dados una lista y un elemento. <br />;; Si el elemento se encuentra en la lista <br />;; devuelve #t, caso contrario #f.<br />;;---------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">elemento_en_lista</span> (lambda (elemento lista)<br /> (if (null? lista)<br /> #f<br /> (if (eqv? elemento (car lista))<br /> #t<br /> (elemento_en_lista elemento (cdr lista))<br /> );if<br /> );if<br /> );lambda<br />);define<br /><br />;(elemento_en_lista '4 (list 1 2 3))<br /><br /><br />;;---------------------------------------------------------------------------;;<br />;; Contrato: agrego el elemento junto a los demás<br />;; elementos iguales de la lista o al final de la<br />;; misma, en caso de no encontrar semejantes. <br />;;---------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">agrupar_elem_lista<span style="font-weight:bold;"></span></span> (lambda (elemento lista)<br /> (if (null? lista)<br /> (cons lista elemento)<br /> (if (elemento_en_lista elemento lista)<br /> (insertar_elemento (posicion_en_lista elemento lista) elemento lista)<br /> (insertar_elemento (+ (length lista) 1) elemento lista)<br /> );if<br /> );if<br /> );lambda<br />);define <br /> <br />;(agrupar_elem_lista '4 '(1 2 3 4 5 6 4)) ;=>(1 2 3 4 4 5 6 4)<br /><br /><br />;;---------------------------------------------------------------------------;;<br />;; Contrato: la función AGRUPAR recibe dos <br />;; argumentos: lista y elemento, en cualquier <br />;; orden. Comprueba cuál de ellos es un elemento<br />;; y cuál una lista. A continuación agrega el <br />;; elemento junto a los demás elementos iguales<br />;; de la lista o al final de la misma, en caso <br />;; de no encontrar semejantes. <br />;;---------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">agrupar </span>(lambda (parametro1 parametro2)<br /> (if (list? parametro1) <br /> (agrupar_elem_lista parametro2 parametro1)<br /> (agrupar_elem_lista parametro1 parametro2)<br /> );if<br /> );lambda<br /> );define<br /><br />(agrupar '(a b b c c) 'c);=> (a a b b c c c)<br />(agrupar 'c '(a b b c c));=> (a a b b c c c)<br /><br /><br />;;---------------------------------------------------------------------------;;<br />;; Ejercicio 7 <br />;; Contrato dadas dos listas: l1 y l2, concatena <br />;; las mismas devolviendo un única lista resultante <br />;; por los elementos de l1 más los de l2. <br />;; Aplicable a listas propias e impropias. <br />;;---------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">concatenar_listas</span> (lambda (lista1 lista2)<br /> (if (and (null? lista1) (null? lista2))<br /> '()<br /> (if (not (null? lista1))<br /> (cons (car lista1) (concatenar_listas (cdr lista1) lista2))<br /> (if (not (null? lista2))<br /> (cons (car lista2) (concatenar_listas lista1 (cdr lista2)))<br /> '()<br /> );if<br /> );if<br /> );if<br /> );lambda<br />);define<br /><br />;(concatenar_listas (list '0 '1 '2 '3) (list '4 '5 '6));=> (0 1 2 3 4 5 6 ) Probado con listas impropias.<br /><br /><br />;;---------------------------------------------------------------------------;;<br />;; Contrato: la función APLANAR reciba como <br />;; argumento una expresión simbólica y elimina <br />;; todos los paréntesis que aparezcan en esa <br />;; expresión, devolviendo como resultado una <br />;; lista con todos los átomos que aparezcan en<br />;; el argumento.<br />;; Requiere de: (CONCATENAR l1 l2)<br />;;---------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">aplanar</span> (lambda (lista)<br /> (if (null? lista) <br /> '()<br /> (if (list? (car lista))<br /> (concatenar_listas (aplanar (car lista)) (aplanar (cdr lista)))<br /> (concatenar_listas (list (car lista)) (aplanar (cdr lista)))<br /> );if<br /> );if<br /> );lambda<br />);define<br /><br />(aplanar '( (1 2 3) (9 (2 3 4) ) ( ( ( ( 3 4 ( 7 ) ) ) ) ) ));=> (1 2 3 9 2 3 4 3 4 7)<br />(aplanar '( 1 2 3)) ;= >(1 2 3)<br /><br /><br />;;---------------------------------------------------------------------------;;<br />;; Ejercicio 8 <br />;; Contrato: eliminar de la lista el elemento <br />;; indicado, y devolver el resto de la lista.<br />;;---------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">extraer_elemento</span> (lambda (pos listado)<br /> (letrec (<br /> (funcion (lambda (contador posicion lista)<br /> (if (null? lista)<br /> '()<br /> (if (= contador posicion)<br /> (cdr lista)<br /> (cons (car lista) (funcion (+ contador 1) posicion (cdr lista)))<br /> );if<br /> );if<br /> );lambda<br /> );funcion<br /> )<br /> (funcion 1 pos listado)<br /> );letrec <br /> );lambda<br />);define<br /><br />;(extraer_elemento 1 (list 10 20 30 40 50));=>(10 20 30 40)<br /><br /><br />;;---------------------------------------------------------------------------;;<br />;; Contrato: dada una posición en una lista,<br />;; devuelve el elemento en ESA posición.<br />;;---------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">obtener_elemento</span> (lambda (n lista)<br /> (letrec(<br /> (devolver_n (lambda (cont n lista)<br /> (if (null? lista)<br /> "null"<br /> (if (= n cont)<br /> (car lista)<br /> (devolver_n (+ cont 1) n (cdr lista))<br /> );if<br /> );if<br /> );lambda<br /> );devolver_n<br /> )<br /><br /> (devolver_n 1 n lista)<br /> );let <br /> );lambda<br />);define <br /><br />;(obtener_elemento 1 (list '11 '12 '13 '14 '())) ;=> 11<br /><br /><br />;;------------------------------------------------------------------------;;<br />;; Contrato: dada una lista, rotar el último <br />;; elemento hacia la izquierda. <br />;; Requiere de: (OBTENER_ELEMENTO pos lista) <br />;; (EXTRAER_ELEMENTO pos lista) <br />;;------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">rotar_izquierda </span>(lambda (lista)<br /> (if (null? lista)<br /> '()<br /> (cons (obtener_elemento (length lista) lista) (extraer_elemento (length lista) lista))<br /> );if<br /> );lambda<br />);define <br /><br />;(rotar_izquierda (list 1 2 3 4 5 6 0)); → (0 1 2 3 4 5 6)<br /><br /><br />;;---------------------------------------------------------------------------;;<br />;; Contrato dadas dos listas: l1 y l2, concatena <br />;; las mismas devolviendo un única lista resultante <br />;; por los elementos de l1 más los de l2. <br />;; Aplicable a listas propias e impropias. <br />;;---------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">concatenar_listas</span> (lambda (lista1 lista2)<br /> (if (and (null? lista1) (null? lista2))<br /> '()<br /> (if (not (null? lista1))<br /> (cons (car lista1) (concatenar_listas (cdr lista1) lista2))<br /> (if (not (null? lista2))<br /> (cons (car lista2) (concatenar_listas lista1 (cdr lista2)))<br /> '()<br /> );if<br /> );if<br /> );if<br /> );lambda<br />);define<br /><br />;(concatenar_listas (list '0 '1 '2 '3) (list '4 '5 '6));=>(0 1 2 3 4 5 6) Probado con listas impropias.<br /><br /><br />;;---------------------------------------------------------------------------;;<br />;; Contrato: la función APLANAR reciba como <br />;; argumento una expresión simbólica y elimina<br />;; todos los paréntesis que aparezcan en esa<br />;; expresión, devolviendo como resultado una<br />;; lista con todos los átomos que aparezcan<br />;; en el argumento.<br />;; Requiere de: CONCATENAR_LISTAS(l1 l2) <br />;;---------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">aplanar</span> (lambda (lista)<br /> (if (null? lista)<br /> '()<br /> (if (list? (car lista))<br /> (concatenar_listas (aplanar (car lista)) (aplanar (cdr lista)))<br /> (concatenar_listas (list (car lista)) (aplanar (cdr lista)))<br /> );if<br /> );if<br /> );lambda<br />);define<br /><br />;(aplanar '( (1 2 3) (9 (2 3 4) ) ( ( ( ( 3 4 ( 7 ) ) ) ) ) ));=> (1 2 3 9 2 3 4 3 4 7)<br /><br /><br />;;----------------------------------------------------------------------;;<br />;; Contrato: dada una lista, rotar el último <br />;; elemento hacia la derecha. <br />;; Requiere de: APLANAR(lista) ;;<br />;;----------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">rotar_derecha</span> (lambda (lista)<br /> (if (null? lista)<br /> '()<br /> (aplanar (cons (extraer_elemento 1 lista) (list (obtener_elemento 1 lista))))<br /> );if <br /> );lambda<br />);define<br /><br />(rotar_derecha (list 5 0 1 2 3 4)); => (0 1 2 3 4 5)<br /><br /><br />;;----------------------------------------------------------;;<br />;; Ejercicio 9 <br />;; Contrato: dado un valor, devuelve el <br />;; cuadrado del mismo. <br />;;----------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">cuadrado</span> (lambda (x)<br /> (expt x 2)<br /> );lambda<br />);define <br /><br /><br />;;---------------------------------------------------------------------------;;<br />;; Contrato: dada una lista de valores, devuelve <br />;; una lista con cada uno de los cuadrados de la<br />;; primer lista. <br />;;---------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">calcula_cuadrados</span> (lambda (lista)<br /> (map<br /> (lambda (y)<br /> (cuadrado y)<br /> );lambda <br /> lista<br /> );map<br /> );lambda<br />);define <br /> <br />(calcula_cuadrados (list 1 2 3 4)); → (1 4 9 16)<br /><br /><br />;;---------------------------------------------------------------------------;;<br />;; Ejercicio 10 <br />;; Contrato: eliminar de la lista el elemento <br />;; indicado, y devolver el resto de la lista. <br />;;---------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">extraer_elemento_e</span> (lambda (elemento lista)<br /> (if (null? lista)<br /> '()<br /> (if (eqv? elemento (car lista))<br /> (extraer_elemento_e elemento (cdr lista))<br /> (cons (car lista) (extraer_elemento_e elemento (cdr lista)))<br /> );if<br /> );if<br /> );lambda<br />);define <br /><br />;(extraer_elemento_e 6 '(1 2 3 4 5 6));=> (1 2 3 4 5)<br /><br /><br />;;---------------------------------------------------------------------------;;<br />;; Contrato: dados una lista y un elemento. <br />;; Si el elemento se encuentra en la lista <br />;; devuelve #t, caso contrario #f.<br />;;---------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">elemento_en_lista</span> (lambda (elemento lista)<br /> (if (null? lista)<br /> #f<br /> (if (eqv? elemento (car lista))<br /> #t<br /> (elemento_en_lista elemento (cdr lista))<br /> );if<br /> );if<br /> );lambda<br />);define<br /><br />;(elemento_en_lista '5 (list 1 2 3 4 5 6));=> #t<br /><br /><br />;;-------------------------------------- ------------------------------------;;<br />;; Contrato: restar 2 listas. Devolver una lista <br />;; con los elementos de la primera lista que no <br />;; están en la segunda. <br />;; Requiere de: (EXTRAER_ELEMENTO_E e l)<br />;;---------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">restar_listas</span> (lambda (lista1 lista2)<br /> (if (and (null? lista1) (null? lista2))<br /> '()<br /> (if (null? lista2)<br /> lista1<br /> (if (elemento_en_lista (car lista2) lista1)<br /> (restar_listas (extraer_elemento_e (car lista2) lista1) (cdr lista2))<br /> (restar_listas lista1 (cdr lista2))<br /> );if<br /> );if<br /> );if<br /> );lambda<br />);define <br /> <br />;(restar_listas '(1 2 3 4 5 6 7 8 9) '(2 5 7 9)); => (1 3 4 6 8)<br />;(restar_listas '(1 2 3 4 5 6 7 8 9) '(1 2 3 4 5)); => (6 7 8 9)<br /><br /><br />;;---------------------------------------------------------------------------;;<br />;; Ejercicio 11 <br />;; Contrato dadas dos listas: l1 y l2, concatena <br />;; las mismas devolviendo un única lista resultado<br />;; de los elementos de l1 más los de l2. <br />;;---------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">concatenar_listas</span> (lambda (lista1 lista2)<br /> (if (and (null? lista1) (null? lista2))<br /> '()<br /> (if (not (null? lista1))<br /> (cons (car lista1) (concatenar_listas (cdr lista1) lista2))<br /> (if (not (null? lista2))<br /> (cons (car lista2) (concatenar_listas lista1 (cdr lista2)))<br /> '()<br /> );if<br /> );if<br /> );if<br /> );lambda<br />);define<br /><br />;(concatenar_listas (list '0 '1 '2 '3) (list '4 '5 '6));Probado con listas impropias.<br /><br /><br />;;---------------------------------------------------------------------------;;<br />;; Contrato: la función APLANAR reciba como <br />;; argumento una expresión simbólica y elimina <br />;; todos los paréntesis que aparezcan en esa <br />;; expresión, devolviendo como resultado una <br />;; lista con todos los átomos que aparezcan en <br />;; el argumento.<br />;; Requiere de: (CONCATENAR_LISTAS l1 l2)<br />;;---------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">aplanar</span> (lambda (lista)<br /> (if (null? lista)<br /> '()<br /> (if (list? (car lista))<br /> (concatenar_listas (aplanar (car lista)) (aplanar (cdr lista)))<br /> (concatenar_listas (list (car lista)) (aplanar (cdr lista)))<br /> );if<br /> );if<br /> );lambda<br />);define<br /><br />;(aplanar '( (1 2 3) (9 (2 3 4) ) ( ( ( ( 3 4 ( 7 ) ) ) ) ) ));=> (1 2 3 4 2 3 4 3 4 7)<br /><br /><br />;;---------------------------------------------------------------------------;;<br />;; Contrato: dados una lista y un elemento. <br />;; Si el elemento se encuentra en la lista <br />;; devuelve #t, caso contrario #f.<br />;;---------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">elemento_en_lista</span> (lambda (elemento lista)<br /> (if (null? lista)<br /> #f<br /> (if (eqv? elemento (car lista))<br /> #t<br /> (elemento_en_lista elemento (cdr lista))<br /> );if<br /> );if<br /> );lambda<br />);define<br /><br />;(elemento_en_lista '5 (list 1 2 3 4 5 6));=> #t<br /><br /><br />;;------------------------------------------------------------------------ --;;<br />;; Contrato: devuelve una lista con los elementos <br />;; de la primer lista y los de la segunda que no <br />;; aparecen en la primera. <br />;; Requiere de: (ELEMENTO_EN_LISTA e, lista) <br />;; (APLANAR lista)<br />;;---------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">sumar_listas</span> (lambda (lista1 lista2)<br /> (if (and (null? lista1) (null? lista2))<br /> '()<br /> (if (null? lista2)<br /> lista1<br /> (if (elemento_en_lista (car lista2) lista1)<br /> (sumar_listas lista1 (cdr lista2))<br /> (sumar_listas (aplanar (cons lista1 (cons (car lista2) '()))) (cdr lista2))<br /> );if<br /> );if<br /> );if<br /> );lambda<br />);define<br /><br />;(sumar_listas '(1 2 3) '(4 5));=>(1 2 3 4 5)<br />;(sumar_listas '(1 2 3) '(3 4 5 2 1));=>(1 2 3 4 5)<br />;(sumar_listas '(1 2 3 4 5) '(3 4 5 2 1 0));=>(1 2 3 4 5 0)<br /><br /><br />;;---------------------------------------------------------------------------;;<br />;; Ejercicio 12 <br />;; Contrato: obtiene el número máximo de listas <br />;; anidadas que aparecen en una lista. ;;---------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">obtener_profundidad</span> (lambda (lista)<br /> (if (null? lista)<br /> 0<br /> (if (list? (car lista))<br /> (if (>= (+ (obtener_profundidad (car lista)) 1) (obtener_profundidad (cdr lista)))<br /> (+ (obtener_profundidad (car lista)) 1)<br /> (obtener_profundidad (cdr lista))<br /> );if<br /> 0<br /> );if<br /> );if<br /> );lambda<br />);define <br /><br /><br />(obtener_profundidad '((1 (2)) (((5 7))) (((((4))))))); → 5Analía Lorenzattohttp://www.blogger.com/profile/07923900145462112039noreply@blogger.com0tag:blogger.com,1999:blog-2720195421602751185.post-47202099202034187032010-05-02T10:48:00.011-03:002010-05-02T12:47:51.384-03:00Programación Funcional con Scheme parte II;;----------------------------------------------------------------------;;<br />;; Ejercicio 1<br />;; Contrato: define una estructura que represente un<br />;; punto en el plano. Crear una función que calcule <br />;; la distancia entre dos puntos dados recibiendo <br />;; como parámetros la estructura de cada uno. <br />;;----------------------------------------------------------------------;;<br /><br />(define-struct punto (x y))<br /><br />(define <span style="font-weight:bold;">distancia_entre_2_ptos</span> (lambda (punto1 punto2)<br /> (let (<br /> (cuadrado (lambda (x)<br /> (* x x)<br /> );lambda<br /> ); cuadrado<br /><br /> (punto1 (make-punto 1 1))<br /> (punto2 (make-punto 3 3))<br /> )<br /> (sqrt ( + (cuadrado (- (punto-x punto2) (punto-x punto1)))<br /> (cuadrado (- (punto-y punto2) (punto-y punto1)))))<br /> );let<br /> );lambda<br />);define<br /><br />(define p1 (make-punto 1 1))<br />(define p2 (make-punto 3 3))<br /><br />(distancia_entre_2_ptos p1 p2)<br /><br /><br />;;----------------------------------------------------------------------------;;<br />;; Ejercicio 2 <br />;; Contrato: definie una estructura que represente un<br />;; punto en el espacio. Crear una función que calcule <br />;; el centro de gravedad de una lista de puntos en el <br />;; espacio representados por la estructura definida <br />;; previamente. <br />;;----------------------------------------------------------------------------;;<br /><br />(define-struct punto3d (x y z))<br /><br />(define <span style="font-weight:bold;">centro_de_gravedad</span> (lambda (lista_puntos)<br /> (letrec (<br /> (centro (lambda (n puntos)<br /> (if (null? puntos)<br /> '(0 0 0)<br /> (list <br /> (+ (/ (punto3d-x (car puntos)) n) (car (centro n (cdr puntos))))<br /> (+ (/ (punto3d-y (car puntos)) n) (cadr (centro n (cdr puntos))))<br /> (+ (/ (punto3d-z (car puntos)) n) (caddr (centro n (cdr puntos))))<br /> );list<br /> );if<br /> );lambda<br /> );centro<br /> )<br /> (centro (length lista_puntos) lista_puntos)<br /> );letrec<br /> );lambda<br />);define<br /><br />(define p1 (make-punto3d 2 4 2))<br />(define p2 (make-punto3d 3 9 4))<br />(define p3 (make-punto3d 2 1 2))<br />(define p4 (make-punto3d 1 1 2))<br /><br />(centro_de_gravedad (list p1 p2 p3 p4))<br /><br /><br />;;---------------------------------------------------------------------------;;<br />;;Ejercicio 3 <br />;; Contrato: define una estructura que represente un<br />;; automóvil con las sgtes. características:<br />;; - consumo promedio en km /Lts <br />;; - velocidad promedio km /Hora<br />;; usar la estructura para calcular el consumo de <br />;; combustible y el tiempo que tardo en recorrer dos <br />;; puntos representados por estructuras del ejercicio 1<br />;;---------------------------------------------------------------------------;;<br /><br />(define-struct automovil(consumo velocidad))<br />(define-struct punto(x y))<br /><br />(define <span style="font-weight:bold;">distancia_entre_2_pto</span>s (lambda (punto1 punto2)<br /> (sqrt ( + <br /> (expt (- (punto-x punto2) (punto-x punto1)) 2) <br /> (expt (- (punto-y punto2) (punto-y punto1)) 2)<br /> )<br /> )<br /> )<br />)<br /><br />(define t<span style="font-weight:bold;">iempo_y_consumo</span> (lambda (punto1 punto2)<br /> (list <br /> (/ (distancia_entre_2_ptos punto1 punto2) (automovil-consumo auto))<br /> (/ (distancia_entre_2_ptos punto1 punto2) (automovil-velocidad auto))<br /> )<br /> )<br />) <br /><br />(define p1 (make-punto 1 1))<br />(define p2 (make-punto 3 3))<br />(define auto (make-automovil 1 123))<br /><br />(tiempo_y_consumo p1 p2)<br /><br /><br />;;----------------------------------------------------------------------;;<br />;; Ejercicio 4 <br />;; Contrato: calcule la distancia máxima entre dos <br />;; puntos de una lista, usando el predicado MAP y <br />;; estructuras. <br />;;----------------------------------------------------------------------;;<br /><br />(define-struct punto(x y))<br /><br />(define <span style="font-weight:bold;">distancia_2p</span> (lambda (p1 p2)<br /> (round (sqrt (+ (expt (- (punto-x p2) (punto-x p1)) 2) (expt (- (punto-y p2) (punto-y p1)) 2))))<br /> );lambda<br />);define <br /><br />(define <span style="font-weight:bold;">maximo </span>(lambda (lista)<br /> (if (null? lista)<br /> '()<br /> (if (null? (cdr lista))<br /> (car lista)<br /> (if (> (car lista) (maximo (cdr lista)))<br /> (car lista)<br /> (maximo (cdr lista))<br /> );if<br /> );if<br /> );if<br /> );lambda <br />);maximo<br /><br /><br />(define max_distancia_p_lista (lambda (punto lista_distancias)<br /> (maximo <br /> (map <br /> (lambda (pp) (distancia_2p punto pp))<br /> lista_distancias<br /> );map<br /> );maximo<br /> );lambda<br />);define<br /><br /><br />(define punto1 (make-punto 2 4))<br />(define punto2 (make-punto 3 9))<br />(define punto3 (make-punto 2 1))<br />(define punto4 (make-punto 1 1))<br /><br />(max_distancia_p_lista punto1 (list punto2 punto3 punto4))<br /><br /><br />;;-------------------------------------------------------------------------;;<br />;; Ejercicio 5 <br />;; Contrato: cuenta la cantidad de palabras <br />;; y de caracteres de un archivo. <br />;;-------------------------------------------------------------------------;;<br /><br />(define (<span style="font-weight:bold;">cant_palabras_archivo archivo</span>)<br /> (letrec ( <br /> (contar_palabras(lambda (archivillo cant_palabras)<br /> (let (<br /> (palabra (read archivillo))<br /> );let <br /> (if (eof-object? palabra)<br /> cant_palabras <br /> (contar_palabras archivillo (+ cant_palabras 1))<br /> );if<br /> );let <br /> );lambda<br /> );contar_palabras<br /> )<br /> (contar_palabras archivo 0)<br /> );letrec <br />);define<br /><br />(define archivo1 (open-input-file "archivo.txt"))<br />(display "La cantidad de palabras es: ") <br />(cant_palabras_archivo archivo1)<br />(close-input-port archivo1)<br /><br /><br />(define (<span style="font-weight:bold;">cant_caracteres_archivo</span> archivo)<br /> (letrec (<br /> (contar_caracteres(lambda (archi cant_caracteres)<br /> (let (<br /> (caracter (read-char archi))<br /> );let <br /> (if (eof-object? caracter)<br /> cant_caracteres<br /> (contar_caracteres archi (+ cant_caracteres 1))<br /> );if<br /> );let <br /> );lambda<br /> );contar_caracteres<br /> )<br /> (contar_caracteres archivo 0)<br /> );letrec<br />);define<br /><br />(define archivo2 (open-input-file "archivo.txt"))<br />(display "La cantidad de caractéres es: ") <br />(cant_caracteres_archivo archivo2)<br />(close-input-port archivo2)<br /><br /><br />;;-----------------------------------------------------;;<br />;; Ejercicio 6 <br />;; Contrato: muestra por pantalla<br />;; un archivo de texto. <br />;;-----------------------------------------------------;;<br /><br />(define (<span style="font-weight:bold;">mostrar_archivo archivo</span>)<br /> (letrec (<br /> (leer_archivo (lambda(archi contenido)<br /> (let* (<br /> (palabra (read archi))<br /> (contenido_aux (cons contenido (cons palabra '())))<br /> (contenido contenido_aux)<br /> )<br /> (if (eof-object? palabra)<br /> contenido<br /> (leer_archivo archi contenido)<br /> );if <br /> );let*<br /> );lambda<br /> );leer_archivo<br /> );letrec<br /> (leer_archivo archivo "")<br /> );letrec<br />);define <br /><br /><br />(define archivo (open-input-file "archivo.txt"))<br />(mostrar_archivo archivo) <br />(close-input-port archivo)<br /><br /><br />;;------------------------------------------------------------------------;;<br />;; Ejercicio 7 <br />;; Contrato: lee una operación aritmética simple<br />;; (+, -) y la convierta en sintáxis de Scheme.<br />;;------------------------------------------------------------------------;;<br /><br />(let (<br /> (<span style="font-weight:bold;">convierte_operacion</span> (lambda (ecuacion)<br /> (let (<br /> (parametro1 (car ecuacion))<br /> (operador (car (cdr ecuacion)))<br /> (parametro2 (car (cdr (cdr ecuacion))))<br /> )<br /> (cons operador (cons parametro1 (cons parametro2 '())))<br /> );let<br /> );lambda<br /> );convierte_operacion<br /> )<br /> (convierte_operacion (list 34 + 2))<br />);let<br /><br />;; Nota: como el enunciado dice "una operación <br />;; aritmética simple", solo contemplo el ingreso <br />;; de un único operador y de dos operandos.Analía Lorenzattohttp://www.blogger.com/profile/07923900145462112039noreply@blogger.com0tag:blogger.com,1999:blog-2720195421602751185.post-21882483699294192602010-05-02T10:18:00.012-03:002010-05-02T12:48:09.410-03:00Programación Funcional con Scheme parte ISi bien en mi caso, la facultad es la parte aburrida e insulsa de la informática, me ha tocado una materia en la cual intentan hacernos ver diferentes paradigmas de programación. Por lo que debo destacar, que por esta vez, me divertí aprendiendo. A continuación, <span style="font-weight:bold;">algunas funciones, desarrolladas bajo el paradigma funcional puro con el lenguaje SCHEME </span>;)<br /><br /><br />;;----------------------------------------------------------------------------;;<br />;; Ejercicio 1 ;;<br />;; Contrato: cuenta la cantidad de apariciones de un <br />;; elemento en una lista. El primer parámetro es el <br />;; elemento a buscar y el segundo la lista en la que<br />;; se deber buscar. <br />;;----------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">count-elem</span>(lambda (num lista)<br /> (if (null? lista)<br /> 0<br /> (if (= (car lista) num)<br /> (+ (count-elem num (cdr lista)) 1)<br /> (count-elem num (cdr lista))<br /> );if<br /> );if<br /> );lambda<br />);define<br /><br />(count-elem 3 '(1 3 4 3)) ;=> 2<br /><br /><br />;;-------------------------------------------------------;;<br />;; Ejercicio 2 <br />;; Contrato: calcula el factorial del valor <br />;; pasado en n. <br />;;-------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">factorial</span> (lambda (x)<br /> (if (= x 0)<br /> 1<br /> (* x (factorial(- x 1)))<br /> );if<br /> )<br />) <br /><br />(factorial 0) ;=> 1<br />(factorial 1) ;=> 1<br />(factorial 2) ;=> 2<br /> <br /><br />;;--------------------------------------------;;<br />;; Ejercicio 3 <br />;; Contrato: devuelve el length <br />;; de una lista. <br />;;--------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">largo</span>_lista(lambda (lista)<br /> (if (null? lista)<br /> 0<br /> (+ (largo_lista (cdr lista)) 1)<br /> );if<br /> );lambda<br />);define<br /><br />(largo_lista (list '1 '23 '31 '4 '() '7)); => 6 Probado en lista impropia.<br />(largo_lista (list '1 '23 '31)) ; => 3 Probado en lista propia.<br /><br /><br />;;---------------------------------------------------------------------------;;<br />;; Ejercicio 4 ;<br />;; Contrato: dados dos parametros en formato hora, <br />;; a traves de una lista (hh mm ss). <br />;; Devuelve la suma de las mismas. <br />;;---------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">suma-horas</span> (lambda (hora1 hora2)<br /> (let (<br /> (mtotal (+ (cadr hora1) (cadr hora2)))<br /> (stotal (+ (caddr hora1) (caddr hora2))) <br /> (htotal (+ (car hora1) (car hora2)))<br /> ) <br /> (if (> (+ stotal) 59)<br /> (if (> (+ mtotal 1) 59) <br /> (cons (+ htotal 1) (cons (modulo (+ mtotal 1) 60) (cons (modulo (+ stotal) 60) '())))<br /> (cons (+ htotal) (cons (modulo (+ mtotal 1) 60) (cons (modulo (+ stotal) 60) '())))<br /> );if <br />:<br /> (if (> (+ mtotal 1) 59)<br /> (cons (+ htotal 1) (cons (modulo (+ mtotal) 60) (cons (modulo (+ stotal) 60) '())))<br /> (cons (+ htotal) (cons (modulo (+ mtotal) 60) (cons (modulo (+ stotal) 60) '())))<br /> );if <br /> );if<br /> );let <br /> );lambda <br />);define <br /><br /><br />(define <span style="font-weight:bold;">devolver_listado</span> (lambda (lista h_salida)<br /> (if (null? lista)<br /> '()<br /> (cons <br /> (list (caar lista) (suma-horas (cdr (car lista)) h_salida)) <br /> (devolver_listado (cdr lista) (suma-horas (cdr (car lista)) h_salida))<br /> );cons<br /> );if<br /> );lambda<br />);define<br /><br /><br />(define listado (list <br /> (cons "Federico Lacroze" '(00 00 00)) <br /> (cons "Jose Artigas" '(00 03 00)) <br /> (cons "Pn Parata" '(00 02 00)) <br /> (cons "Dr Fco Beiro" '(00 02 00)) <br /> (cons "El libertador" '(00 02 00)) <br /> (cons "Antonio Devoto" '(00 02 00))<br /> (cons "Cnelfo Lynch" '(00 02 00))<br /> ) ;solo por una cuestión de comodidad no incorporé la lista completa. <br />)<br />(devolver_listado listado '(05 30 00))<br /><br /><br />;;--------------------------------------------------------------------------;;<br />;; Ejercicio 5 <br />;; Contrato: dadas dos listas, concatenarlas en una <br />;; única lista resultante. <br />;;--------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">concatenar_listas </span>(lambda (lista1 lista2)<br /> (if (and (null? lista1) (null? lista2))<br /> '()<br /> (if (not (null? lista1))<br /> (cons (car lista1) (concatenar_listas (cdr lista1) lista2))<br /> (if (not (null? lista2))<br /> (cons (car lista2) (concatenar_listas lista1 (cdr lista2)))<br /> '()<br /> );if<br /> );if<br /> );if<br /> );lambda<br />);define<br /><br />(concatenar_listas (list '1 '2 '3 '()) (list '4 '5 '()));=> (1 2 3 () 4 5 ()) Probado con listas impropias.<br />(concatenar_listas (list '1 '2 '3) (list '4 '5));=> (1 2 3 4 5) Probado con listas propias.<br />(concatenar_listas (list '()) (list '()));=> (() ()) Probado con listas vacías<br /><br /><br />;;---------------------------------------------------------------------------;;<br />;; Ejercicio 6 ;; Contrato: devuelve el primer elemento <br />;; de una lista que es un número, si lo <br />;; encuentra. Caso contrario, devuelve null. <br />;;---------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">devolver_numero </span>(lambda (lista)<br /> (if (null? lista)<br /> "null"<br /> (if (number? (car lista)) <br />:<br /> (car lista)<br /> (devolver_numero (cdr lista))<br /> );if<br /> );if <br /> );lambda <br />);define<br /><br />(devolver_numero (list 'a 'b #f '() 'a 89)) ;=> 89<br /><br /><br />;;------------- -------------------------------------------------------------;; <br />;; Ejercicio 7 <br />;; Contrato: recibe como parametro un valor y una <br />;; lista y retorna la lista con los mismos valores <br />;; excepto el que se pasó por parámetro que se <br />;; agregará al final. <br />;;---------------------------------------------------------------------------;; <br /><br />(define <span style="font-weight:bold;">attach-at-end </span>(lambda (numero lista)<br /> (if (null? lista)<br /> numero<br /> (if (= (car lista) numero)<br /> (attach-at-end numero (cdr lista))<br /> (cons (car lista) (attach-at-end numero (cdr lista)))<br /> );if<br /> );if<br /> );lambda<br />);define<br /><br />(attach-at-end '2 (list '1 '2 '3 '2 '2 '4 '2 '5));=> (1 3 4 5 2)<br /><br /><br />;;---------------------------------------------------------------------------;;<br />;; Ejercicio 8 <br />;; Contrato: recibe 3 parámetros (dos valores y una <br />;; lista) y devuelve la lista con todos los componentes <br />;; que son iguales al primer parametro reemplazados<br />;; por el valor del tercer parámetro.<br />;;---------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">subst</span>(lambda (c k lista)<br /> (if (null? lista)<br /> lista<br /> (if (eqv? c (car lista))<br /> (cons k (subst c k (cdr lista)))<br /> (cons (car lista) (subst c k (cdr lista)))<br /> );if<br /> );if<br /> );lambda<br /> );define<br /><br />(subst 'c 'k '( c o c o n u t '()))<br />(subst 'c 'k '( c o c o n u t ))<br /><br /><br />;;---------------------------------------------------------------------------;;<br />;; Ejercicio 9 <br />;; Contrato: devolver de la suma del rango de valor <br />;; que va desde menor hasta mayor. <br />;;---------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">range-sum</span> (lambda (menor mayor)<br /> (if (> menor mayor)<br /> (display "Los parámteros no son correctos")<br /> (if (= menor mayor)<br /> menor<br /> (+ menor (range-sum (+ menor 1) mayor))<br /> );if<br /> );if <br /> );lambda<br />);define <br /><br />(range-sum 1 13)<br />(range-sum 2 2)<br /><br /><br />;;--------------------------------------------------------------------------;;<br />;; Ejercicio 10 <br />;; Contrato: recibe como parametros los puntos de <br />;; dos rectas y determine el punto de intersección <br />;; de las mismas. Ecuación de la recta que pasa <br />;; por dos puntos: <br />;; (y – y1) / (y2 – y1) = (x – x1) / (x2 - x1) <br />;;--------------------------------------------------------------------------;;<br /><br />(define <span style="font-weight:bold;">interseccion</span> (lambda (x11 y11 x12 y12 x21 y21 x22 y22)<br /> (let* (<br /> (pendiente1 (/ (- y12 y11) (- x12 x11)))<br /> (pendiente2 (/ (- y22 y21) (- x22 x21)))<br /> (ordenada1 (- y11 (* pendiente1 x11)))<br /> (ordenada2 (- y21 (* pendiente2 x21)))<br /> (x-interseccion (/ (- ordenada2 ordenada1) (- pendiente1 pendiente2)))<br /> (y-interseccion (+ (* pendiente1 x-interseccion) ordenada1))<br /> )<br /> (cons x-interseccion y-interseccion)<br /> );let*<br /> );lambda<br />);define<br /><br />(interseccion 0.5 0.5 1 1 1 1 3 3)<br />(range-sum 13 1)Analía Lorenzattohttp://www.blogger.com/profile/07923900145462112039noreply@blogger.com1tag:blogger.com,1999:blog-2720195421602751185.post-71025428079763377112010-02-04T09:56:00.017-03:002010-02-04T11:19:37.083-03:00Cómo relacionar 'Provincia' > 'Departamento' > 'Localidad' > 'Zona' en DjangoEs muy común la necesidad de relacionar éstos modelos en Django para algún desarrollo que debamos sacar andando. Por supuesto, generé el modelo de datos de la aplicación para lo cual Django te lo hace muy sencillo. Todo venía de un modo casi trivial hasta que necesité crear una vista del tipo Generic View para el alta de un inmueble. El mismo requería setear las relaciones: 'Provincia' > 'Departamento' > 'Localidad' > 'Zona'. Pero las vistas en Django, del tipo Generic View no permiten acceder a modelos relacionados entre si en más de un nivel de profunidad, por ej.: sólo podía relacionar: 'Zona' > 'Localidad'. Por otro lado, el filtro debía hacerse al revés, desde: 'Provincia' > 'Departamento' > 'Localidad' > 'Zona' <span style="font-weight:bold;">y no así</span> 'Zona' > 'Localidad' > 'Departamento' > 'Provincia'.<br />Es aquí cuando vino a mi salvación <span style="font-weight:bold;">"Dajax"</span>.<br /><br />Seguí al pie la letra la instalación / configuración de: <br />http://wiki.github.com/jorgebastida/django-dajax/<br /><br />Y del sgte. sitio obtuve el ejemplo: 'País' > 'Provincia': http://www.dajaxproject.com/forms/<br /><br />Similar a lo que necesitaba, pero imcompleto. Pués faltaba incorporar relaciones y que los datos sean obtenidos de una base de datos y no desde una variable.<br /><br />A continuación incorporé los cambios antes mencionados requeridos: <span style="font-weight:bold;">las relaciones 'Provincia' > 'Departamento' > 'Localidad' > 'Zona' obtenidos de una base de datos.</span><br /><br /><span style="font-weight:bold;">############</span><br /><span style="font-weight:bold;">## ajax.py ##</span><br /><span style="font-weight:bold;">############</span><br />from dajax.core import Dajax<br />from AppInmo.models import Provincia, Departamento, Localidad, Zona<br /><br /><span style="font-weight:bold;">def cargar_provincias(request)</span><br /> --dajax = Dajax()<br /> --provincias = Provincia.objects.all()<br /> --out = ""<br /> --for provincia in provincias:<br /> ----out = "%s<option value='%s'>%s" % (out,provincia.id,provincia.nombre)<br /> --dajax.assign('#provincia','innerHTML',out)<br /> --return dajax<br /><br /><span style="font-weight:bold;">def cargar_departamentos(request)</span><br /> --dajax = Dajax()<br /> --departamentos = Departamento.objects.filter(provincia_id = int(request.POST['option']))<br /> --out = ""<br /> --for departamento in departamentos:<br /> ----out = "%s<option value='%s'>%s" % (out,departamento.id,departamento.nombre)<br /> --dajax.assign('#departamento','innerHTML',out)<br /> --return dajax<br /><br /><span style="font-weight:bold;">def cargar_localidades(request):</span><br /> --dajax = Dajax()<br /> --localidades = Localidad.objects.filter(departamento_id = int(request.POST['option']))<br /> --out = ""<br /> --for localidad in localidades:<br /> ----out = "%s<option value='%s'>%s" % (out,localidad.id,localidad.nombre)<br /> --dajax.assign('#localidad','innerHTML',out)<br /> --return dajax<br /><br /><span style="font-weight:bold;">def cargar_zonas(request):</span><br /> --dajax = Dajax()<br /> --zonas = Zona.objects.filter(localidad_id = int(request.POST['option']))<br /> --out = ""<br /> --for zona in zonas:<br /> ----out = "%s<option value='%s'>%s" % (out,zona.id,zona.nombre)<br /> --dajax.assign('#zona','innerHTML',out)<br /> --return dajax<br />...<br /><br /><span style="font-weight:bold;">##################</span><br /><span style="font-weight:bold;">## inmueble.html ##</span><br /><span style="font-weight:bold;">##################</span><br />...<br />{% block body_params %}onload=<span style="font-weight:bold;">"Dajax.AppInmo_cargar_provincias()"</span><br />{% endblock %}<br /><br /> < select name="provincia" id="provincia" onchange=<span style="font-weight:bold;">"Dajax.AppInmo_cargar_departamentos({'option':this.value})"</span> size="1"><br /> < / select ><br /><br /> < select name="departamento" id="departamento" onchange=<span style="font-weight:bold;">"Dajax.AppInmo_cargar_localidades({'option':this.value})"</span> size="1"><br /> < / select ><br /><br /> < select name="localidad" id="localidad" onchange=<span style="font-weight:bold;" >"Dajax.AppInmo_cargar_zonas({'option':this.value})"</span> size="1"><br /> < / select ><br /><br /> < select name="zona" id="zona" size="1"> <br /> < / select ><br />...<br /><br /><span style="font-weight:bold;">###############<br /><span style="font-weight:bold;">## settings.py ##</span><br /><span style="font-weight:bold;">###############</span></span><br />...<br />DAJAX_FUNCTIONS = (<br /> 'AppInmo.ajax.cargar_provincias',<br /> 'AppInmo.ajax.cargar_departamentos',<br /> 'AppInmo.ajax.cargar_localidades',<br /> 'AppInmo.ajax.cargar_zonas',<br />)<br />...Analía Lorenzattohttp://www.blogger.com/profile/07923900145462112039noreply@blogger.com2tag:blogger.com,1999:blog-2720195421602751185.post-26753634928120925092010-01-27T12:41:00.005-03:002010-01-27T12:52:08.767-03:00"Las redes sociales son fuentes para conocer debilidades en materia de seguridad" por kevin MiltnickAnalía Lorenzattohttp://www.blogger.com/profile/07923900145462112039noreply@blogger.comtag:blogger.com,1999:blog-2720195421602751185.post-58711798576772260142010-01-14T17:04:00.006-03:002010-01-14T17:34:12.232-03:00Usos de GitUtilizaremos como estándar de documentación:<br /># para referirnos a superusuario (root)<br />$ para referirnos a un usuario<br /><br /><span style="font-weight:bold;">Generar un patch con Git</span><br /> $ git format-patch rev<br />rev: es la revisión desde la cual comenzará el patch.Analía Lorenzattohttp://www.blogger.com/profile/07923900145462112039noreply@blogger.com0tag:blogger.com,1999:blog-2720195421602751185.post-77688072005935950642009-11-09T09:38:00.001-03:002010-01-27T12:48:09.510-03:00"Cómo ser un hacker" por Eric Raymond. (.pdf)Analía Lorenzattohttp://www.blogger.com/profile/07923900145462112039noreply@blogger.comtag:blogger.com,1999:blog-2720195421602751185.post-44774192676543489162009-11-09T09:18:00.006-03:002010-01-27T12:50:48.057-03:00"La Catedral y el Bazar" por Eric Raymond. (.Pdf)Analía Lorenzattohttp://www.blogger.com/profile/07923900145462112039noreply@blogger.comtag:blogger.com,1999:blog-2720195421602751185.post-71234235194164003052009-11-04T21:33:00.012-03:002010-01-27T12:51:38.733-03:00¿Lado oscuro de un sysadmin?<span style="font-weight:bold;">Si bien aún no hay pruebas, ni una declaración oficial.. es bueno estar al tanto del asunto..</span><br /><br /><li>http://blog.segu-info.com.ar/2009/11/sitio-de-distro-de-linux-argentina.html</li><br /><br /><li>http://murder.diosdelared.com/?coment=3837</li>Analía Lorenzattohttp://www.blogger.com/profile/07923900145462112039noreply@blogger.comtag:blogger.com,1999:blog-2720195421602751185.post-34928111985521403682009-03-09T20:46:00.010-02:002009-11-04T20:21:55.363-03:00Ganeti<span style="font-weight:bold;">¿Qué es Ganeti y para qué sirve? ¶</span><br /><br />Ganeti es un sistema administrador de clusters basado en Xen, el cual integra un conjunto de herramientas, a saber:<br /><br /> * LVM<br /> * XEN<br /> * DRBD <br /><br />que permiten facilitarle al administrador la gestión de servidores virtuales. Es opensource creada por Google. Posee capacidad de debootstraping.<br /><span style="font-weight:bold;">Documentación Posta </span><br /><br /> * http://code.google.com/p/ganeti/ <br /><br /><span style="font-weight:bold;">Jerga de ganeti </span><br /><br /> * Nodo: equipo físico, contenedor de máquinas virtuales.<br /> * Instancia: máquina virtual administrada por el cluster. <br /><br /><span style="font-weight:bold;">Requesitos obligatorios </span><br /><br /> * Un Volume Group de al menos de 20GB, para almacenamiento de las máquinas virtuales.<br /> * Resolución para el cluster ganeti, diferente de la resolución del nodo primario que forma parte del cluster.<br /> * Xen.<br /> * Configuración de bridge para Xen. <br /><br /><span style="font-weight:bold;">Requisitos opcionales</span><br /><br /> * Drbd. <br /><br /><span style="font-weight:bold;">Instalación </span><br /><br />Suponiendo una distribución Debian.<br /><br />apt-get install ganeti<br /><br />La versión utilizada y probada es la 1.2.6-3.<br /><br /><span style="font-weight:bold;">Configuración del cluster </span><br /><span style="font-style:italic;">Configuración de red para el ganeti cluster </span><br /><br /> 1. Obligatoriamente el Xen inicial debe estar trabajando en modo bridge.<br /><br /> marte:# cat /etc/network/interfaces<br /><br /> allow-hotplug xenbr0<br /> auto xenbr0<br /> iface xenbr0 inet static<br /> address 10.0.0.2<br /> netmask 255.255.255.0<br /> network 10.0.0.0<br /> gateway 10.0.0.1<br /> pre-up ifconfig eth4 up<br /> bridge_ports eth4<br /> bridge_stp off<br /> bridge_fd 0<br /><br /> 2. Resolución propia para el cluster y diferente de la resolución del nodo master.<br /><br /> marte:/srv/ganeti/os# cat /etc/hosts<br /><br /> 10.0.0.4 cluster1.intranet cluster1<br /><br /> 3. Definición del hostname<br /><br /> marte:# echo "marte.intranet" > /etc/hostname<br /> marte:# /etc/init.d/hostname.sh start<br /><br />Sí o sí la salida del comando hostname debe ser marte.intranet, si devuelve tan solo marte las configuraciones sgtes. no funcionarán.<br /><br /> 4. Configuración final de red<br /><br /> marte:/srv/ganeti/os# ifconfig<br /><br /> eth4 Link encap:Ethernet HWaddr 00:22:19:18:29:7b<br /> inet6 addr: fe80::222:19ff:fe18:297b/64 Scope:Link<br /> UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1<br /> RX packets:727133 errors:0 dropped:0 overruns:0 frame:0<br /> TX packets:39613 errors:0 dropped:0 overruns:0 carrier:0<br /> collisions:0 txqueuelen:1000<br /> RX bytes:150008152 (143.0 MiB) TX bytes:5237793 (4.9 MiB)<br /> Interrupt:16 Memory:da000000-da012100<br /><br /> xenbr0 Link encap:Ethernet HWaddr 00:22:19:18:29:7b<br /> inet addr:10.0.0.2 Bcast:10.0.0.255 Mask:255.255.255.0<br /> inet6 addr: fe80::222:19ff:fe18:297b/64 Scope:Link<br /> UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1<br /> RX packets:724972 errors:0 dropped:0 overruns:0 frame:0<br /> TX packets:36700 errors:0 dropped:0 overruns:0 carrier:0<br /> collisions:0 txqueuelen:0<br /> RX bytes:136587142 (130.2 MiB) TX bytes:4721560 (4.5 MiB)<br /><br /> xenbr0:0 Link encap:Ethernet HWaddr 00:22:19:18:29:7b<br /> inet addr:10.0.0.4 Bcast:0.0.0.0 Mask:255.255.255.255<br /> UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1<br /><br /><span style="font-weight:bold;">Inicialización del cluster ganeti </span><br /><br /> 1. Inicializo el cluster. Para esto es necesario especificar: el nombre del volume group el cual almacenará las instancias ganeti (máquinas virtuales); y el bridge por defecto.<br /><br /> # gnt-cluster init -g vgganeti --bridge=xenbr0 cluster1.intranet<br /><br /> 2. Compruebo el paso anterior.<br /><br /> # gnt-node list<br /><br /> Node DTotal DFree MTotal MNode MFree Pinst Sinst<br /> marte.intranet 95368 0 32762 1024 30768 0 0<br /><br /><span style="font-weight:bold;">Incorporación de un nodo al cluster </span><br /><br />Hasta aquí el nodo marte es el único nodo que conforma el cluster (denominado cluster1). Para agregar un nuevo nodo (venus.intranet) al mismo, es necesario:<br /><br /> 1. Redefinir el hostname del nodo<br /><br /> venus:~# echo "venus.intranet" > /etc/hostname && /etc/init.d/hostname.sh start;<br /><br /> 2. Regenerar par de claves ssh. la clave DEBE SER dsh.<br /><br /> marte:~/.ssh# rm id_dsa*<br /> marte:~/.ssh# ssh-keygen -t dsa<br /><br /> 3. Decirle a ganeti que incorporo un nuevo nodo al cluster.<br /><br /> marte:~/.ssh# gnt-node add venus.intranet<br /><br /> 4. Compruebo que el nodo antes agregado forme parte del cluster.<br /><br /> marte:~/.ssh# gnt-node list<br /><br /> Node DTotal DFree MTotal MNode MFree Pinst Sinst<br /> marte.intranet 445244 438588 32762 1024 31024 2 0<br /> venus.intranet 445244 445244 32762 1024 31280 0 0<br /><br /><span style="font-weight:bold;">Generación de templates de Sistema Operativo </span><br /><br />Según la documentación de ganeti se pueden generar diferentes templates de sistemas operativos a partir de debootstrap.<br /><br /> 1. La disponibilidad de los S.O se pueden ver a través del sgte. comando:<br /><br /> marte:# gnt-os list<br /><br /> Name<br /> debian-etch<br /> debootstrap<br /><br /> 2. Si se desea generar otros templates de S.O es necesario instalar el sgte. paquete:<br /><br /> marte:# apt-get install ganeti-instance-debootstrap<br /><br /> 3. Configuración para el debootsrap de las variables: $MIRROR, $PROXY,$ARCH y $LENNY.<br /><br /> marte:~# vi /etc/default/ganeti-instance-debootstrap<br /><br /> 4. Adaptación del script create de deboostrap<br /><br /> marte:/srv/ganeti/os/rect64# vi create<br /><br /><span style="font-weight:bold;">Administración de instacias </span><br /><span style="font-style:italic;">Definición del kernel que usarán las instancias (domU) </span><br /><br />marte:/boot# ln -s vmlinuz-2.6.26-1-xen-amd64 vmlinuz-2.6-xenU<br />marte:/boot# ln -s initrd.img-2.6.26-1-xen-amd64 initrd-2.6-xenU<br /><br /><span style="font-weight:bold;"><span style="font-style:italic;">Creación de una instancia </span></span><br /><br />El comando que spre. se utilizará a nivel instancia (antes domU) será spre. gnt-instance con diferentes combinaciones de parámetros según se requiera, a saber:<br /><br /> * -t plain: indica que las particiones de la instancia serán LVM.<br /> * -n marte: la instancia se creará en el node (antes denominado dom0) marte.<br /> * -o rect64: la instancia se creará a partir del template utilizado en rectorado rect64.<br /> * -s 3g: tamaño de la partición /dev/sda de la instancia.<br /> * --swap-size 256: tamaño de la partición de swap de la instancia.<br /> * -m 64: cant. de memoria asignada a la instancia.<br /> * --mac 00:16:3e:00:00:25: mac asignada a la instancia, que en el caso de estar declarada dn DHCP+DNS la misma levantará con red configurada.<br /> * minmei: nombre de la instancia, spre. debe ser el último parámetro. <br /><br />marte:~# gnt-instance add -t plain -n marte.intranet -o rect64 -s 3g --swap-size 256 -m 64 --mac 00:16:3e:00:00:25 --no-start minmei<br /><br /><span style="font-weight:bold;"><span style="font-style:italic;">Levantar una instancia </span></span><br /><br />Luego de crear una instancia, es OBLIGATORIO correr los sgtes. dos comandos. NO USAR COMANDOS DE XEN.<br /><br />gnt-instance startup --extra "xencons=tty1 console=tty1" minmei<br />gnt-instance console minmei<br /><br /><span style="font-weight:bold;"><span style="font-style:italic;">Verificar estado de una instancia </span></span><br /><br />Una instancia luego de estar creada, puede estar corriendo o pausada. El sgte. comando permite verificar cualq. de los casos antes mencionados. Ver la columna Status.<br /><br />gnt-instance list<br /><br />Instance OS Primary_node Status Memory<br />minmei.intranet rect64 marte.intranet running 64<br /><br /><span style="font-weight:bold;"><span style="font-style:italic;">Ver información general de una instancia </span></span><br /><br />La información gral. comprende: nodo en el cual está creada la instancia, tipo de S.O, kernel, memoria, cant. de CPUS, mac, bridge y devices.<br /><br />marte:~# gnt-instance info Instance name: <br /> minmei.intranet<br /><br /> State: configured to be up, actual state is up<br /> Considered for memory checks in cluster verify: True<br /> Nodes:<br /> - primary: marte.intranet<br /> - secondaries:<br /> Operating system: rect64<br /> Kernel path: (default: /boot/vmlinuz-2.6-xenU)<br /> initrd: (default: /boot/initrd-2.6-xenU)<br /> Hardware:<br /> - VCPUs: 1<br /> - memory: 64MiB<br /> - NICs: {MAC: 00:16:3e:00:00:25, IP: None, bridge: xenbr0}<br /> Block devices:<br /> - sda, type: lvm, logical_id: (u'vgganeti', u'316f28b2-e8c1-4618-b329-504656abc1ba.sda')<br /> primary: /dev/vgganeti/316f28b2-e8c1-4618-b329-504656abc1ba.sda (254:1)<br /> - sdb, type: lvm, logical_id: (u'vgganeti', u'a78b14a1-4f77-424a-af57-8e30fd3d2ba6.sdb')<br /> primary: /dev/vgganeti/a78b14a1-4f77-424a-af57-8e30fd3d2ba6.sdb (254:2)<br /><br /><br /><span style="font-weight:bold;"><span style="font-style:italic;">Modificar tamaño de una instancia </span></span><br /><br />Que pasa si el /dev/sda de la instancia es de 2GB y necesito hacerlo crecer a 4GB?? A continuación se encuentran en orden los comandos para extender (no disminuir) una partición en una instancia.<br /><br /> marte:~# gnt-instance grow-disk minmei sda 2g<br /> marte:~# gnt-instance stop minmei<br /> marte:~# gnt-instance startup --extra "xencons=tty1 console=tty1" minmei<br /> marte:~# gnt-instance console minmei<br /><br /><span style="font-weight:bold;"><span style="font-style:italic;">Loguearse a la instancia y dentro de la misma ejecutar:</span></span><br /><br /> minmei:~# resize2fs /dev/sda<br /><br /><span style="font-style:italic;">Reasignar memoria a una instancia </span><br /><br /><span style="font-style:italic;">El cambio debe hacerse desde el cluster.</span><br /><br /> marte:~# gnt-instance modify -m 128 minmei<br /><br />All the changes take effect at the next restart. If the instance is<br /> running, there is no effect on the instance.Analía Lorenzattohttp://www.blogger.com/profile/07923900145462112039noreply@blogger.com0tag:blogger.com,1999:blog-2720195421602751185.post-5415666550403107552009-02-27T09:20:00.005-02:002009-11-04T20:34:08.130-03:00XenUtilizaremos como estándar de documentación:<br /># para referirnos a superusuario (root)<br />$ para referirnos a un usuario<br /><br /> 1. Instalo ifrename.<br /><br /> zaphod:~#apt-get install ifrename xen-linux-system-2.6.26-1-xen-amd64 xen-tools xen-utils bridge-utils -t testing<br /><br /> 2. Configuro el ifrename.<br /><br /> zaphod:~# echo "intranet mac 00:22:19:18:29:7b" > /etc/iftab<br /> zaphod:~# ifdown eth4<br /> zaphod:~# ifup intranet<br /> zaphod:~# /etc/init.d/ifrename start<br /><br /> 3. Configuro la interfaz de red en modo estático.<br /><br /> zaphod:~# cat /etc/network/interfaces<br /> # This file describes the network interfaces available on your system<br /> # and how to activate them. For more information, see interfaces(5).<br /><br /> # The loopback network interface<br /> auto lo<br /> iface lo inet loopback<br /><br /> # The primary network interface<br /> allow-hotplug xenbr0<br /> iface xenbr0 inet static<br /> address 172.16.0.44<br /> netmask 255.255.128.0<br /> gateway 172.16.0.1<br /> bridge_ports intranet<br /> bridge_stp off<br /> bridge_fd 0<br /><br /> 4. Aparentemente tenemos el xen andando:<br /><br /> zaphod:~# ps ax|grep xen<br /> 31 ? S< 0:00 [xenwatch]<br /> 32 ? S< 0:00 [xenbus]<br /> 3340 ? S 0:00 /usr/lib/xen-3.2-1/bin/xenstored --pid-file /var/run/xenstore.pid<br /> 3348 ? S 0:00 python /usr/lib/xen-3.2-1/bin/xend start<br /> 3350 ? Sl 0:01 python /usr/lib/xen-3.2-1/bin/xend start<br /> 3352 ? Sl 0:00 /usr/lib/xen-3.2-1/bin/xenconsoled<br /> 3655 pts/0 R+ 0:00 grep xen<br /><br /> 5. Configuración inicial de bridge<br /><br /> zaphod:~# brctl show<br /> bridge name bridge id STP enabled interfaces<br /> xenbr0 8000.00221918297b no intranet<br /><br /><br /> 6. Levantar un domU. Copiar la imagen generada al dom0.<br /><br /> 6.1. marte:/etc/xen# mkdir zaphod<br /> 6.2. marte:/etc/xen/zaphod# scp -r root@cualquiera:/srv/xendomains/imagen_test .<br /> 6.3. marte:/etc/xen/zaphod# scp -r root@cualquiera:/etc/xen/imagen_test.cfg .<br /> 6.4. marte:/etc/xen/zaphod# xm create -c imagen_test.cfg<br /><br /> 7. Una vez levantado el domU: se prueba loguearse al mismo y salir a internet. <br /> 7.1. Se comprueba que el domU ya esté levantado.<br /><br /> zaphod:~# xm list<br /> Name ID Mem VCPUs State Time(s)<br /> Domain-0 0 1024 4 r----- 144.4<br /> imagen_test 1 512 2 -b---- 1.5<br /><br /> 7.2. Se accede al domU (minmei), y se prueba salir a internet.<br /><br /> user@imagen_test:~$ ping google.com<br /><br /> PING google.com (74.125.45.100) 56(84) bytes of data.<br /> 64 bytes from yx-in-f100.google.com (74.125.45.100): icmp_seq=1 ttl=243 time=173 msAnalía Lorenzattohttp://www.blogger.com/profile/07923900145462112039noreply@blogger.com0tag:blogger.com,1999:blog-2720195421602751185.post-69446348600357786372008-12-17T00:01:00.007-02:002009-11-04T20:36:46.204-03:00PuppetEs un sistema que permite la administración centralizada de un gran numero de máquinas basada en una estructura cliente-servidor. Es una herramienta open source escrita en Ruby, diseñada para funcionar en la mayoría de los sistemas operativos UNIX.<br /><br />En puppet los servidores centrales, llamados puppetmasters, son instalados y configurados. La configuración es definida en el puppetmaster, compilada y luego es empujada a los clientes puppets cuando éstos se conectan.<br /><br />El término cliente refiere al servicio del cliente puppet (ó puppetd), el cual se conecta al puppetmaster y se trae la configuración; mientras que el término nodo hace referencia al host sobre el cual las configuraciones son aplicadas. <br /><br />Las sesiones de puppet son encriptadas y autenticadas mediante el uso de certificados autofirmados. Cada cliente puppet, nodo, genera un certificado autofirmado, que es validado y autorizado por el puppetmaster. Luego, cada cliente se conecta al puppetmaster para confirmar que su configuración se encuentra al día, si la misma ha cambiado, se recompilará y se aplicarán los cambios al cliente puppet.<br /><br />Los resultados de todas las actividades son logueadas y transmitidas al puppetserver, y podrán ser visualizadas con coquetos colores.<br /><br />Puppet es una combinación de: un lenguaje declarativo, mediante el uso de ruby; y la abstracción de la capa de recursos, pues puppet detecta la plataforma del nodo y funciona con la gran mayoría de los Unix.<br /><br /><span style="font-weight:bold;">Requerimientos en el servidor </span><br /><br /> * Los desarrolladores de puppet recomiendan un cpu con 2GB de ram para la administración de 50 a 100 nodos. <br /><br /><span style="font-weight:bold;">Comunicación inicial cliente-servidor (certificados) </span><br /><br /> 1. Para la comunicación entre servidor puppet y cliente puppet es necesario tener habilitado y disponible el puerto 8140.<br /> 2. El servidor puppet se denominará simplemente PUPPET. El nodo puppet será MINMEI. <br /><br /><span style="font-weight:bold;">Configuración del servidor </span><br /><br /> 1. Instalación de paquetes en el servidor puppet:<br /><br /><span style="font-style:italic;"> puppet:~# apt-get install puppetmaster -t testing</span><br /><br />El finalizar el paso anterior el servidor puppet, denominado puppetmaster en debian, intentará levantar. El cual fallará debido a que no hay ningún manifiesto instalado, don't worry es inofensivo, necesitamos seguir configurando.<br /><br /> 2. Habilitar el "servidor de archivos" (ubicado en /etc/puppet/files) propio de puppet:<br /><br /><span style="font-style:italic;"> puppet:~# vi /etc/puppet/fileserver.conf</span><br /><br /> <span style="font-style:italic;">[files]<br /> path /etc/puppet/files<br /> allow *.intranet</span><br /><br /><span style="font-weight:bold;">Creación de un manifiesto o receta (ubicado en /etc/puppet/manifests).</span><br /><br /><span style="font-style:italic;">puppet:/etc/puppet/manifests# vi site.pp</span><br /><br /> <span style="font-style:italic;">########################<br /> # Test inicial site.pp #<br /> ########################<br /> class test_class {<br /> file { "/tmp/testfile":<br /> ensure => present,<br /> mode => 644,<br /> owner => root,<br /> group => root,<br /> }<br /> }<br /><br /> node minmei {<br />I include test_class<br /> }</span><br /><br />El manifiesto anterior le dirá a puppet que genere en el nodo minmei un archivo de configuración vacío con los permisos antes definidos. El manifiesto por default debe llamarse site.pp, si existiesen otros manifiestos los mismos deben ser llamados desde site.pp a través de la claúsula import.<br /><br /> 4. Lanzar el servicio en modo foreground y debug, de modo de tener la salida por consola.<br /><br /><span style="font-style:italic;"> puppet:~# puppetmasterd --debug --no-daemonize</span><br /><br /><span style="font-weight:bold;">Nota</span>: puede lanzarse el servicio al modo clásico de debian "/etc/init.d/puppetmaster start" , es opcional. El primer modo es útil para informarnos debido a que puppet no genera logs muy descriptivos en "/var/log/puppet".<br /><br /><span style="font-weight:bold;">Configuración del cliente </span><br /><br /> 1. Instalación de paquetes en el cliente puppet en minmei.<br /><br /><span style="font-style:italic;"> minmei:~# apt-get install puppet -t testing</span><br /><br />Una vez que el paquete ha sido instalado es necesario configurar en el cliente puppet el nombre del servidor puppet. Por defecto intentará resolver el hostname puppet y conectarse al mismo.<br /><br /> 2. En caso de que el servidor puppet no se llame puppet, es necesario explicitarlo manualmente así:<br /><br /><span style="font-style:italic;"> minmei:~# vi /etc/puppet/puppet.conf</span><br /><br /> <span style="font-style:italic;"> [puppetd]<br /> server = nombre_del_servidor.intranet<br /> logdir = /var/log/puppet<br /> vardir = /var/lib/puppet<br /> rundir = /var/run<br /></span><br /><span style="font-weight:bold;">Nota</span>: si el hostname del servidor puede resolverse como puppet NO ES NECESARIO llevar adelante éste paso. <br /> 3. Testear la conectividad del cliente puppet , puppetd, con el servidor puppet. Para ello lanzar el servicio así:<br /><br /><span style="font-style:italic;"> minmei:~# puppetd --server puppet.intranet --waitforcert 60 --no-daemonize --test</span><br /><br /> <span style="font-style:italic;">err: No certificate; running with reduced functionality.<br /> info: Creating a new certificate request for pclient.example.con<br /> info: Requesting certificate<br /> warning: peer certificate won't be verified in this SSL session<br /> notice: Did not receive certificate</span><br /><br />De éste modo tendremos la salida por consola, lo cual es más práctico de debuggear. Igualmente es posible lanzar el servicio del cliente puppet al modo clásico de debian: "/etc/init.d/puppetd start".<br /><br /><span style="font-weight:bold;">Intercambio de certificados </span><br /><br />Como mencioné al principio, puppet utiliza certificado para la comunicación en la red y el control de acceso al servidor.<br /><br />La primera vez que se lanza el servicio del puppet cliente en el nodo, como se explica en el paso anterior, puppetd enviará su certificado y solicitará que el puppetmaster lo firme.<br /><br /> 1. Del lado del servidor puppet, se debería correr el sgte comando, que listará aquellos certificados a la espera de ser firmados:<br /><br /> <span style="font-style:italic;">puppet:~# puppetca --list<br /><br /> minmei.intranet</span><br /><br />Luego que el servidor master firma el certificado (que se encuentra a la espera del nodo minmei) el cliente puppet de minmei solicitará cada X tiempo las configuraciones definidas en el servidor puppet.<br /><br /> 2. Firma de certificados: <br /><br /><span style="font-style:italic;"> puppet:~# puppetca --sign minmei.intranet</span><br /><br />Si el certificado fué firmado, al ejecutar "puppetca --list" no debería mostrar certificados a la espera de ser firmados.<br /><br />Los certificados se encuentran almacenados, tanto en el cliente como en el servidor, en /var/lib/puppet/ssl. En el servidor puppet los certificados firmados se encuentran en /var/lib/puppet/ssl/ca/signed. Si bien debian los almacena en /etc/ssl/certs, puppet no los busca allí.<br /><br /><span style="font-weight:bold;">Compruebo que las configuraciones fueron tomadas en el cliente </span><br /><br /> 1. Compruebo si existe el archivo con sus correspondientes permisos en minmei:<br /><br /> <span style="font-style:italic;">minmei:# ls -l /tmp/testfile<br /><br /> -rw-r--r-- 1 root root 0 2008-12-16 13:00 /tmp/testfile</span><br /><br /><span style="font-weight:bold;">Casos de uso </span><br /><span style="font-style:italic;">Gestión de APT:</span> el nodo minmei se trae del servidor puppet (a través del protocolo puppet) la configuración completa de apt y realiza una actualización del listado de paquetes una vez al día en el rango horario especificado.<br /><br /><span style="font-style:italic;">puppet:~# vi /etc/puppet/manifests/site.pp</span><br /><br /><span style="font-style:italic;">## Gestión de APT vía puppet<br />class apt {<br /> file {<br /> "/etc/apt":<br /> ensure => directory,<br /> owner => "root",<br /> group => "root",<br /> recurse => true,<br /> source => "puppet:///files/apt";<br /><br /> "/etc/apt/preferences":<br /> ensure => "/etc/apt/preferences-host"<br /> }<br /> schedule {<br /> "daily":<br /> period => daily,<br /> range => "10-12",<br /> repeat => 1<br /> }<br /> exec {<br /> "/usr/bin/apt-get update":<br /> schedule => daily<br /> }<br />}<br />## Nodos que tomaran la configuración<br />node minmei {<br />include apt<br />} </span><br /><br /><span style="font-weight:bold;">Nota</span>: la línea <span style="font-weight:bold;">source => "puppet:///files/apt"<span style="font-weight:bold;"></span></span>; busca en el directorio de archivos del servidor puppet.intranet el directorio de configuración apt que se trae el cliente. Cuando el nombre del servidor puppet no es puppet la línea de source sería source => "puppet://nombre_servidor_puppet.intranet/files/apt";.Analía Lorenzattohttp://www.blogger.com/profile/07923900145462112039noreply@blogger.com0tag:blogger.com,1999:blog-2720195421602751185.post-63143473004168919622008-10-31T20:10:00.003-02:002009-11-04T21:08:14.303-03:00GnuPGLos métodos de cifrado son una buena alternativa como barrera de seguridad. En Linux disponemos de GnuPG, versión del código libre de PGP, la que nos permite cifrar los mensajes utilizando pares de claves asimétricas. Las claves públicas suelen ser compartidas con otros usuarios depositándolas en los servidores de claves, mientras que la privada debe permanecer SOLO con su propietario. GPG usa para ello algoritmos no patentados, a saber: ElGamal, CAST5, 3DES, AES y Blowfish.<br /><br />Utilizaremos como estándar de documentación:<br /># para referirnos a superusuario (root)<br />$ para referirnos a un usuario<br /><br /><span style="font-weight:bold;">Definir un server por default</span><br /><br />vi .gnupg/gpg.conf<br /><br /> keyserver hkp://subkeys.pgp.net<br /><br /><span style="font-weight:bold;">Generar par de claves pública/privada</span><br /><br />Se generará un par de llaves público/privada.<br /><br /> gpg --gen-key<br /><br />Se requiere especificar, según se pida, a continuación:<br /><br /> 1. Tamaño de la llave.<br /> 2. Caducidad de el par de claves.<br /> 3. Ingresar información de usuario.<br /><br /><span style="font-weight:bold;">Agregar GPG pública</span><br /><br /> gpg --keyserver hkp://subkeys.pgp.net --recv-keys ABCDEGFH<br /><br /><span style="font-weight:bold;">Listar keys privadas</span><br /><br />Lista todas aquellas claves públicas adheridas a tu ” ~/.gnupg/pubring.gpg”.<br /><br /> gpg --list-keys<br /><br /><span style="font-weight:bold;">Validar key</span><br /><br />Se valida verificando la huella digital de la key y firmándola para certificar su validez.<br /><br />La huella digital de una clave se verifica con el propietario de la clave. Esto puede hacerse en persona o por teléfono, o por medio de otras maneras. Si la huella digital que se obtiene por medio del propietario es la misma que la que se obtiene de la clave, entonces se puede estar seguro de que se está en posesión de una copia correcta de la clave. Después de comprobar la huella digital ya se puede firmar la clave con el fin de validarla. <br /><br />gpg --edit-key username@gmail.com<br /> Command> fpr<br /> Command> sign<br /> Command> check<br /> Command> quit<br />Renovar key privada<br /><br />La idea es que la key privada tiene una fecha de caducación que es definida cuando es creada. Una vez cumplida esa fecha, la misma expira, y es requerido renovarla. A saber: La actualizo localmente, y guardo los cambios.<br /><br /> gpg --edit-key ID expire<br /> Command> save<br /><br />Donde ID podría ser nombre y apellido de persona. Envió los cambios a algún server para que se actualicen.. A partir de allí puede decirse que la key privada fué renovada exitosamente.<br /><br /> gpg --keyserver hkp://subkeys.pgp.net --send-keys ABCDEFGH<br /><br />Puedo comprobar la esperada actualización de expiración de la key.<br /><br /> gpg --list-key<br /><br /><span style="font-weight:bold;">Renovar subkey privada</span><br /><br />La subkey es “El gamal”(que permite cifrar + firmar). Es posible que una vez caducada nuestro par de claves gpg, y luego de renovadas (Paso anterior) NO SE HAYA ACTUALIZADO la fecha de expiración de la subkey. Cómo hacerlo? »<br /><br /> gpg --edit-key ABCDEFGH<br /><br />Command> key 1 # donde key 1=subkey. pub 1024D/ABCDEFGH created: 2007-03-12 expires: never usage: SC trust: ultimate validity: ultimate sub* 1024g/ABCDEFGH created: 2007-03-12 expires: never usage: E [ultimate] (1). Username username@gmail.com Command> save<br /><br /> gpg --keyserver hkp://subkeys.pgp.net --send-keys ABCDEFGH<br /><br />Puedo comprobar la esperada actualización de expiración de la key.<br /><br /> gpg --list-key<br /><br /><span style="font-weight:bold;">Generar certificado de revocación</span><br /><br />En el caso de perder contraseña, extravío de key privada, el certificado de revocación sse hará público. De modo que los usuarios de la misma serán notificados de que la clave pública NO DEBERÁ ser usada nunca más.<br /><br /> gpg --output revoke.asc --gen-revoke ABCDEFGH<br /> gpg --keyserver hkp://subkeys.pgp.net --send-keys ABCDEFGH<br /><br />OBLIGATORIAMENTE: se pedirá ingresar la passprhase para confirmar la operación.<br />Cifrar archivo<br /><br /> gpg -c file_a_encriptar<br /><br />El comando anterior generará “file_a_encriptar.gpg”, el cual es una copia idéntica de “file_a_encriptar” pero encriptado. Lo encriptará luego de ingresar correctamente dos veces la passphrase.<br /><span style="font-weight:bold;">Descifrar archivo</span><br /><br /> gpg --output file_desencriptado --decrypt file_encriptado.gpg<br /><br />“file_desencriptado” es un archivo idéntico a “file_encriptado.gpg” DESENCRIPTADO. Para hacer esta acción pedirá passphrase.<br /><span style="font-weight:bold;">Exportar clave pública</span><br /><br />La idea es copiar la llave pública a un archivo, en este caso file_with_publickey.asc, en formato ASCII, para después trasladarlo. <br /><br /> gpg --armor --output file_with_publickey.asc --export usuario@gmail.comAnalía Lorenzattohttp://www.blogger.com/profile/07923900145462112039noreply@blogger.com0tag:blogger.com,1999:blog-2720195421602751185.post-39928031699313644162008-09-28T20:21:00.018-03:002009-11-04T21:28:50.882-03:00Suspender a discoLa idea es que al apagar el equipo en el cual estamos trabajando y lo prendamos nuevamente, el mismo quede exactamente en el mismo punto en el cual lo dejamos cuando lo apagamos. De este modo, nos ahorramos, por ej.: loguearnos, iniciar el navegador con las urls consultadas, lanzar las consolas, etc. muy práctico!, aunque nada seguro si otros usuarios tienen acceso al equipo.<br /><br /><span style="font-size:85%;"><span style="font-family:arial;">Utilizaremos como estándar de documentación:</span><br /><span style="font-family:arial;"># para referirnos a superusuario (root)</span><br /><span style="font-family:arial;">$ para referirnos a un usuario</span></span><br /><br />1. Establecer una partición/archivo/algo para swap. <strong></strong><br /><br />2. Instalar paquetes necesarios:<pre class="wiki">#apt-get install uswsusp <span style="font-family:Georgia,serif;"><br /><br /></span>NOTA: Esta parte puede hacerse más fácilmente con dpkg-reconfigure uswsusp<br /><br /><span style="font-size:130%;"><span style="font-family:times new roman;">3. Configuración del archivo</span></span><br /><br /># vi /etc/uswsusp.conf<br /><br />resume device = /dev/sda5 #Partición swap<br />compute checksum = y<br />compress = y<br />early writeout = y<br />image size = 484036935 #Al menos, el tamano de la ram.<br />#RSA key file = /etc/uswsusp.key #En mi caso, deshabilité la encriptación porque mi filesystem es encriptado<br />shutdown method = platform</pre>Analía Lorenzattohttp://www.blogger.com/profile/07923900145462112039noreply@blogger.com0tag:blogger.com,1999:blog-2720195421602751185.post-28151065243308597772008-09-24T21:38:00.006-03:002009-11-04T21:06:00.856-03:00Servidor de logs con Syslog-ng<div class="wikipage"><div id="searchable"><h1 id="ServidordelogsconSyslog-ng">Servidor de logs con Syslog-ng<a title="Link to this section" class="anchor" href="https://trac.intranet/admin/wiki/Syslog-ngPasoaPaso#ServidordelogsconSyslog-ng"> ¶</a></h1> <p> Los registros de logs nos sirven para comprobar la salud del sistema. Puede utilizarse localmente o enviar mensajes a través de la red desde una fuente a otro host de registro. La "buena nueva" se llama <i>Syslog-ng</i> que vino a salvar las falencias de syslog. Si bien éste último se convirtió en un estándar de facto, tiene falencias importantes, a saber: </p> <ul><li>Falta de métodos de autenticación, es decir, Syslogd no puede distinguir entre distintos hosts. </li><li>Transmisión de mensajes en claro. </li><li>No registra el orígen de la fuente, es decir, cuando un mensaje pasa por distintos servidores de registros cambia su ip. Syslog no almacena el FQDN. Y en grandes redes, esto se vuelve un poco impráctico. </li><li>Syslogd solo utiliza mensajes UDP para la transferencia, entonces si un paquete se pierde en la red, el mensaje nunca llegará a destino. </li></ul><p> Syslog-ng vino para salvar estas falencias :) </p> <h2 id="Instalación">Instalación<a title="Link to this section" class="anchor" href="https://trac.intranet/admin/wiki/Syslog-ngPasoaPaso#Instalaci%C3%B3n"> ¶</a></h2> <p> En Debian.. </p> <pre class="wiki">apt-get update ; apt-get install syslog-ng<br /></pre><h2 id="Configuración">Configuración<a title="Link to this section" class="anchor" href="https://trac.intranet/admin/wiki/Syslog-ngPasoaPaso#Configuraci%C3%B3n"> ¶</a></h2> <p> El único archivo de configuración se encuentra en <strong>/etc/syslog-ng/syslog-ng.conf</strong> </p> <p> En el original syslog teníamos: <strong>original</strong> y <strong>priority</strong>. En syslog-ng tenemos: <strong>logpaths</strong> formado por: <strong>source</strong>, <strong>filter</strong> y <strong>destination</strong>. Los <strong>controladores fuentes</strong>: </p> <ul><li><strong>file</strong> y <strong>pipe</strong> usadas como fuentes desde las cuales el servicio lee mensajes y no como destino a donde redirigirlos. </li><li><strong>file</strong> abre el archivo especificado. </li><li><strong>UDP</strong> y <strong>TCP</strong>, escucha mensajes en un perto udp/tcp respectivamente. </li></ul><p> Los <strong>filtros</strong> determinan como syslog-ng deberia filtrar los mensajes que recibe de las diferentes fuentes. Mediante los filtros se organizan y restringen los mensajes para enviarlos a sus correspondientes <strong>destinos</strong> quedando los registros de logs finalmente ordenaditos. </p> <p> Los distintos filtros que pueden utilizarce son: </p> <ul><li><strong>facility</strong>: utilidad que origina los logs. </li><li><strong>level</strong> / <strong>priority</strong> </li><li><strong>program</strong>: filtra aquellos mensajes donde el campo "nombre del programa" es coincidente con la expresión regular especificada. </li><li><strong>host</strong>: filtra mensajes donde el campo "nombre del host" coincide con la expresión regular especificada. </li><li><strong>filter</strong>: llama a otra "regla filtro". </li><li><strong>match</strong>: aplica la expresión regular especificada. </li></ul><p> Los <strong>destinos</strong> especifian dónde y porqué medios un mensaje debe ser redirigido y procesado. </p> <p> Syslog-ng llama al controlador una única vez y lo mantiene ejecutándose hasta que el servicio recibe la señal de "terminar" (SIGHUP). Esto es muy eficiente porque si Syslog-ng lanzace un programa externo por cada mensaje entonces sería muy fácil para un atacante lanzar varios procesos similar a un ataca DOS. </p> <h3 id="OpcionesGlobales">Opciones Globales<a title="Link to this section" class="anchor" href="https://trac.intranet/admin/wiki/Syslog-ngPasoaPaso#OpcionesGlobales"> ¶</a></h3> <pre class="wiki">vi /etc/syslog-ng/syslog-ng.conf<br /></pre><pre class="wiki"> chain_hostnames(0);<br /> time_reopen(10);<br /> time_reap(360);<br /> sync(0);<br /> stats(43200);<br /> log_fifo_size(2048);<br /> use_dns(no);<br /> use_fqdn(no);<br /><br /> source s_all {<br /> internal();<br /> # standard Linux log source (this is the default place for the syslog()<br /> # function to send logs to)<br /> unix-stream("/dev/log");<br /> # messages from the kernel<br /> file("/proc/kmsg" log_prefix("kernel: "));<br /> <br />};<br /></pre><h3 id="Ladocliente"><strong>Lado cliente</strong><a title="Link to this section" class="anchor" href="https://trac.intranet/admin/wiki/Syslog-ngPasoaPaso#Ladocliente"> ¶</a></h3> <pre class="wiki">###########<br /># Destinos<br />destination df_auth { udp("172.16.0.17");};<br />destination df_syslog { udp("172.16.0.17"); };<br /><br />##########<br /># Filtros<br /><br /># Todos los mensajes vienen de las utilidades: auth y authpriv<br />filter f_auth { facility(auth, authpriv); };<br /><br /># Todos los mensajes vienen EXCEPTO de las utilidades: auth y authpriv<br />filter f_syslog { not facility(auth, authpriv); };<br /><br />#########<br /># Reglas<br /><br />log {<br /> source(s_all);<br /> filter(f_auth);<br /> destination(df_auth);<br />};<br /><br />log {<br /> source(s_all);<br /> filter(f_syslog);<br /> destination(df_syslog);<br />};<br /><br /></pre><h3 id="Ladoservidor"><strong>Lado servidor</strong><a title="Link to this section" class="anchor" href="https://trac.intranet/admin/wiki/Syslog-ngPasoaPaso#Ladoservidor"> ¶</a></h3> <pre class="wiki">vi /etc/syslog-ng/syslog-ng<br /></pre><pre class="wiki">source s_net {<br /> udp(); #los mensajes de logs pueden ser enviados electivamente a través de TCP o UDP<br /># tcp();<br />};<br /><br />filter f_slapd {match("slapd"); };<br />filter f_dhcp {match("dhcp"); };<br /><br />destination df_slapd { file("/var/log/slapd.log"); };<br />destination df_dhcp { file("/var/log/dhcpd3.log"); };<br /><br />log{<br /> source(s_net);<br /> filter(f_dhcp);<br /> destination(df_dhcp);<br />};<br /><br />log{<br /> source(s_net);<br /> filter(f_slapd);<br /> destination(df_slapd);<br />};<br /></pre></div> </div> <div class="buttons"> <form method="get" action="/admin/wiki/Syslog-ngPasoaPaso"><div> <input name="action" value="edit" type="hidden"> <input value="Edit this page" accesskey="e" type="submit"></div></form></div>Analía Lorenzattohttp://www.blogger.com/profile/07923900145462112039noreply@blogger.com1tag:blogger.com,1999:blog-2720195421602751185.post-15201946867634998322008-09-24T21:34:00.007-03:002009-11-04T21:27:42.449-03:00Manejo de logs con Socklog<span style="font-weight:bold;">Introducción</span><br />Es un sistema de log que trabaja en conjunto con <strong>runit</strong> y se encarga de rotar los logs automáticamente. Para utilizar socklog es necesario que el programa <strong>svlogd</strong> esté instalado, ya que es parte <strong>runit</strong>. </p> <p> Documentación: </p> <p> <a class="ext-link" href="http://smarden.org/socklog/"><span class="icon">http://smarden.org/socklog/</span></a> </p> <br /><br /><span style="font-weight:bold;">Instalando socklog</span><br /><br />apt-get install socklog socklog-run<br /><br /><span style="font-weight:bold;">Configurando sistema de logs</span><br />Es necesario que <strong>socklog-unix</strong> escuche en el socket local de unix /dev/log. Se crean los directorios del servicio y de los logs, a través de la herramienta <strong>socklog-conf</strong>: </p> <br /><br />socklog-conf unix nobody log<br /><br />Hacer un stop del syslogd/syslog-ng, en el caso de que éste se encuentre corriendo. No rebootear antes de finalizar la configuración de <strong>socklog</strong>. </p> <p> Avisarle al supervisor de servicios, <strong>runsvdir</strong>, para que comience a supervisar socklog. </p> <br /><br />ln -s /etc/sv/socklog-unix /var/service/<br /><br />Verificar que socklog-unix esté siendo supervisado por runit. sv status socklog-unix </p> <br /><br />run: socklog-unix: (pid 27461) 3086s; run: log: (pid 1338) 254110s<br /><br />Ver que socklog esté logueando<br /><br />less /var/log/socklog/main/current<br /><br />Modificar parámetros de rotación </p> <p> Vi /var/log/socklog/<strong>$SERVICIO</strong> </p> #Tamaño del archivo en bytes, antes de ser rotado.<br />s999999<br />#Cant. de archivos de logs que deberían mantenerse<br />n5<br />#Opcionalmente, se le especifica que sean compresos.<br />!/bin/bzip2<br /><br />Remoto a través de UDP<br />La idea es transmitir logs a un host remoto, dentro de una red interna, a través de UDP. No es fiable, y tampoco provee autenticación entre las partes. </p> <br /><br />Lado cliente<br />Puede especificarse el envío de logs por servicio o decirle que envíe directamente todo. <br />Para el primer caso debe crearse el archivo <strong>/var/log/$SERVICIO/config</strong>. <br />Para el segundo caso, se especifica debajo. </p> <p> vi /var/log/socklog/main/config </p> <br /><br /> s9999<br /> n2<br /> # '+*': se toman todos los datos. '-*': se descartan todos los datos<br /> +*<br /> # 'U'= se realizan logs locales, además de enviarse a un server de logs remoto. 'u'= solo se realizan logs locales.<br /> U10.0.0.16:514<br /><br />sv restart socklog-unix </p> <p> sv hup socklog-unix/log </p> <br /><br />Lado servidor<br />Remoto a traves de TCPAnalía Lorenzattohttp://www.blogger.com/profile/07923900145462112039noreply@blogger.com0tag:blogger.com,1999:blog-2720195421602751185.post-63433467435640908102008-09-20T21:01:00.008-03:002009-11-04T21:31:09.358-03:00Acelerando el arranque del sistema con RUNIT<span style="font-weight: bold;">Runit</span> es un esquema de servicios supervisados. A diferencia de Sysvinit, runit permite la supervisión de servicios, y en caso de que alguno de ellos caiga, Runit tratará de levantarlo.<br /><br /><span style="color: rgb(0, 0, 0); font-family: verdana; font-size: 85%;">Utilizaremos como estándar de documentación:</span><span style="font-size: 85%;"><br /></span><span style="color: rgb(0, 0, 0); font-family: verdana; font-size: 85%;"># para referirnos a superusuario (root)</span><span style="font-size: 85%;"><br /></span><span style="color: rgb(0, 0, 0); font-family: verdana; font-size: 85%;">$ para referirnos a un usuario</span><br /><br />1. Instalación de paquetes:<br /><br />#apt-get install runit-services runit-run runit<br /><h2 id="Crearconfiguracióndeservicioasupervisar"><span style="font-size:100%;">Crear configuración de servicio a supervisar</span></h2>Para que Runit monitoree y supervise un servicio, necesita algunos scripts y links particulares que se encuentran en el directorio /etc/sv (para la distribución STABLE). En caso que no exista la entrada del servicio a supervisar, crearla siguiendo estos pasos:<br /><br />Suponiendo que "SERVICIO<servicio_a_supervisar>" es el daemon que se quiere instalar.<br /><br />1. Crear directorio donde se encontrará la configuración de servicios a supervisiar y levantar por Runit.<br /><br /># mkdir /etc/sv/${SERVICIO}/<br /><br /># mkdir /etc/sv/${SERVICIO}/log<br /><br /><p> 2. Creo directorio para logs de "mi_servicio"</p><p># mkdir /var/log/${SERVICIO}<br /></p> <p>3. Creo script que se encarga de lanzar "mi_servicio"</p><p># vi /etc/sv/${SERVICIO}/run<br /></p><pre class="wiki">#!/bin/sh</pre><pre class="wiki">exec 2>&1<br /># FIXME: poner el nombre adecuado del servicio a lanzar.<br /># verificar que los parametros que se pasan son adecuados, de acuerdo al init.d<br /># original.<br /><br />exec servicio <options><br /><br /><span style="font-size:130%;"><br />4. Creo un ejecutable que se encarga de loguear mi_servicio</span><br /><br />#!/bin/sh<br />set -e<br /><br /># FIXME: Poner el nombre del servicio adecuado<br /># Tambien verificar si los logs estaran centralizados<br />SERVICIO=<servicio_a_supervisar><br /><br />LOG=/var/log/${SERVICIO}<br /><br />test -d "$LOG" || mkdir -p -m0750 "$LOG" && chown log:adm "$LOG"<br /><br />exec chpst -ulog:adm svlogd -tt "$LOG"<br /></servicio_a_supervisar></options></pre><br />5. Hago los archivos, ejecutables.<br /><br /># chmod +x /etc/sv/${SERVICIO}/run<br /><br /># chmod +x /etc/sv/${SERVICIO}/log/run<br /><br /><p> 6. Testear ${SERVICIO}</p><p># cd /etc/sv/${SERVICIO}</p><p># ./run</p><div class="wikipage"><div id="searchable"><h2 id="PonerelserviciobajoelmonitoreodeRunit"><span style="font-size:100%;">Poner el servicio bajo el monitoreo de Runit<a title="Link to this section" class="anchor" href="https://trac.intranet/admin/wiki/RunitPasoaPaso#PonerelserviciobajoelmonitoreodeRunit"> ¶</a></span></h2> <p> Luego, para poder poner bajo supervisión un servicio, debemos realizar los siguiente pasos: </p> <p>1. Detener el servicio, utilizando el método tradicional. </p> <pre class="wiki">/etc/init.d/${SERVICIO} stop<br /></pre><p> 2. Luego debemos realizar un divert del paquete en el que viene el servicio. Esto es para que cuando apt actualize el paquete, no modifique el script. </p> <p> Esto se realiza de la siguiente manera:</p><p># dpkg-divert --add --rename /etc/init.d/${SERVICIO}<br /></p> <p>3. Reemplazamos el script de init del servicio por un enlace simbólico a /usr/bin/sv, para lo que previamente se recomienda realizar un backup del mismo.</p><p># cd /etc/init.d/</p><p># ln -s /usr/bin/sv /etc/init.d/${SERVICIO}<br /></p> <p> 4. Le informamos a RunIt del nuevo servicio.</p><p># ln -s /etc/sv/${SERVICIO} /var/service/<br /></p> <p> y listo, ya deberíamos tener bajo supervisión nuestro servicio. </p> <p> 5. Para poder chequear que efectivamente todo funcione bien, ejecutamos</p><p># sv status ${SERVICIO}<br /></p> <p> y deberiamos obtener algo como: </p> <pre class="wiki">run: cron: (pid 19833) 3s<br /></pre><p> o sino, por medio del viejo método:</p><p># /etc/init.d/${SERVICIO} status</p><p># run: mi_servicio: (pid 19833) 4s<br /></p> </div> </div> <div class="buttons"> <form method="get" action="/admin/wiki/RunitPasoaPaso"><div> <input name="action" value="edit" type="hidden"> <input value="Edit this page" accesskey="e" type="submit"></div></form></div></servicio_a_supervisar><br /><br />Es importante destacar que no todos los servicios son posible poner bajo supervisión de Runit. Debido a que Runit requiere que el nuevo servicio a supervisar funcione en FOREGROUND, u opcionalmente en modo DEBUG. Aquellos que funcionen únicamente en FOREGROUND no será posible que runit lo supervise.<br />Cuando un servicio corre en background, el mismo se desprende del terminal, por ejemplo: <span style="font-weight:bold;">iceweasel & </span> devolviéndonos el control y uso del terminal nuevamente, en el cual se lanzó anteriormente el navegador. En cambio cuando un servicio corre en foreground, por ejemplo: <span style="font-weight:bold;">iceweasel</span>, el terminal sigue teniendo el control del mismo, por lo cual la misma queda inutilizable, salvo por el navegador antes lanzado.Analía Lorenzattohttp://www.blogger.com/profile/07923900145462112039noreply@blogger.com0tag:blogger.com,1999:blog-2720195421602751185.post-29192630235172355722008-09-11T12:59:00.029-03:002009-11-04T21:31:36.867-03:00Instalación de Debian con filesystem encriptado (LUKS) en una EeePcMi idea es instalar Debian con particiones <span style="font-weight: bold;">LVM</span> y con filesystem encriptado (<span style="font-weight: bold;">LUKS</span>) en una Eeepc<br /><br />El instalador destinado a la EeePc es muy reducido y no es posible instalar Luks desde el mismo, aunque permite instalar Debian al modo clásico. Sólo en este caso realizar los sgts. pasos.<br /><br /><span style="color: rgb(0, 0, 0);font-family:verdana;font-size:85%;" >Utilizaremos como estándar de documentación:</span><span style="font-size:85%;"><br /></span><span style="color: rgb(0, 0, 0);font-family:verdana;font-size:85%;" ># para referirnos a superusuario (root)</span><span style="font-size:85%;"><br /></span><span style="color: rgb(0, 0, 0);font-family:verdana;font-size:85%;" >$ para referirnos a un usuario</span><br /><br />1. dd if=debian-eeepc_20080907.img oflag=direct of=/dev/sdb<br /><br />Saltar al item .5 y llevar adelante una instalación clásica de Debian.<br /><br />1. Descargar la imagen iso y comprobar su integridad vía md5sum.<br /><span class="anchor" id="line-27"></span><a class="http" href="http://eeepc.debian.net/images/debian-eeepc_20080907.img"></a><a class="http" href="http://www.debian.org/devel/debian-installer/">http://www.debian.org/devel/debian-installer/</a><br /><br />2. Descargar "boot.img.gz" de /debian/dists/lenny/main/installer-i386/current/images/hd-media del mirror que prefieras.<br /><br />3. Copiar "boot.img.gz" a tu pendrive, donde X es el dispositvo que tu pendrive está utilizando.<span class="anchor" id="line-28"></span><br /><br /># zcat boot.img.gz > /dev/sdX<br /><span class="anchor" id="line-29"></span><br />4. Montar el pendrive y copiar la imágen ISO allí.<br /><br />5. Colocar el pendrive en el puerto usb izquierdo de la EeePC, configurar Bios para que booteo primero vía USB, reiniciar y esperar...<br /><br /><span style="font-weight: bold;">Aparecerá la interfaz de instalación de Debian!</span><br /><br />A continuación es posible generar las particiones LVM y encriptarlas con LUKS, a través del instalador de Debian. En mi caso, hice un particionado clásico y luego configuré LVM con LUKS vía una terminal.<br /><ol><li>Instalar paquetes<pre class="wiki"># apt-get install cryptsetup <span style="font-family:Georgia,serif;"> </span></pre><p> Cryptsetup es una herramienta que facilita el uso de dm-crypt y se encargará de crear los dispositivos de mapeo.</p></li><li>Crear en LVM <strong>LVs</strong> para almacenar los datos encriptados. Si es necesario, crear el/los <strong>VGs</strong> también. <pre class="wiki"># vgcreate crypto /dev/sda2<br /></pre><pre class="wiki"># lvcreate -n home --size 40g crypto<br /></pre></li><li>Crear el logical volume encriptado <pre class="wiki"># cryptsetup luksFormat /dev/mapper/crypto-home<br /></pre></li><li>Abrir el device y mapearlo en el <strong>mapper. Mapper </strong>es una interfaz uniforme de acceso a los discos.<br /><pre class="wiki">#cryptsetup luksOpen /dev/mapper/crypto-home home<br /></pre>Cryptofs va a montar la partición desencriptada y se creará una entrada directa en:<pre class="wiki">/dev/mapper/home</pre></li><li>Formatear las particiones <pre class="wiki">mkfs.ext3 -L homefs /dev/mapper/home<br /></pre></li><li>Editar el <strong>/etc/crypttab</strong> (para que cryptosetup los abra al inicio) <pre class="wiki">home /dev/mapper/crypto-home none luks<br />swap /dev/mapper/crypto-swap none luks,swap<br /></pre></li><li>Agregar las entradas en el <strong>/etc/fstab</strong> <pre class="wiki"># Cryptofs<br />/dev/mapper/home /home ext3 defaults,noatime 0 2<br />/dev/mapper/swap none swap sw 0 0<br /></pre></li><li>Agregar los datos necesarios al ramdisk <pre class="wiki">update-initramfs -u -k all<br /></pre></li></ol>Analía Lorenzattohttp://www.blogger.com/profile/07923900145462112039noreply@blogger.com0tag:blogger.com,1999:blog-2720195421602751185.post-90402066266958885722008-08-25T20:53:00.003-03:002009-11-04T21:30:27.508-03:00Sshfs (Ssh filesystem)Es un sistema de archivos que opera sobre un host remoto, de modo seguro (a través de SSH) y el modulo del kernel local FUSE.<br />La idea es interactuar con un servidor remoto ssh, pero de modo transparente, es decir, como si estuvieras en la misma máquina.<br /><br /><br /><span style="font-weight: bold;">Configuración inicial</span><span style="font-style: italic; font-weight: bold;"><br /></span><br /><span style="color: rgb(0, 0, 0);font-family:verdana;font-size:85%;" >Utilizaremos como estándar de documentación:</span><span style="font-size:85%;"><br /></span><span style="color: rgb(0, 0, 0);font-family:verdana;font-size:85%;" ># para referirnos a superusuario (root)</span><span style="font-size:85%;"><br /></span><span style="color: rgb(0, 0, 0);font-family:verdana;font-size:85%;" >$ para referirnos a un usuario</span><br /><br /><br /><span style="font-style: italic;"><span style="font-weight: bold;"><span style="font-style: italic;"><span style="font-weight: bold;"></span></span></span></span>La configuración que sigue a continuación, debe realizarce, en el host en el cual se requiere montar los datos.<br /><br />1. Paquetes requeridos para Debian.<br />#apt-get update && apt-get install fuse-utils sshfs;<span style="font-style: italic; font-weight: bold;"><span style="font-weight: bold;"><span style="font-style: italic;"><br /></span></span></span><br />2. Se crea directorio de montado.<br />#mkdir /mnt/sshfs<br /><br />3. Se conceden permisos de acceso al directorio de montado.<br />3.1 #chown usuario:grupo /mnt/sshfs<br />3.2 #chmod 755 /mnt/sshfs<br /><br /><span style="font-weight: bold;">usuario</span> es el usuario que desea montar el filesystem.<br /><span style="font-weight: bold;">grupo</span> es el grupo del cual forma parte "usuario" con permisos de montado del filesystem.<br /><br />4. Agregar <span style="font-weight: bold;">usuario</span> al grupo <span style="font-weight: bold;">fuse</span><br /># adduser usuario fuse<br /><br />5. Comprobar permisos para fuse. <span style="font-weight: bold;">No deberíamos cambiarlos.</span><br />$ ls -l /dev/fuse<br />crw-rw---- 1 root fuse 10, 229 ago 27 17:00 /dev/fuse<br /><br /><span style="font-weight: bold;">Cómo usarlo</span><br />1. Para montarlo<br />$sshfs user@host-remoto:/musica /mnt/sshfs<br /><br />2. Para desmontarlo<br />$fusermount -u /mnt/sshfs<span style="font-style: italic; font-weight: bold;"><span style="font-weight: bold;"><span style="font-style: italic;"><span style="font-weight: bold;"><span style="font-style: italic;"><br /><br /></span></span></span></span></span><br /><br /><span style="font-weight:bold;">Sshs tiene varios parámetros opcionales, los cuales lo hacen bastante nice :)<br />A saber:</span><br /> -o reconnect<br /> reconnect to server<br /><br /> -o sshfs_sync<br /> synchronous writes<br /><br /> -o no_readahead<br /> synchronous reads (no speculative readahead)<br /><br /> -o sshfs_debug<br /> print some debugging information<br /><br /> -o cache=YESNO<br /> enable caching {yes,no} (default: yes)<br /><br /> -o cache_timeout=N<br /> sets timeout for caches in seconds (default: 20)<br /><br /> -o cache_X_timeout=N<br /> sets timeout for {stat,dir,link} cache<br /><br />En mi caso, hice un script lanzado desde mi .xsession, el cual se encarga de montar un directorio de musica desde otra pc. Para el cual me fueron super útiles algunos de los parámetros antes mencionados.Analía Lorenzattohttp://www.blogger.com/profile/07923900145462112039noreply@blogger.com0tag:blogger.com,1999:blog-2720195421602751185.post-58575579812505972902008-08-24T17:36:00.002-03:002009-11-04T21:29:54.687-03:00Montar dispositivo USBSi bien montar dispositivos extraíbles en Debian no tiene mayores complejidades, requiere llevar adelante una serie de pasos hasta lograrlo.<br /><br />Existen otros métodos más sencillos, como pueden ser: mountd, automount, etc., que se encargan de hacer estas cosas automágicamente, pero lo dejaré para otro post ;)<br /><br />Linux asigna a cada dispositivo un identificador dentro de los devices (/dev/) que suele ser secuencial para cada uno de su tipo. Los dispositivos USB son identificados en el grupo periféricos SCSI (sd por "SCSI disk") y por lo tanto se ven como /dev/sdXn, donde “X” es la letra que representa el orden de los dispositivos y “n” el numero de partición en dicho dispositivo. En este ejemplo, el device se ve como segundo disco SCSI y por lo tanto lo muestra como "/dev/sdb". A su vez, tiene una sola partición que se ve como "/dev/sdb1".<br /><br /><span style="color: rgb(0, 0, 0);font-family:verdana;font-size:85%;" >Utilizaremos como estándar de documentación:</span><span style="font-size:85%;"><br /></span><span style="color: rgb(0, 0, 0);font-family:verdana;font-size:85%;" ># para referirnos a superusuario (root)</span><span style="font-size:85%;"><br /></span><span style="color: rgb(0, 0, 0);font-family:verdana;font-size:85%;" >$ para referirnos a un usuario</span><br /><br />Para "levantar" un pen-drive, entonces:<br /><br />1. Conectar físicamente el dispositivo al conector USB.<br />2. Identificar el nombre de dispositivo el cual reconoce el sistema operativo. Para ésto, nada más práctico que colgarse a un dmesg:<br /><br /><span style="color: rgb(0, 0, 0);"> # watch dmesg</span><br /><br />En caso de que el sistema operativo no reconozca el dispositivo USB, es posible que falte cargar el modulo "usb_storage" al kernel.<br /><br />2.1 Comprobar si el modulo está cargado:<br /># lsmod | grep usb_storage<br /><br />2.2 En caso de que no esté cargado, hacemos:<br /># modprobe usb_storage<br /><br />2.3 Si deseamos que el módulo se cargue siempre en forma forzada al iniciar la PC:<br /># echo usb_storage > /etc/modules<br /><br />3. Agregar entrada en el fichero "/etc/fstab". El mismo es leído por el S.O para identificar permisos de montado y tipo de filesystem del mismo.<br /><br /><span style="color: rgb(0, 0, 0);"> # </span><span style="color: rgb(0, 0, 0);" class="postbody">echo /dev/sdb1 /media/usb vfat rw,user,noauto 0 0 > /etc/fstab</span><span class="postbody"><br /></span><span class="postbody"><span style="font-weight: bold;"><br />/dev/sdb</span> es el dispositivo físico identificado por el S.O.<span style="font-weight: bold;"><br />mount /media/usb</span> es el directorio donde se montará el dispositivo extraíble.<br /><span style="font-weight: bold;">vfat</span> es el sistema de archivos FAT32. Puede ser otro.<br /><span style="font-weight: bold;">rw</span> dispositivo accesible en modo de lectura y escritura.<br /><span style="font-weight: bold;">noauto</span> el dispositivo no se montará automáticamente.<br /><span style="font-weight: bold;">user</span> para que un usuario diferente de root lo puede montar.<br /><span style="font-weight: bold;">0</span> no verificará el sistema de archivos al levantar la PC, con 1 si lo hace. Como el pendrive no siempre estará montado al iniciar la PC, no tiene sentido forzar la verificación.<br /><span style="font-weight: bold;">0</span> no montará automáticamente el dispositivo al prender la PC. 1 es para que lo haga, pero no tiene sentido para un dispositivo USB removible.<br /></span><span class="postbody"><br />4. Permisos al directorio en el cual se montará la dispositivo.<br /></span><span style="color: rgb(0, 0, 0);" class="postbody"> #chown usuario:grupo /media/usb<br /></span><span style="color: rgb(0, 0, 0);" class="postbody"> #chmod 755 /media/usb </span><br /><span class="postbody"><br /><span style="font-weight: bold;">usuario</span> es el usuario permitido para montar dispositvo USB.<br /><span style="font-weight: bold;">grupo</span> es el grupo al cual pertenece el usuario permitido para montar dispositivo USB<br /><br />5.1 Montar el dispositivo. Como usuario:<br /></span><span style="color: rgb(0, 0, 0);" class="postbody"> $mount /media/usb<br /></span><span style="color: rgb(0, 0, 0);" class="postbody"></span><span class="postbody"><br />5.2 Montar el dispositivo. Como root:<br />#mount -t vfat /dev/sdb1 /media/usb<br /><br /></span>Analía Lorenzattohttp://www.blogger.com/profile/07923900145462112039noreply@blogger.com1