Conociendo a Debian - Infografia -

-click para agrandar-

fuente: ubuntronics.com

Tip: Firewall Off




  Hoy leí en un blog y recorde tambien que cuando instalas Red Hat, o alguno de sus derivados siempre trae iptables activo y siempre está el olvido de apagarlo o abrir los puertos que realmente necesitamos... (y en mas de una ocasión me ha pasado esto...) 


  $ service iptables stop
  $ chkconfig iptables off
o tambíen podemos editarlo a mano...
  $ vi /etc/sysconfig/iptables
  # Firewall configuration written by system-config-firewall
  # Manual customization of this file is not recommended.
  *filter
  :INPUT ACCEPT [0:0]
  :FORWARD ACCEPT [0:0]
  :OUTPUT ACCEPT [0:0]
  -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
  -A INPUT -p icmp -j ACCEPT
  -A INPUT -i lo -j ACCEPT
  -A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
  # <--Abrimos el p 80 para que httpd este accesible
  -A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
  # <-----
  -A INPUT -j REJECT --reject-with icmp-host-prohibited
  -A FORWARD -j REJECT --reject-with icmp-host-prohibited
  COMMIT
Se guarda, salimos y reiniciamos.
  $ service iptables restart
Solucionado el problema :) 

Ayudas para usar Vim

Para los que recien empiezan con linux, puede que les sea de gran ayuda estas dos imagenes con los comandos necesarios para sacar el maximo provecho:


        (click para agrandar)


...y como siempre, pueden consultar la wiki

Programación Shell

  


La comprensión  de este tema nos permitirá, básicamente:


1 - La automatización de tareas repetitivas: Como todo lenguaje de programación, ésta es la idea básica. Podremos,  por ejemplo, crear programas que borren diariamente directorios, que inicialicen archivos, que controlen el uso del espacio libre, que controlen el tamaño de las casillas de correo,  que hagan back-ups, etc.

2 - Entender el funcionamiento del Sistema Operativo: Algunos de los comandos UNIX no son programas objetos sino Shell-Scripts. Podiéndolos interpretar, se logrará una mayor comprensión del sistema.

---

Procedimiento Básico
La creación de un Shell-Script, incluye:

(a) Edición: Escribiremos el programa mediante nuestro editor standard Vi.
(b) Cambio de permiso: Debemos hacer ejecutable al programa mediante la conocida instrucción
                            $ chmod +x mi_script
o bien, dándole todos los premisos mediante:
   $ chmod 777 mi_script
(c) Ejecución: Lo ejecutamos mediante su nombre (podemos incluir ./ para mayor seguridad)
   $ ./mi_script


Nuestro Primer Shell-Script.

Antes de construir nuestro primer programa. detallaremos el siguiente comando, muy utilizado en programación Shell:

$ clear
Simplemente, limpia la pantalla.

Recomendamos la utilización de este comando como primer instrucción de cualquier programa Shell. La razón se basa en que no se cuenta con posicionamiento fila-columna como en otros lenguajes de programación.

Si no lo utilizamos, entonces, la pantalla se presentará con un nivel muy grande de desprolijidad.

También es necesario introducir en este momento al caracter de comentario. Nos referimos al símbolo numeral (#). Este símbolo, comenta una línea y sólo una. Es decir, por cada línea de comentario debo escribir un # al principio de la misma. Hechas estas aclaraciones, procederemos, entonces, a la presentación de nuestro primer Script.

Dentro de una sesión del editor vi (o vim, nano, mc etc) y escribimos:
(en otro tutorial, veremos como sacarle el jugo a vi)

# Mi primer Script.
# Autor: Fulano de tal.
# Fecha: dd-mm-aa.
clear
echo “Hola mundo”

Observaciones Iniciales Acerca de Nuestro Primer Shell-Script:
Nótese las 4 líneas de comentario iniciales. Cuando se programa en grupo, es importantísimo escribir líneas que aclaren cuál es la idea principal del programa. También podemos escribir comentarios en cualquier parte del mismo si lo consideramos necesario. Datos como autor y fecha son también usuales y relevantes.
Nuestro programa cuenta con sólo dos instrucciones que limpian la pantalla y escriben por STDOUT.

Instrucciones Para Ingreso de Datos por Teclado
Se permite el ingreso de datos por teclado mediante la sentencia:

$ read <variable>
Ej: $ read a

La instrucción anterior, permite el ingreso de un dato numérico o alfanumérico y lo guarda en la variable a.  Recordemos que dicha variable no tiene tipo predefinido. Existe una variante que acepta ingreso por teclado hasta el primer blanco. Se detalla a continuación:

$ read a junk

El hecho de cortar el string ingresado por el usuario luego del primer blanco,  permite algún grado de validación. También recordemos que como esta instrucción permite ingresar cualquier tipo de dato, es responsabilidad del programador analizar dicho contenido a posteriori.

Instrucciones de Display
Para mostrar datos por pantalla debemos utilizar el comando echo ya aprendido. Lo único a tener en cuenta es que dicho comando posee un caracter de LF (line-Feed) automático. Esto significa que si quiero ingresar un dato a continuación del cartel, en principio no es posible. Para remediar esta
situación se cuenta con dos alternativas (variantes del comando echo). A saber:

1) Incluir la opción “-n”.
      Ej: $ echo -n “Ingrese dato: “
2) Incluir la secuencia de escape “\c” al final de la instrucción.
      Ej: $ echo “Ingrese dato: \c”

Nota: Se debe probar cuál de las dos versiones se encuentra disponible en su sistema.

Solicitud de Ingreso de Datos Típica
Con los elementos aprendidos, escribiremos un Script que solicita datos por teclado y muestra lo ingresado. Por razones de espacio ya no detallaremos autor y fecha.

# Solicita ingreso de datos y muestra lo ingresado.
clear
echo -n “Ingrese número: ”
read a junk
echo -n “Usted ingresó: $a”

Condicionales y Estructuras de Repetición.
Como todo lenguaje que se precie de tal, se dispone de estructuras varias para poder justamente automatizar tareas. Detallaremos solamente las que necesitamos para el presente curso.

1)  IF
if    <condicón>
then
sentencia 1
sentencia 2
...
sentencia n
else
sentencia 1
sentencia 2
...
sentencia n
fi

Condiciones:
Como se apreciará se trata de algo bastante similar a otros lenguajes. El único inconveniente se presenta en la forma que se detalla la condición.

Lamentablemente no podemos escribir:

if  $a > $2
then
echo “La primer variable es mayor a la segunda”
fi

Necesitamos utilizar un nuevo elemento  para expresar una condición. Se trata del comando test.
Si bien dicho comando tiene muchas otras utilidades, solamente lo utilizaremos para expresar condiciones cuando sea necesario.El formato básico es el siguiente:

test $variable1 Operador $variable2
test $variable1 Operador constante

Este comando hace distinción entre datos numéricos y alfanuméricos. Esto quiere decir que se presentan 2 variantes en su utilización con distintos operadores:

a)  Operadores Alfanuméricos del comando Test.
Se consideran la igualdad y desigualdad.

OPERADOR SIGNIFICADO
= Igual
!= Distinto

b)  Operadores Numéricos del comando Test.
Se consideran los siguientes:

OPERADOR SIGNIFICADO
-eq Igual (equal)
-ne Distinto (Not equal)
-lt Menor que (Less than)
-le Menor o igual (Less or equal)
-ge Mayor o igual (Greater or equal)
-gt Mayor que (Greater than)


Ha llegado el momento de ejemplificar los comandos if y test
# Solicita el ingreso de un número e informa si es menor, o mayor o igual a 3.
clear
echo -n “Ingrese número: ”
read num
if test $num -lt 3
then
echo  “Es menor a 3”
else
echo  “Es mayor o igual a 3”
fi

El comando test posee otra forma de escritura que se detalla a continuación:
# Solicita el ingreso de un número e informa si es menor, o mayor o igual a 3.
# Utiliza otra forma de escribir el comando test.
# Se usan corchetes.
clear
echo -n “Ingrese número: ”
read num
if [  $num -lt 3 ]
then
echo  “Es menor a 3”
else
echo  “Es mayor o igual a 3”
fi

Nótese la utilización de corchetes en vez de la palabra test.

2)  WHILE
while    <condición>
do
sentencias
done

# Solicita el ingreso de un número hasta que sea mayor o igual a 3
clear
echo -n “Ingrese número: ”
read num
while test  $num -lt 3
do
echo  “Es menor a 3”
echo -n “Ingrese número: ”
read num
done

3)  FOR
for  var  in  <lista>
do
sentencias
done

Esta estructura es notablemente diferente a lo que un lenguaje típico nos tiene acostumbrados.
Necesitamos aclarar que no disponemos ni de vectores, ni matrices para subindicar. Tampoco contamos con punteros como en lenguaje C. Daremos un primer ejemplo sencillo y luego uno más útil donde se ve claramente para que se usa en la práctica esta estructura.

# Muestra 1 2 y 3
# :-(
clear
for  i  in  1 2 3
do
echo $i
done

Como se puede apreciar en el ejemplo anterior, no parece de mayor utilidad esta estructura, por lo menos, de esta manera. La forma útil de aplicarla se basa en la idea de hacer la lista variable.
Por ejemplo:

# Copia los archivos de un directorio a otro
# Un tanto más útil
clear
for  i  in   `ls`
do
echo $i
cp $i /tmp
done

3)  CASE
for  $var  in
(primer valor) sentencia 1
sentencia 2
...
sentencia n
;;

(segundo valor) sentencia 1
sentencia 2
...
sentencia n
;;

(*) sentencia 1
sentencia 2
...
sentencia n
;;
esac

Esta estructura permite la múltiple selección. O sea que puede ser reemplazada por varias estructuras del tipo if. El contenido de los paréntesis se refiere al hipotético contenido de la variable.
Entre opción y opción se debe colocar doble punto y coma (;;). El asterisco (*) significa “cualquier otro valor distinto de los anteriores”. Pasamos al ejemplo:

# Ingresa un dato y valida si es uno, dos, pepe u otro valor.
clear
echo -n “Ingrese un dato: “
read dato
case $dato in
1) echo “Usted  ingresó uno”
;;
2) echo “Usted  ingresó dos”
;;
pepe) echo “Usted ingresó pepe”
;;
*) echo “Usted ingresó otro valor”
;;
esac


Loop infinito e Instrucciones Asociadas
Contamos con una variable de significado especial denominada true. Dicha variable presenta la particularidad de ser siempre verdadera. Podemos escribir, entonces, el siguiente loop infinito:

# No hagan esto jamás
clear
while true
do
echo “Y ahora?"
done

Al ser siempre verdadera la condición,  se muestra eternamente por STDOUT el contenido del comando echo.
La idea de considerar este tipo de loop radica en que existen comandos para poder salir de él o continuar la iteración en forma elegante. De esta forma  se permite salir del ciclo while por varias condiciones distintas y no por UNA  SOLA como hemos visto hasta ahora.
El comando break permite salir del ciclo más interno.
El comando continue continúa con la próxima iteración del ciclo.
Estos comandos están también disponibles en C.

A continuación se ejemplifica la utilización del loop infinito.

# Solicita el ingreso de un número hasta que sea igual a 9.
clear
while true
do
echo -n “Ingrese un número: ”
read num
if test  $num -eq 9
then
echo  “Usted ingresó 9”
break
fi
echo  “Usted no ingresó 9”
done

En el ejemplo anterior, el ciclo se corta con la instrucción break, si el número ingresado es igual a 9. Si la condición es falsa, se sigue solicitando el ingreso de otro número.

A continuación se puede observar otra manera de escribir el código anterior, utilizando el comando continue.
Nótese que ambos programas son equivalentes.

# Solicita el ingreso de un número hasta que sea igual a 9.
clear
while true
do
echo -n “Ingrese un número: ”
read num
if test  $num -ne 9
then
echo  “Usted no ingresó 9”
continue
else
echo  “Usted ingreso 9”
break
fi
done

Programa Menú. (Primer Modelo)
A continuación se detalla el código necesario para escribir un programa menú. En principio se trata de 4 Shell-Scripts. El primero contiene el cuerpo principal que muestra las opciones por pantalla, solicita el ingreso por teclado y llama a los otros 3. Estos son quienes resuelven verdaderamente las opciones de dicho menú. Más adelante veremos que es posible hacer esto mismo mediante llamadas a funciones y librerías.

# Programa Menu, cuerpo principal.
while true
do
clear
echo -n “Menu General para Tareas Varias
1) Ver directorio corriente
2) Borrar un archivo
3) Mostrar un archivo
4) Fin

Digite la opción deseada: “

read a
case $a in
1) ./verdir;;
2) ./borrar;;
3) ./mostrar;;
4) exit;;
*);;
esac
done

# Script verdir /  Muestra el contenido del directorio corriente.
clear
ls
echo -n “Presione <ENTER> para continuar: “
read a

# Script mostrar / Muestra el contenido de un archivo.
clear
echo -n “Ingrese el nombre del archivo a mostrar: “
read a
more $a
echo -n “Presione <ENTER> para continuar: “
read a

#Script borrar / Borra un archivo.
clear
echo -n “Ingrese el nombre del archivo a borrar: “
read a
rm $a
echo -n “Presione <ENTER> para continuar: “
read a

Observaciones Varias Acerca del Programa Menú:
Como se podrá notar, el cuerpo principal consiste en un loop infinito que finaliza por la opción número 4, que llama a la instrucción exit. También es importante destacar el formato de la instrucción echo multilínea.
Otro detalle que merece atención son las 2 últimas instrucciones de los scripts secundarios.
La idea es detener la ejecución para que puedan verse los resultados en pantalla antes de que el cuerpo principal ejecute la instrucción clear.
Hay otra manera de obtener el mismo resultado y es considerando la instrucción sleep que literalmente duerme la ejecución del programa por n segundos.
Ej:

$ sleep 20
El comando anterior detiene la ejecución del programa por 20 segundos y luego devuelve el prompt.


Operaciones aritméticas:
Lamentablemente, si probamos sumar como lo hace el siguiente script:

# Intenta sumar dos números.
clear
c=0
echo -n “Ingrese el primer número a sumar: “
read a
echo -n “Ingrese el segundo número a sumar: “
read b
c=$a+$b
echo  “La suma es: $c”

llegaremos a la conclusión de que esa no es la forma de hacerlo. Lo que sucede es que el shell le asigna el dato alfanumérico “$a+$b” a la variable c.
Para realizar operaciones aritméticas necesitamos utilizar el comando expr.

c=`expr $a + $b`

Esta es la forma correcta de sumar. Nótese, además, que es necesario utilizar las back-quotes.
Las operaciones permitidas para el comando expr son: la suma (+), la resta (-), la multiplicación (\*), la división (/) y el resto de la división entera (%).

Programa Par / Impar. (Segundo modelo).
A continuación se detalla el código de un programa que solicita un número por teclado y decide si es par o impar.

# Informa si un número es par o impar.
clear
echo -n “Ingrese un número: “
read numero
resto=`expr $numero % 2`
if test $resto -eq 0
then
echo “El número que usted ingresó es par!.”
else
echo “El número que usted ingresó es impar!.”
fi

Programa Promedio (Tercer modelo)

Para realizar un programa que obtenga un promedio de notas ingresadas por teclado, deberemos realizar lo siguiente...
Se sugiere que la condición de fin sea la nota 99.
La idea básica es contar con una estructura de repetición, cuya condición de fin sea el número 99.
Mientras se ingresan notas, se debe sumar y contar. Para ello definiremos las siguientes estructuras:

cont=`expr $cont + 1`        (contador)
sum=`expr $sum + $var`   (sumador)

Programa Factorial. (Cuarto modelo)
Para realizar un programa que obtenga el factorial de un número ingresado por teclado tendremos en cuenta lo siguiente
Se cuenta con todos los elementos necesarios para la resolución del  modelo. Simplemente se refrescará la definición matemática de factorial:

n!=n * (n-1) * (n-2) * (n-3) * ..... * 1
0!=1

Ejemplo: 4!=4*3*2*1=24

Esto último significa que basta con utilizar alguna estructura de repetición para ir realizando los productos.

Programa de Número Capicúa. (Quinto modelo)
Deberemos Realizar un programa que solicite un número por teclado e informe si es capicúa o no.
Se podría decir que lo más complicado en este modelo es poder separar cada uno de los dígitos del número. Recordemos que la instrucción read ingresa el número completo. Por otro lado, el programa debe contemplar también, números de n dígitos, o sea, una cantidad variable.

Parámetros Posicionales
Existe una segunda manera de que un programa reciba datos. (Recordemos que la primera consiste en la utilización del comando read). De la misma forma que un programa C, un script puede recibir datos a través de parámetros. Por ejemplo:

$ ./suma_numeros 5 8

Arriba, se puede observar cómo se le pasan parámetros al script suma_numeros en la línea de comandos, separados por blancos.  A su vez. el script reconoce a dichos parámetros
como $1, $2, ...., $9 (hasta nueve en forma standard).
A continuación se codifica un programa que muestra sus dos parámetros.

# muestra_parametros.
# Muestra sus dos parámetros.
clear
echo  “Primer Parámetro: $1“
echo  “Segundo Parámetro: $2“

Se supone que dicho script fue invocado desde la línea de comandos como:

$ ./muestra_parametros 67  23
Por lo tanto, el STDOUT del mismo es:

$ Primer Parámetro: 67
$ Segundo Parámetro: 23

El comando Shift
Alguien se podría preguntar qué sucede cuando se necesita pasarle al script más de 9 parámetros.
Para ello se cuenta con el comando shift. Por cada ejecución de dicho comando, se corren de derecha a izquierda cada uno de los parámetros, permitiéndose así ingresar uno más. Esto quiere decir que, por ejemplo, $1 es reemplazado por $2, $9 es reemplazado por el décimo parámetro.
Resumiendo:
Por cada instrucción shift, sucede lo siguiente:

PARAMETRO ES REEMPLAZADO POR Y PASA A SER LUEGO
$9 El décimo parámetro $8
$8 $9 $7
$7 $8 $6
$6 $7 $5
$5 $6 $4
$4 $5 $3
$3 $4 $2
$2 $3 $1
$1 $2 SE PIERDE

Variables pre-definidas del Shell
Además de las variables de ambiente, y, relacionadas con el tema de  parámetros posicionales, se cuenta con las siguientes variables para uso en programación Shell:

VARIABLE SIGNIFICADO
$# Número de parámetros del script
$* Todos los parámetros del script
$0 Nombre del Script
$1,..,$9 Cada uno de los parámetros posicionales del script
$? Valor de retorno del último comando ejecutado
$$ Número de proceso del shell corriente
$! Pid del último comando ejecutado en back-ground

Obsérvese con atención el STDOUT del siguiente programa:

# muestra_ variable s_predefinidas.
# Muestra parametros posicionales y demás variables predefinidas.
clear
while  [  $# -ge 0  ]
do
echo  “Nombre del Script: $0“
echo  “Primer Parámetro: $1“
echo  “Todos los Parámetros: $*“
echo  “Cantidad de Parámetros: $#“
echo  “Pid de mi Shell: $$“
shift
done

La variable $0 no es afectada por el shift, es decir, no se pierde.
La variable $$, tiene un número único por sesión (el pid del shell) por lo que se utiliza normalmente para definir un archivo con nombre único:

$ vi yo$$
El shell reemplaza la variable $$ por un número, por ejemplo: 21345. Por lo que en realidad se está invocando al archivo yo21345, único en el sistema. (Difícilmente alguien haya creado un archivo con ese nombre.

La variable $? es muy útil cuando necesitamos saber si la ejecución de un comando fue exitosa.
Por Ejemplo:

$ cp a b
$ echo $?

Si fue exitosa la ejecución del comando cp (seguramente si), la variable $? contendrá 0 (Salida exitosa). Caso contrario presentará otro valor. Ej:

$ cp a a
$ echo $?

Al fallar el comando cp, la variable vale 2. Este valor depende del comando, se debe revisar la documentación para saber qué valor retornará por error.
De esta forma, en los shell-scripts puede validarse la ejecución exitosa de los comandos.

Programa de Temperaturas. (Sexto modelo)
Para ejemplificar el uso del comando shift y de los parámetros posicionales, se detallará el código necesario para construir un programa que calcule la Ciudad con temperatura más baja.
Se ingresan por parámetros el par ordenado Ciudad y Temperatura.
Se sugiere validar que se ingresen datos y sean pares.

# calcula_temperatura_minima.
# Muestra ciudad y temperatura mínima.
clear
minimo=99
resto=`expr $# % 2`
if test $# -eq 0
then
echo “Debe ingresar Ciudad y Temperatura”; exit 2
fi
if test $resto -ne 0
then
echo “La cantidad de Parámetros debe ser par”; exit 3
fi
while test $# -ge 1
do
if test $2 -lt $minimo
then
minimo=$2; ciudad=$1
fi
shift; shift
done
echo “La Ciudad: $ciudad tiene la temperatura más baja ($minimo)”

En el código anterior, vale destacar:

1) La utilización del doble shift para “correr” el par Ciudad, Temperatura,
2) La utilización de la línea multisentencia debido al poco espacio en la diapositiva,
3) La forma de validación de existencia de parámetros y cantidad par de los mismos,
4) El algoritmo utilizado para encontrar el mínimo,
5) Los 2 códigos de retornos distintos (2 y 3) que pueden ser validados a posteriori.

Funciones
La programación Shell permite el uso sencillo de funciones. Como en otros lenguajes,  se pueden pasar parámetros y devolver resultados.
Esto quiere decir, por ejemplo, que el modelo número 1 (Menu) puede ser re-escrito utilizando funciones incluidas en el mismo programa (en vez de llamar a otros scripts externos).
Básicamente hay 2 formas de escribir una función:

function sumo
sumo()
{
}

Se deberá probar cuál es la que funciona correctamente en cada sistema.
Las funciones deben escribirse al comienzo del programa.
Los parámetros que reciben las funciones se reconocen internamente como $1, $2, etc.

El siguiente programa solicita 2 números por teclado y los suma utilizando funciones:

# suma_dos_numeros.
# Solicita 2 números por teclado y los suma utilizando funciones.

function sumo
{
suma=`expr $1 + $2`
echo $suma
}

clear
echo -n “Ingrese primer número a sumar: “
read num1
echo -n “ingrese segundo número a sumar: “
read num2
result=`sumo $num1 $num2`
echo “La suma es: $result”
exit 0

Obsérvese como la función sumo recibe los parámetros como $1 y $2. Además es necesario escribir echo $suma para devolver el resultado.

Librerías
Es posible escribir todas las funciones juntas en un archivo separado denominado librería e invocarlo dentro del script que utiliza las funciones.
Primeramente crearemos un script denominado sumo2lib con el siguiente contenido:

# sumo2lib
function sumo
{
suma=`expr $1 + $2`
echo $suma
}

function resto
{
resta=`expr $1 - $2`
echo $resta
}

Como segundo paso, creamos el script principal que llama a las funciones mediante la llamada previa a la librería. La manera de incluir la librería es escribiendo como primer línea del script un punto (.), luego un blanco y luego el nombre de la librería

. sumo2lib
clear
echo -n “Ingrese primer número a operar: “
read num1
echo -n “ingrese segundo número a operar: “
read num2
result=`sumo $num1 $num2`
echo  “La suma es: $result”
result2=`resto $num1 $num2`
echo  “La resta es: $result2”
exit 0

/* Fin de la 2da Parte */