Bash it mash up

Por favor consulte: “Bash it mash up

Clonar en nuestro “home”

git clone https://github.com/revans/bash-it.git ~/.bash_it

Correr la instalación

~/.bash_it/install.sh

Editar al gusto

vim ~/.bash_profile

Se puede deshabilitar “plugins”

bash-it disable plugin chruby-auto
bash-it disable plugin chruby
bash-it disable plugin java
bash-it disable plugin jekyll
bash-it disable plugin latex
bash-it disable plugin nginx
bash-it disable plugin osx
bash-it disable plugin z_autoenv
bash-it disable plugin z

Se puede deshabilitar “aliases”

bash-it disable alias bundler
bash-it disable alias emacs
bash-it disable alias heroku
bash-it disable alias hg
bash-it disable alias homebrew
bash-it disable alias jitsu
bash-it disable alias maven
bash-it disable alias osx
bash-it disable alias rails
bash-it disable alias textmate

SSH – Llaves privadas y públicas

Key Authentication

Si un servidor SSH es visible a través de Internet, en lugar de las contraseñas, se recomienda utilizar la autenticación mediante llave pública.

Con la autenticación mediante llave pública, cada equipo tiene una llave privada y cada equipo remoto de confianza una llave pública (un gran número con propiedades particularmente matemáticas).

La llave privada se mantiene en el equipo de confianza desde el cual hacemos ingreso, mientras que la llave pública se almacena en el archivo .ssh/authorized_keys dentro de todos los equipos a los cuales se necesita ingreso para iniciar sesión.

Cuando se ingresa a otro equipo, el servidor SSH utiliza la llave pública para “bloquear” los mensajes de una manera que sólo pueden ser “desbloqueados” con nuestra propia llave privada – esto significa que incluso el atacante más curioso le será muy difícil espiar, o interferir con nuestra sesión.

Passphrase

Como medida de seguridad adicional, los programas SSH pueden almacenar la llave privada en un formato de contraseña-protegida, de modo que si el equipo es robado o quebrantado, se puede tener un tiempo suficiente para desactivar nuestra llave pública, antes de que terceros puedan romper la contraseña e iniciar sesióon utilizando nuestra propia llave privada.

Bruteforce

Las llaves son mucho más difíciles de quebrantar mediante la fuerza bruta, o de suponer contraseñas simples, presentan longitud de llave amplia de la clave.

Key Pairs

La autenticación mediante llaves utiliza “dos llaves”, una llave “pública” que nadie pueda ver, y otra llave “privada” que sólo cada propietario pueda ver. Para lograr una comunicación segura con otro equipo, mediante la autenticación basada en llaves, se debe crear una llave pública para cada equipo que se necesite acceder, de la misma manera se debe copiar de manera segura la llave pública que le vamos a confiar.

mkdir ~/.ssh

chmod 700 ~/.ssh
ssh-keygen -t rsa -b 2048 -f ~/.ssh/id_rsa -P "" -q
-f

Define el nomnbre de archivo de la llave.

-q

Genera las llaves en silencio.

-P

Proporciona la contraseña-protegida vieja.

Transferir la llave cliente al equipo

La llave que hay que transferir al otro equipo de confianza es la llave pública. Si podemos ingresar a otro equipo a través de SSH mediante una contraseña, entonces sí se puede transferir nuestra clave RSA desde nuestro propio ordenador:

ssh-copy-id user@example
ssh-copy-id -i ~/.ssh/id_rsa.pub user@example.com

Si el directorio ~/.ssh sí existe en el equipo remoto:

cat ~/.ssh/id_rsa.pub | ssh user@example.com 'cp ~/.ssh/authorized_keys ~/.ssh/authorized_keys_original_backup; cat >> ~/.ssh/authorized_keys'
cat ~/.ssh/id_rsa.pub | ssh user@example.com 'cp ~/.ssh/authorized_keys ~/.ssh/authorized_keys_original_`date +%F_%T | sed 's/[:-]/_/g'`; cat >> ~/.ssh/authorized_keys'

Si el directorio ~/.ssh no existe en el equipo remoto:

cat ~/.ssh/id_rsa.pub | ssh user@example.com 'mkdir ~/.ssh; chmod 700 ~/.ssh; cat >> ~/.ssh/authorized_keys'

Una vez que hay confianza en la autenticación mediante llaves los comandos como: ssh, rsync y scp se pueden usar con o sin el archivo de identidad o llave privada.

SCP

scp ~/scp.txt user@example.com:~/scp.txt
scp ~/scp.txt user@example.com:~/scp.txt_`date +%F_%T | sed 's/[:-]/_/g'`
scp -o IdentityFile=/home/user/.ssh/id_rsa -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ~/scp.txt user@example.com:~/scp.txt
scp -o IdentityFile=/home/user/.ssh/id_rsa -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ~/scp.txt user@example.com:~/scp.txt_`date +%F_%T | sed 's/[:-]/_/g'`

SSH

ssh user@example.com 'ls -la ~/'
ssh -i /home/user/.ssh/id_rsa -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null user@example.com 'ls -la ~/'

RSYNC

Las opciones SSH son esenciales para correr Rsync en silencio:

rsync --timeout=30 -q -e "ssh -i /home/user/.ssh/id_rsa -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" ~/rsync.txt user@example.com:~/rsync.txt_`date +%F_%T | sed 's/[:-]/_/g'`

El fin

ssh user@example.com 'rm -rf ~/scp.txt*; rm -rf ~/rsync.txt*; ls -la ~/'

Crontab – Cheat sheet

EDITOR=vi && VISUAL=vi crontab -e

Parece que el comando crontab -e consulta las variables de ambiente $EDITOR y $VISUAL para usar un editor específico, por lo tanto:

export VISUAL=vim
export EDITOR=vim

podría funcionar bien para editar crontab utilizando vim.

Tabla de cron auto-documentada (con un ejemplo), es un diagrama con los comentarios necesarios para ayudarnos a recordar la sintaxis de crontab:

# * * * * * Comando a correr
# - - - - -
# | | | | |
# | | | | +- - - - Día de la semana   (0 - 6) (Domingo=0)
# | | | +- - - - - Mes                (1 - 12)
# | | +- - - - - - Día del mes        (1 - 31)
# | +- - - - - - - Hora               (0 - 23)
# +- - - - - - - - Minuto             (0 - 59)

Por ejemplo:

# Alarma diaria a las 5:30AM
30 5 * * * /home/josoroma/alarma.sh

Las esquinas oscuras de AWK

AWK es un lenguaje de Escaneo y procesamiento de patrones.

Dark Corners (poorly documented or not documented at all)

Brian Wilson Kernighan“Dark corners are basically fractal — no matter how much you illuminate, there’s always a smaller but darker one.” –Brian Kernighan.

Gawk es una implementación mejorada de parte desde el proyecto GNU para el lenguaje de programación AWK. La línea de comando consite de opciones:

  • Propias de Gawk.
  • El programa de texto Awk (si no se especifíca vía -f o –file).
  • Los valores disponibles mediante las variables predefinidas ARGC y ARGV.

Pgawk es la versión “profiling” de gawk. Es identíco en todo aspecto a Awk, excepto que los programas corren más despacio, debido a que producen de manera automática un perfil (awkprof.out) Por favor consulte la opción –profile.

Dgawk es un “debugger“, en vez de correr el programa de manera directa, más bien carga el código fuente del programa y luego pregunta por comandos necesarios para hacer debugging. A diferencia de Gawk en Pgawk, Dgawk sólo procesa el código fuente suministrado con la opción -f. El debugger se encuentra documentado en el recurso “GAWK: Effective AWK Programming“.

La función básica de awk permite buscar líneas en archivos (unidades de texto) que contienen ciertos patrones. Cuando una línea coincide con uno de los patrones, awk realiza las acciones especificadas en esa línea. awk se mantiene procesando líneas de entrada hasta llegar al final de los archivos de entrada. Los programas en awk son diferentes a los de otros lenguajes.

Formato de opciones

Las opciones de Gawk pueden ser cualquiera de las dos, el estilo tradicional POSIX conformado por opciones de una letra o el estilo GNU de opciones largas.

Las opciones POSIX empiezan con un sólo guión “-” y las opciones largas GNU empiezan con dos. Los opciones largas se encuentran disponibles para características específicas de GNU y para características mandated de POSIX.

Empecemos con awk

Como los programas awk son basados en datos, eso es todo, se describen los datos con los que deseamos trabajar y se dice que hacer cuando se encuentran. La mayoría lenguajes de programción son procesales, hay que describir en detalle cada paso que el programa toma. Cuando se trabaja con lenguas procedimentales, por lo general es más difícil describir con claridad los datos vamos a procesar con el programa. Por esta razón, con frecuencia, los programas awk son fáciles de escribir y de leer.

Cuando ejecutamos un programa awk, le dicimos a awk qué es lo que dede hacer. El programa consiste en una serie de reglas, donde cada regla especifica un patrón a buscar y una acción a realizar cuando se encuentra el patrón. Sintácticamente, una regla consiste de un patrón seguido por una acción.

La accións encuentra entre llaves, se separa del patrón. De manera usual, las reglas se separan por líneas. Por lo tanto, un programa awk se puede ve así:

pattern {action}
pattern {action}

¿Cómo ejecutar programas AWK?

Hay varias formas de ejecutar un programa awk. Si el programa es corto, más fácil correrlo desde la línea de comando que corre awk, por ejemplo:

awk SCRIPT archivo-entrada-1 archivo-entrada-2 ...

Cuando el programa es largo, es más conveniente realizar un script en un archivo, para que pueda ser corrido como en el siguiente ejemplo:

awk -f SCRIPT archivo-entrada-1 archivo-entrada-2 ...

Trataremos ambos mecanismos, junto con algunas variaciones en cada uno.

Una mirada a Progamas AWK

Una vez que se esté familiarizado con awk, es más simple escribir programas que utilicen awk. De esta manera se puede escribir programas como el primer argumento de un programa awk, por ejemplo:

awk SCRIPT archivo-entrada-1 archivo-entrada-2 ...

donde el programa es compuesto por una serie de patrones y acciones.

Este formato de comandos realiza: Ordenes al shell o intérprete de comandos, para iniciar awk y utilizar el programa para procesar los registros de los archivos de entrada. Se usan las comillas simples alrededor del programa, de esta manera el shell no interpretará los caracteres awk como caracteres especiales del shell.

Las comillas simples hacen que el shell trate todo el programa como un solo argumento para awk, lo que permite que el programa sea de más de una línea. Este formato es muy útil para correr programas awk que sean cortos o mediano a partir de shell scripts, esto evita la necesidad de usar un archivo separado para el programa awk.

Un script de shell autónomo es más confiable, porque no hay otros archivos que puedan perderse. Parece muy simple, más adelante, se presentan varios programas cortos independientes (self-contained programs).

Corriendo awk sin archivos de entrada

Awk también se puede correr sin especificar archivos de entrada, es decir, lo que sea que se escriba en la terminal o línea de comandos:

awk 'programita'

awk aplica el programa a la entrada estándar, que por lo general significa: lo que sea que se escriba en la terminal. Esto continúa hasta se indica el fin de un archivo (Ctrl-D). (En otros sistemas operativos, el carácter de fin de archivo puede ser diferente. Por ejemplo, en OS/2, es Ctrl-z).

Por ejemplo, el siguiente programa imprime un trozo o pequeño consejo (de Douglas Adams “Guide to the Galaxy”), para evitar preocupaciones debido a las complejidades de la programación de computadoras (BEGIN es una característica que no hemos empezado a discutir):

awk "BEGIN { print \"'Tranquilidad'\" }"

Este programa no lee archivo de entrada. El uso de ‘\’ antes de cada una de las comillas dobles interiores es necesario debido a las reglas de de comillasparticulares del shell, en este ejeplo, se mezclan las comillas simples y las comillas dobles también.

El siguiente programa awk emula la utilidad del comando cat, copia lo que sea que se escriba en el teclado hacia la salida estándar:

awk '{ print }'
Ahora es el momento para
todos los hombres buenos.

Presione CTRL-d para salir.

Corriendo programas largos

A veces los programas awk pueden ser muy largos. En este caso, es más conveniente poner el programa en un archivo separado. Con esto se le dice a awk que utilice un archivo para su programa, de esta manera se puede usar:

awk-f SCRIPT archivo-entrada-1 archivo-entrada-2 ...

La opción -f le dice a awk que obtenga el programa de un SCRIPT o archivo fuente. Cualquier nombre de archivo se puede utilizar para ste archivo fuente. Por ejemplo, se puede crear el siguiente trozo de programa:

vi tranquilidad.awk

Begin {print "Tranquilidad" }

Entonces utilice el siguiente:

awk -f tranquilidad.awk

en esencia hace lo mismo que:

awk "BEGIN { print \"Tranquilidad\" }"

De manera general no se necesita comillas simples alrededor del nombre de archivo que se especifica con la opción -f, ya que la mayoría de los nombres de archivo no contienen ninguno de los caracteres especiales del shell.

Pero en tranquilidad.awk, el programa awk no tiene comillas simples alrededor. Las comillas sólo son necesarios para los programas que se corren en la línea de comando awk. Si desea identificar claramente los archivos de programa awk como tales, se puede añadir la extensión .awk al nombre del archivo. Esto no afecta la ejecución del programa awk, además hace más fácil el “housekeeping“.

Programas awk ejecutables

Una vez que se aprende awk, es posible escribir scripts awk autónomos, a través del mecanismo “#!” para scripts. Por ejemplo, se puede modificar archivo tranquilidad.awk agregando al principio lo siguiente:

vi tranquilidad.awk

#! /usr/bin/awk -f

Begin {print "Tranquilidad" }

Además se cambian sus permisos:

cmmod +x tranquilidad.awk

Seguidamente puede correr desde la terminal con:

./tranquilidad.awk

Los scripts awk autónomos son de gran ayuda cuando se escribe un programa que los usuarios pueden invocar sin tener la idea de que el programa está escrito en awk.

Problemas de portabilidad con “#!”

Algunos sistemas limitan la longitud del nombre del intérprete a 32 caracteres. A menudo, esto se puede trabajar mediante el uso de un enlace simbólico. Después de la ruta de awk en la línea “#!”, no se debe colocar más de un argumento. Es importante saber que el valor de ARGV[0] puede variar dependiendo del sistema operativo.

Algunos sistemas colocan a awk ahí, otros colocan la ruta completa de awk (tal como /bin/awk o /usr/bin/awk), y otros colocan el nombre del propio script (tranquilidad.awk). Por favor con confíe en el valor de ARGV[0] para proveer el nombre del script.

Los comentarios en los programas awk

Un comentario es un texto que se incluye en un programa por el bien de los lectores humanos, no se una parte ejecutable del programa. Los comentarios pueden explicar lo que hace el programa y cómo funciona.

Casi todos los lenguajes de programación permiten comentarios, ya que los programas algunas veces pueden ser difíciles de entender sin ellos. En el lenguaje awk, un comentario comienza con el símbolo # (sharp sign) y continúa hasta el final de la línea.

El carácter # no tiene que ser el primer carácter de la línea. El lenguaje awk ignora el resto de la línea después de un símbolo #. Por ejemplo, se colocar el siguiente comentario en el script tranquilidad.awk:

vi tranquilidad.awk

#! /usr/bin/awk -f

# Este programa imprime un mensaje optimista.
# Permite que todas las personas no teman a las computadoras.

Begin {print "Tranquilidad" }

El propósito de un comentario sirve para ayudarnos y para ayudar a otras personas a entender el programa al leerlo en un momento posterior.

PRECAUCIÓN: Se puede encerrar programas cortos o medianos entre comillas simples, con el fin de mantener los scripts de shell autónomos. Al hacerlo, no se deben colocar, por ejemplo, una apóstrofe (es decir, una comilla simple) dentro de un comentario (o en cualquier otro lugar del programa). Si esto se hace entonces el shell interpreta la comilla simple como la que cierra todo el programa. Como resultado, por lo general el shell muestra un mensaje sobre comillas simples coincidentes, y si awk en realidad corre, es probable que imprima mensajes extraños acerca de errores de sintaxis. Por ejemplo:

awk '{ print "hello" } # let's be cute'

El shell entiende que los dos primeros encomillados coinciden , y que un nuevo encomillado empieza al final de la línea. Por lo tanto se queda esperando “prompt”, esperando por más entradas. En awk de Unix, por ejemplo:

awk '{ print "hello" } # let's be cute'
'

error--> awk: can't open file be
error-->  source line number 1

Colocar una barra invertida (backslash) antes de las comillas simples en “let’s” no va a funcionar, ya que las barra invertida no son especiales dentro de comillas simples.

Cuestiones de comillas en el Shell

Para programas awk cortos o medianos, es más conveniente entrar el programa en la línea de comandos awk. Esto se hace encerrando todo el programa entre comillas simples. Esto es cierto si está entrando en el programa de forma interactiva en el intérprete de comandos (shell prompt), o si se escribe como parte de un Script de Shell más grande:

awk-f 'programa en texto' archivo-entrada-1 archivo-entrada-2 ...

Cuando se trabaja con el shell sirve tener un conocimiento básico de las reglas de comillas del shell. Las siguientes reglas sólo aplican a Shells estilo Bourne compatibles con POSIX (tales como Bash, el GNU Bourne-Again Shell). Si se utiliza el C Shell, se está relativamente sólo.

Elementos entre comillas se pueden concatenar con otros elementos que no estén entre comillas, así como con otros elementos que sí lo estén. El shell convierte todo en un argumento para el comando. Precediendo a cualquier carácter con una barra invertida (‘\’) coloca entre comillas ese carácter. El shell elimina la barra invertida y pasa el carácter entre comillas en el comando.

Las comillas simples protegen todo lo que se encuentra entre la apertura y el cierre de comillas. El shell no hace ninguna interpretación del texto entre comillas, lo pasa textualmente al comando.

Es imposible insertar una comilla simple dentro de un texto que se encuentre de por sí entre comillas simples. Las comillas dobles protegen la mayoría de las cosas entre la apertura y el cierre de comillas. El shell al menos hace sustituciones de variable y de comandos dentro del texto entre comillas.

Shells diferentes pueden hacer cosas adicionales al procesar texto entre comillas dobles. Dado que ciertos carácteres dentro de las comillas dobles son procesados ​​por el shell, deben ser escapadas dentro del texto. Hay que notar que los caracteres ‘$‘, ‘`‘, ‘\‘, y ‘‘, deben ser precedidos por una barra invertida dentro de las comillas dobles texto si van a ser transmitidas literalmente al programa. Por ejemplo:

awk "BEGIN { print \"'Tranquilidad'\" }"

Hay que tomar en cuenta que la comilla simple no es especial dentro de comillas dobles. Cadenas vacías se remueven cuando se producen como parte de un argumento no nulo en la línea de comandos, mientras que los objetos no nulos explícitos se mantienen. Por ejemplo, para especificar que el separador de campo FS se podría configurar a la cadena null, utilice:

awk -F "" 'programita' ARCHIVOS

No utilice la siguiente:

awk -F"" 'programita' ARCHIVOS

En el segundo caso, awk tratará de usar el texto del programa como el valor de FS, y el primer nombre de archivo como el texto del programa. Esto resulta en errores de sintáxis, además de empeorar el comportamiento.

Trucos

Mezclar comillas simples y comillas dobles es difícil. Hay que recurrir a trucos, como el siguiente:

awk 'BEGIN { print "Aquí hay una linda comilla simple '"'"' " }'

Este programa consta de tres cadenas entre comillas que se encuentran concatenadas. La primera y la tercera son comillas simples, la segunda es de comillas dobles. Esto se puede “simplificar” en:

awk 'BEGIN { print "Aquí hay una linda comilla simple '\''" }'

Otra opción es utilizar comillas dobles:

awk "BEGIN { print \"Aquí hay una linda comilla simple '\" }"

Esta opción suele ser dolorosa, porque las comillas dobles, las barras invertidas, y los signos de dólar son muy comunes en los programas awk más avanzados. Una tercera opción es usar las secuencias de escape equivalentes en octal para los caracteres entre comillas simples y entre comillas dobles, de este modo:

awk 'BEGIN { print "Aquí hay una linda comilla simple \47" }'

awk 'BEGIN { print "Aquí hay una linda comilla doble \42" }'

Esto funciona muy bien, excepto que se debe comentar con claridad lo que significan los “escapes“. Una cuarta opción es utilizar la asignación de variable de la línea de comandos, algo así:

awk -v sq="'" 'BEGIN { print "Aquí hay una linda comilla simple "sq"" }'

Si realmente se necesita usar ambos el programa awk, es probable que es mejor moverse hacia un archivo aparte, donde el shell no sea parte de la pintura, aquí se puede decir lo que se quiera decir al respecto.

Entrecomillado dentro de los archivos en lote de MS Windows

Aunque estamos enfocados en los sistemas POSIX y el shell POSIX, el problema siguiente se plantea a menudo para muchos usuarios de MS Windows, por esta razón es que se decide abordar el tema.

Los “shells” en los sistemas Microsoft Windows utilizan el carácter de comillas dobles para entrecomillar, y hacen que sea difícil o imposible el hecho de incluir un carácter de comillas dobles escapado en un script en la línea de comandos.

El siguiente ejemplo muestra cómo imprimir líneas en un archivo que se encuentran entre comillas dobles:

gawk "{ print \"\042\" $0 \"\042\" }" ARCHIVO

Archivos de datos para los ejemplos

Muchos de los ejemplos de este paso a paso toman su entrada de dos archivos de datos de muestra. El primero es, “BBS-list”, representa una lista “bulletin board systems” con información sobre dichos sistemas. El segundo archivo de datos, llamado “inventory-shipped”, contiene información sobre los envíos mensuales. En los dos archivos, cada línea es considerada como un registro.

En el archivo de datos BBS-list, cada registro contiene el nombre de un “computer bulletin board”, su número de teléfono, la velocidad de transmisión de tarjeta, y un código para el número de horas que esté en funcionamiento. Una ‘A’ en la última columna significa que la tarjeta funciona las 24 horas del día. Una ‘B’ en la última columna significa que la tarjeta sólo funciona en la tarde y los fines de semana. Una ‘C’ significa que la tarjeta funciona sólo los fines de semana:

aardvark     555-5553     1200/300          B
alpo-net     555-3412     2400/1200/300     A
barfly       555-7685     1200/300          A
bites        555-1675     2400/1200/300     A
camelot      555-0542     300               C
core         555-2912     1200/300          C
fooey        555-1234     2400/1200/300     B
foot         555-6699     1200/300          B
macfoo       555-6480     1200/300          A
sdace        555-3430     2400/1200/300     A
sabafoo      555-2127     1200/300          C

El archivo de datos “inventory-shipped” representa la información sobre los envíos durante el año. Cada registro contiene el mes, el número de cajas verdes enviadas, el número de cajas de color rojo enviadas, el número de bolsas de color naranja enviadas, y el número de paquetes azul enviados. Hay 16 entradas, que abarcan los 12 meses del año pasado y los primeros cuatro meses del año en curso.

Jan  13  25  15 115
Feb  15  32  24 226
Mar  15  24  34 228
Apr  31  52  63 420
May  16  34  29 208
Jun  31  42  75 492
Jul  24  34  67 436
Aug  15  34  47 316
Sep  13  55  37 277
Oct  29  54  68 525
Nov  20  87  82 577
Dec  17  35  61 401

Jan  21  36  64 620
Feb  26  58  80 652
Mar  24  75  70 495
Apr  21  70  74 514

Algunos ejemplos sencillos

El siguiente comando corre un simple programa awk que busca la cadena de carácteres “foo” en el archivo “BBS-list” de entrada para la cadena de caracteres ‘foo’ (un grupo de carácteres se suele llamar una cadena):

Cuando awk encuentra las líneas que contienen “foo”, las imprime mediante “print $0” que significa imprimir la línea actual (usar sólo “print” significa lo mismo).

awk '/foo/ { print $0 }' BBS-list

Se puede notar que la palabra “foo” se encuentra rodeada o entre dos barras (“/”). Las barras indican que “foo” es el patrón que se desea buscar. Este tipo de patrón se conoce como una expresión regular (ver Regexp). El patrón permite encontrar coincidencias con partes de palabras. Como hay comillas simples alrededor del programa awk, el shell no interprete nada de esto como caracteres especiales de shell.

Esto es lo que imprime este programa:

awk '/foo/ { print $0 }' BBS-list
fooey        555-1234     2400/1200/300     B
foot         555-6699     1200/300          B
macfoo       555-6480     1200/300          A
sabafoo      555-2127     1200/300          C

En una regla de awk, ya sea el patrón o la acción se pueden omitir, pero no ambos. Si se omite el patrón, entonces se realiza la acción para cada línea de entrada. Si se omite la acción, la acción predeterminada es imprimir todas las líneas que coincidan con el patrón.

Por lo tanto, en el ejemplo anterior, podemos dejar de lado la acción (la sentencia print y las llaves) y el resultado sería el mismo: awk imprime todas las líneas que coincidan con el patrón “foo”. Por otro lado, conservar las llaves y omitir la sentencia print, hace un acción vacía que no hace nada (es decir, se imprimen líneas).

Muchos programas awk prácticos son conformado por sólo una o dos líneas. Para empezar, a continuación se presenta una colección de programas cortos pero útiles. Algunos de estos programas contienen construcciones que todavía no se han cubierto. (La descripción del programa awk va a dar una buena idea de lo que hace el mismo).

La mayoría de los ejemplos usa un archivo de datos llamado: datos. Esto es sólo un marcador de ejemplo, si se usan estos programas, los tenemos que sustituir por sus propios nombres de archivo de datos. Para referencia futura, hay que tener en cuenta que a menudo hay más de una manera de hacer las cosas con awk. En algún momento, es posible podamos mirar hacia atrás en estos ejemplos y ver si podemos encontrar diferentes maneras de hacer las mismas cosas que se muestran aquí:

Imprime la longitud de la línea de entrada más larga:

awk '{ if (length($0) > max) max = length($0) } END { print max }' BBS-list

Imprime cada línea que sea mayor a 44 carácteres:

awk 'length($0) > 44' BBS-list

Nota: La única regla que hay tiene una expresión relacional como su patrón y no tiene una acción. Por lo que se utiliza la acción predeterminada, la impresión del registro.

Imprime la longitud de la línea más larga de datos:

expand BBS-list | awk '{ if (x < length()) x = length() } END { print "maximum line length is " x }'

Nota: La entrada es procesada por el comando expand, que convierte TABs en espacios, por lo que en realidad es el ancho de comparación, son las columnas del margen de la derecha.

Imprime cada línea que al menos tiene un campo:

awk 'NF > 0' BBS-list

Nota: Es una manera fácil de eliminar las líneas en blanco de un archivo (para crear un nuevo archivo, sin las líneas en blanco).

Imprime siete números aleatorios entre 0 y 100, inclusive:

awk 'BEGIN { for (i = 1; i <= 7; i++) print int(101 * rand()) }'

Imprime el número total de bytes utilizado por BBS-list:

ls -l BBS-list | awk '{ x += $5 } END { print "total bytes: " x }'

Imprimir el número total de kilobytes utilizados por BBS-list:

ls -l BBS-list | awk '{ x += $5 } END { print "total K-bytes:", x / 1024 }'

Imprime una lista ordenada con todos los nombres de usuario:

awk -F: '{ print $1 }' /etc/passwd | sort

Cuenta el númerop de líneas en BBS-list:

awk 'END { print NR }' BBS-list

Imprime las líneas pares del archivo BBS-list:

awk 'NR % 2 == 0' BBS-list

Imprime las líneas impares del archivo BBS-list:

awk 'NR % 2 == 1' BBS-list

Un ejemplo con dos reglas

La utilidad awk lee los archivos de entrada de línea en línea, una a la vez. Para cada línea, awk trata los patrones de cada una de las reglas. Si varios patrones coinciden, entonces varias acciones se ejecutan en el orden en que aparecen en el programa awk. Si no hay patrones que coinciden, entonces no se corre ninguna acción.

Después de procesar todas las reglas que coinciden con la línea (que tal vez no hay), awk lee la siguiente línea. Esto continúa hasta que el programa llega al final del archivo. Por ejemplo, el siguiente programa awk contiene dos reglas:

/12/  { print $0 }
/21/  { print $0 }

La primera regla tiene la cadena “12” como patrón y “print $0” como la acción. La segunda regla tiene la cadena “21” como patrón y también tiene “print $0” como la acción. Cada acción de cada regla está encerrada dentro de su propio par de llaves.

Este programa imprime cada línea que contiene la cadena “12” o la cadena “21”. Si una línea contiene ambas cadenas, entonces se imprime dos veces, una por cada regla.

Esto es lo que ocurre si corremos este programa en nuestros dos archivos de datos de muestra (“inventory-shipped” y “BBS-list”):

awk '/12/ { print $0 }
     /21/ { print $0 }' BBS-list inventory-shipped
aardvark     555-5553     1200/300          B
alpo-net     555-3412     2400/1200/300     A
barfly       555-7685     1200/300          A
bites        555-1675     2400/1200/300     A
core         555-2912     1200/300          C
fooey        555-1234     2400/1200/300     B
foot         555-6699     1200/300          B
macfoo       555-6480     1200/300          A
sdace        555-3430     2400/1200/300     A
sabafoo      555-2127     1200/300          C
sabafoo      555-2127     1200/300          C
Jan  21  36  64 620
Apr  21  70  74 514

Nota: Observe que la línea que comienza con “sabafoo” en Lista-BBS fue impresa dos veces, una acción de impresión por cada regla.

Un ejemplo más complejo

Ahora que se entienden algunas tareas simples, echemos un vistazo a lo que los típicos programas awk pueden hacer. Este ejemplo muestra como awk puede ser utilizado para resumir, seleccionar y ordenar la salida de otra utilidad o comando:

LC_ALL=C ls -l | awk '$6 == "Nov" { sum += $5 }
                      END { print sum }'

Este comando imprime el número total de bytes de todos los archivos del directorio actual que fueron modificados por última vez en noviembre (de cualquier año). La parte “ls-l” de este ejemplo es un comando del sistema que da una lista de los archivos en un directorio, incluyendo el tamaño de cada archivo y la fecha de la última modificación del archivo. Su salida se puede ver así:

-rw-r--r--  1 arnold   user   1933 Nov  7 13:05 Makefile
-rw-r--r--  1 arnold   user  10809 Nov  7 13:03 awk.h
-rw-r--r--  1 arnold   user    983 Apr 13 12:14 awk.tab.h
-rw-r--r--  1 arnold   user  31869 Jun 15 12:20 awkgram.y
-rw-r--r--  1 arnold   user  22414 Nov  7 13:03 awk1.c
-rw-r--r--  1 arnold   user  37455 Nov  7 13:03 awk2.c
-rw-r--r--  1 arnold   user  27511 Dec  9 13:07 awk3.c
-rw-r--r--  1 arnold   user   7989 Nov  7 13:03 awk4.c

El primer campo contiene los permisos de lectura y escritura, el segundo campo contiene el número de enlaces hacia el archivo, y el tercer campo identifica el propietario del archivo. El cuarto campo identifica el grupo del archivo. El quinto campo contiene el tamaño del archivo en bytes. Los campos sexto, séptimo y octavo contienen el mes, el día y la hora, respectivamente, que significa la última modificación del archivo. Por último, el noveno campo contiene el nombre del archivo.

La expresión ‘$ 6 == “Nov”‘ en nuestro programa awk se encarga de comprobar si el sexto campo del resultado de “ls -l” coincide con la cadena “Nov”. Cada vez que una línea tiene la cadena “Nov” en su sexto campo, se realiza la acción “sum += $5”. Esto agrega el quinto campo (tamaño del archivo) a la variable de suma. Como resultado, cuando awk ha terminado de leer todas las líneas de entrada, la suma es el total de los tamaños de todos los archivos cuyas líneas coinciden con el patrón. (Esto funciona porque las variables awk se inicializan de manera automática en cero.)

Después de que la última línea de la salida de ls haya sido procesado, entonces la regla END ejecuta y muestra el valor de la suma. En este ejemplo, el valor de la suma es 80.600.

Estas técnicas más avanzadas de awk se tratan mejor en secciones posteriores. Pero antes de pasar a una programación más avanzada con awk, se recomienda conocer cómo awk interpreta una entrada (input) y cómo muestra el resultado (output). Mediante la manipulación de campos y el uso de sentencias de impresión, se pueden producir algunos informes muy útiles, con un aspecto impresionante.

Declaraciones awk Versus Líneas

Muy a menudo, cada línea en un programa awk es una sentencia separada o una regla separada, por ejemplo:

awk '/12/  { print $0 }
     /21/  { print $0 }' BBS-list inventory-shipped

Sin embargo, gawk ignora los saltos de línea después de cualquiera de los siguientes símbolos y palabras clave:

     ,    {    ?    :    ||    &&    do    else

Una línea nueva en cualquier otro punto se considera el final de la instrucción oi sentencia.

Si se desea dividir una única sentencia en dos líneas, en un punto donde línea nueva podría terminarla, se puede continuar si finalizamos la primera línea una barra invertida (‘\’). La barra invertida debe ser el último carácter en la línea, para que se reconozca como un carácter de continuación. Una barra invertida es permitida en cualquier lugar de la sentencia, incluso en el medio de una cadena o de una expresión regular. Por ejemplo:

awk '/This regular expression is too long, so continue it\
     on the next line/ { print $1 }'

Por lo general, no se ha usado la barra invertida de continuación en los programas de ejemplo.

gawk no establece límites en la longitud de la línea, por lo tanto la barra invertida de continuación no es estrictamente necesaria, sólo hace que los programas sean más legibles. Por esta misma razón, así como por razones de claridad, en los programas de ejemplo se han mantenido la mayoría de declaraciones de una manera cortas. La barra invertida de continuación es más útil cuando el programa awk está en un archivo fuente independiente, en lugar de ser usada en la línea de comandos.

Hay que tener en cuenta que muchas implementaciones de awk son más exigentes sobre dónde puede usar la barra invertida de continuación. Por ejemplo, no se permiten para dividir una cadena constante mediante la barra invertida de continuación. Por lo tanto, por portabilidad en los programas awk, lo mejor es no dividir las líneas en medio de una expresión regular o una cadena.

PRECAUCIÓN: La barra invertida de continuación no funciona como se describe con el C shell. Funciona para los programas awk en archivos y para programas “one-shot”, siempre y cuando se utiliza un shell compatible con POSIX, como el “Unix Bourne shell” o Bash. Pero el C shell C se comporta de manera diferente! Allí, se deben usar dos barras invertidas en una fila, seguido por un salto de línea. También hay que tener en cuenta que cuando se utiliza el C shell, cada línea nueva en un programa awk debe ser escapada con una barra invertida. Para ilustrar:

% awk 'BEGIN { \
?   print \\
?       "hello, world" \
? }'

En este caso, ‘%’ y ‘?’ Son del C shell (primary and secondary prompts), de forma análoga a la norma shell de ‘$’ y ‘>’.

Compare the previous example to how it is done with a POSIX-compliant shell:

Compare el ejemplo anterior, con la forma en que se hace en un shell compatible con POSIX:

$ awk 'BEGIN {
>   print \
>       "hello, world"
> }'

awk es un lenguaje orientado a líneas. Donde cada acción de cada regla tiene que comenzar en la misma línea que el patrón. Para que el patrón y la acción puedan quedar en líneas separadas, se debe utilizar la barra invertida de continuación, no hay otra opción.

Otra cosa a tener en cuenta es que la barra invertida de continuación y los comentarios no se mezclan. Tan pronto como awk ve “#” se inicia un comentario, por lo tanto awk ignora todo lo que se encuentre en el resto de la línea. Por ejemplo:

$ gawk 'BEGIN { print "dont panic" # a friendly \
>                                    BEGIN rule
> }'
error--> gawk: cmd. line:2:                BEGIN rule
error--> gawk: cmd. line:2:                ^ parse error

En el caso anterior, parece que la barra invertida continuaría el comentario en la siguiente línea. Sin embargo, la combinación de barra invertida con salto de línea ni siquiera se se llega a notar por awk, ya que sen encuentra “escondida” dentro del comentario. Por lo tanto, BEGIN se muestra como un error de sintaxis.

Cuando las sentencias awk en una regla son cortas, es posible que se desee poner más de una de ellas en una línea. Esto se logra mediante la separación de sentencias con un punto y coma (‘;’). Esto también se aplica a las mismas reglas. Por lo tanto, el programa que anterior:

/12/  { print $0 }
/21/  { print $0 }

también se podría escribir de esta manera:

/12/ { print $0 } ; /21/ { print $0 }

NOTA: El requisito que establece que las reglas sobre la misma línea deben estar separadas por un punto y coma no estaba en el lenguaje awk original, más bien esto fue agregado por coherencia con el tratamiento de las sentencias dentro de una acción.

Cuándo utilizar awk

El lenguaje AWK es muy útil para la producción de informes desde grandes cantidades de datos en bruto.

Dado que los programas awk se interpretan, se puede evitar la parte de los ciclos lentos de compilación.

Si en un programa awk escribimos, digamos, más de cien líneas de código, es posible que se deba considerar el uso de un lenguaje de otro programación diferente.

Invocando awk

Hay dos formas de correr awk, ya sea con un programa explícito o con uno o más archivos de programa. Estas son las plantillas para ambos; elementos encerrados entre […] en estas plantillas son opcionales:

awk [opciones] -f 'programita' [--] archivo-de-datos ...
awk [opciones] [--] 'programita' archivo-de-datos ...

Además de las opciones tradicionales de una letra al estilo POSIX, gawk también es compatible con las opciones largas de GNU.

Es posible invocar awk con un programa vacío:

awk '' archivo-de-datos-1 archivo-de-datos-1

Opciones de línea de comandos

Las opciones comienzan con un guión y se componen por un solo carácter. Opciones largas al estilo GNU se componen de dos guiones y una palabra clave. La palabra clave puede ser abreviada, siempre y cuando la abreviatura permite la opción de ser identificada de forma única. Si la opción toma un argumento, entonces la palabra clave va inmediatamente seguida por un signo de igual (‘=’) y el valor del argumento, o la palabra clave y el valor del argumento se separan por espacios en blanco. Si una determinada opción con un valor viene dada más de una vez, entonces es el último valor el que cuenta.

Cada opción de gawk tiene tiene una opción corta y estilo POSIX correspondiente. Las opciones largas y cortas son intercambiables en todos los contextos. La siguiente lista describe las opciones requeridas por el estándar POSIX:

-F fs
--field-separator fs

Establece la variable FS a fs (FS = Separador de Campo).

-f source-file
--file source-file

Lee la fuente del programa awk desde un archivo. Esta opción puede ser usada múltiples veces; un programa awk puede consistir de la concatenación de los contenidos de cada archivo o script fuente que haya sido especificado.

-i source-file
--include source-file

Lee el código fuente de una librería. Esta opción equivale a usar la directiva ‘@ include‘ dentro de un programa. Esta opción es muy similar a la opción -f, pero existen dos diferencias importantes.

En primer lugar, si se usa la opción -i, no se carga el código fuente del programa si éste ya ha sido cargado previamente, mientras que la opción -f siempre cargará el archivo. En segundo lugar, porque esta opción está destinada para ser utilizada por código de librerías, gawk no reconoce tales archivos como la entrada principal del programa.

Por lo tanto, después de procesar una opción -i, gawk aún espera encontrar el código fuente principal a través de la opción -f o en la línea de comandos.

-v var=val
--assign var=val

Establece en la variable var el valor de val antes de que comience a correr el programa awk. Estos valores de variables pueden estar disponibles dentro de la regla BEGIN (ver otros argumentos).

La opción-v puede configurar sólo una variable, pero se puede usar múltiples veces, por ejemplo:

‘awk -v var1=val1 -v var2=val2 ...’

PRECAUCIÓN: El uso de la opción -v para establecer o configurar los valores de variables incorporadas (built-in) puede terminar en resultados sorprendentes. es probable que awk restablecerá los valores de esas variables en cualquier momento que lo necesite, haciendo caso omiso de cualquier valor predefinido que uno mismo pueda haber configurado previamente.

-N
--use-lc-numeric

Al analizar datos de entrada numéricos se usa el carácter de punto decimal que define la configuración regional (Locales).

-o[file]
--pretty-print[=file]

Habilita la impresión linda (pretty-printing) de los programas awk. De manera predeterminada, la salida de un programa queda en un archivo llamado awkprof.out

El argumento de archivo opcional permite especificar un nombre de archivo diferente para la salida. No se permite ningún espacio entre la opción -o y el archivo, si se suministra un archivo.

-O
--optimize

Activa unas optimizaciones en la representación interna del programa. Por el momento esto incluye sólo el simple “constant folding“.

-p[file]
--profile[=file]

Habilita el “Profiling” de programas awk. De forma predeterminada, los perfiles se crean en un archivo llamado awkprof.out. El argumento de archivo opcional permite especificar un nombre de archivo diferente para el archivo de perfil. No se permite ningún espacio entre la opción -p y el archivo, si se suministra archivo.

En el margen izquierdo, el perfil contiene recuentos de ejecución de cada sentencia del programa, y recuenta la llamada de funciones por cada función.

-P
--posix

Operar en modo estricto POSIX. Esto desactiva todas las extensiones gawk (tales como el doble guión) y desactiva todas las extensiones no permitidas por POSIX.

Además, se aplican las siguientes restricciones adicionales:

  • Los fines de línea no actúan como espacios en blanco para separar los campos cuando FS es igual a un solo espacio.
  • Los fines de línea no se permiten después de “?” o “:
  • Si se especifica la opción -Ft en la línea de comando, ésto no establece el valor de FS a ser un solo carácter de tabulación.
  • Utiliza el carácter de punto decimal de la localización (Locale) para analizar los datos de entrada.

Si se proporcionan tanto –tradicional y –posix en la línea de comandos, –posix tiene prioridad. Además gawk emite un aviso si se suministran las dos opciones.

-r
--re-interval

Permite expresiones de intervalo (Operadores Regexp) en las expresiones regulares. Ahora éste es el comportamiento predeterminado de gawk. Sin embargo, esta opción se mantiene tanto por compatibilidad hacia atrás, y para su uso en combinación con la opción –tradicional.

-S
--sandbox

Desactiva la función system(), redirecciones de entrada con getline, redirecciones de salida con print y printf, y extensiones dinámicas. Esto es útil cuando se quiere correr scripts awk de fuentes cuestionables, para asegurar de que los scripts no pueden acceder a nuestro sistema (que no sea el archivo de datos de entrada especificado).

-t
--lint-old

Avisar sobre “constructs” que no están disponibles en la versión original de awk, desde la versión 7 de Unix (ver V7/SVR3.1).

-V
--version

Imprime información sobre la versión particular de gawk. Esto permite determinar si la copia de gawk se encuentra al día con respecto a la que distribuye la Free Software Foundation.

También es muy útil para cooperar con reportes, cuando se presentan errores (Bugs).

Siempre y cuando se haya suministrado el texto del programa, cualquier otra opción se marca como no válida, con un mensaje de advertencia, de lo contrario se pasan por alto.

En el modo de compatibilidad, como un caso especial, si el valor de fs suministrado desde la opción -F es “t“, entonces FS se establece en el carácter de tabulación “\ t“. Esto es cierto sólo para –tradicional y no para –posix.

Si la opción -f se usa más de una vez en la línea de comandos, awk lee su fuente de programas desde todos los archivos especificados, como si hubieran sido concatenados en un sólo archivo grande. Esto es útil para la creación de bibliotecas con funciones awk. Estas funciones pueden escribirse una sola vez y luego y ser recuperadas desde un ínico lugar estándar, en lugar de tener que ser incluido de manera duplicada en cada programa individual (los nombres de funciones deben ser únicos.)

Con el awk estándar, se pueden seguir utilizando funciones de biblioteca, incluso si se introduce el programa desde el terminal, al “-f /dev/tty“. Después de escribir el programa, para salir pulse Ctrl-d (el carácter de fin de archivo). (También puede usar “-f –” para leer el código fuente del programa desde la entrada estándar, pero luego no se puede utilizar la entrada estándar como fuente de entrada de datos.)

Debido a que es torpe mezclar los mecanismos awk estándar para mezclar programas awk desde archivos y desde la línea de comandos, gawk proporciona la opción –source. Esto no requiere de concatenar (pre-empt) la entrada estándar para el código fuente, sino que permite mezclar de manera fácil la línea de comandos y el código fuente de biblioteca (ver Variable AWKPATH). La opción –source también se puede usar múltiples veces desde la línea de comandos.

Si no se especifica la opción -f o la opción –source, entonces gawk utiliza el primer argumento no-opción desde la línea de comandos como texto del código fuente del programa.

Si la variable de entorno o ambiente POSIXLY_CORRECT existe, entonces gawk se comporta en modo estricto POSIX, exactamente como si se hubiera suministrado la opción –posix desde línea de comandos.

Muchos de los programas GNU buscan esta variable de entorno para suprimir las extensiones que entren en conflicto con POSIX, pero gawk se comporta de manera diferente: suprime todas las extensiones, incluso aquellas que no entran en conflicto con POSIX, y se comporta en modo estricto POSIX.

Si se suministra la opción –lint desde la línea de comandos y gawk activa el modo POSIX porque se configura POSIXLY_CORRECT, entonces se emite un mensaje de advertencia indicando que el modo POSIX está en vigor. Esta variable se puede establecer en el archivo de inicio del Shell.

Para ser compatible con Bourne Shell (como Bash), se deben agregar estas líneas al archivo .profile en nuestro propio directorio principal (home):

POSIXLY_CORRECT=true
export POSIXLY_CORRECT

Para tener compatibilidad con un C shell, se debe agregar esta línea en el archivo de inicio de sesión .login en nuestro propio directorio principal (home):

setenv POSIXLY_CORRECT true

NOTA: No se recomienda tener configurado POSIXLY_CORRECT en el uso diario, pero es bueno para probar la portabilidad de los programas en otros entornos.

Otros argumentos desde la línea de comandos

Los argumentos adicionales desde la línea de comandos se tratan normalmente como archivos de entrada que deben ser procesados en el orden especificado. Sin embargo, si un argumento tiene la forma var=value, se asigna el valor value a la variable var. No se especifica un archivo en lo absoluto.

Todos estos argumentos son disponibles para un programa AWK desde el arreglo ARGV (ver Variables Buit-in o integradas). Las opciones de línea de comandos y el texto del programa (si está presente) se omiten desde ARGV. Todos los demás argumentos, incluyendo las asignaciones de variables, sí se incluyen. A medida que se procesa cada elemento del arreglo ARGV, gawk establece la variable ARGIND al índice en ARGV del elemento actual.

La distinción entre los argumentos de nombre de archivo y argumentos de asignación de variables se realiza cuando awk está a punto de abrir el siguiente archivo de entrada. En éste momento de la ejecución, comprueba el nombre awk verfica el nombfre de archivo para ver si realmente es una asignación de variable, si es así, awk establece la variable en lugar de leer un archivo.

Por lo tanto, las variables reciben los valores dados después de que todos los archivos especificados previamente hayan sido leídos. En particular, los valores de las variables asignadas de esta manera no se encuentran disponibles dentro de una regla BEGIN (ver BEGIN/END), porque tales reglas se ejecutan antes de que awk comienza a escanear la lista de argumentos.

Los valores de las variables que aparecen en la línea de comandos se procesan por “escape sequences“.

En algunas implementaciones anteriores de awk, cuando una asignación de variables se producía antes que los nombres de archivo, la asignación iba a suceder antes de que la regla BEGIN sea ejecutada. El comportamiento de awk fue tan incompatible; algunas asignaciones desde la línea de comandos estaban disponibles dentro de la regla BEGIN, mientras que otras no lo eran. Desgraciadamente, muchas aplicaciones llegaron a depender de esta “característica”. Cuando awk fue cambiado para ser más consistente, se agrego la opción -v para dar cabida a las aplicaciones que dependan de este viejo comportamiento.

La función de asignación de variables es muy útil para asignar a variables tales como RS, OFS, y ORS, que controla los formatos de entrada y salida antes de escanear los archivos de datos. También es útil para controlar el estado si se requieren múltiples pasadas sobre un archivo de datos. Por ejemplo:

awk 'pass == 1  { pass 1 stuff }
     pass == 2  { pass 2 stuff }' pass=1 mydata pass=2 mydata

Dada la función de asignación de variables, la opción -F para ajustar el valor de FS no es estrictamente necesario. Se mantiene por compatibilidad histórica.

Nombramiento de entrada estándar

A menudo, es posible que se desea leer la entrada estándar, junto con otros archivos. Por ejemplo, es posible que se necesita leer un archivo, leer la entrada estándar procedente de un “pipe“, y luego leer otro archivo.

La forma de nombrar la entrada estándar, con todas las versiones de awk, es el uso de un sólo guión, ‘-‘. Por ejemplo:

un_comando | awk -f programita.awk archivo-1 - archivo-2

Aquí, awk primero lee archivo-1, seguidamente lee la salida de un_comando, y finalmente lee archivo-2.

También se puede utilizar “” para nombrar la entrada estándar al leer archivos con getline (ver Getline/File).

Además, gawk permite especificar el nombre de archivo especial /dev/stdin, tanto en la línea de comandos como con getline. Otras versiones de awk también soportan esto, pero no es estándar. (Algunos sistemas operativos ofrecen el archivo /dev/stdin en su sistema de archivos, sin embargo, gawk siempre procesa este nombre de archivo él mismo.)

La variable de entorno AWKPATH

En la mayoría de las implementaciones de awk, se debe proporcionar un nombre de ruta precisa para cada archivo de programa, a menos que el archivo se encuentre en el directorio actual. Pero en gawk, si el nombre de archivo suministrado con la opción -f o con la opción -i no contiene un “/“, entonces gawk busca en una lista de directorios (conocida como la ruta de búsqueda), uno por uno, en busca de un archivo con el nombre especificado.

La ruta de búsqueda es una cadena conformada por nombres de directorios separados por dos puntos. gawk obtiene su ruta de búsqueda desde la variable de entorno AWKPATH. Si la variable no existe, gawk utiliza una ruta por defecto “.:/usr/local/share/awk

La función de ruta de búsqueda es esencial en la construcción de bibliotecas útiles con funciones awk. Los archivos de biblioteca se pueden colocar en un directorio estándar en la ruta predeterminada para que se puedan especificar desde la línea de comando mediante un nombre de archivo corto. De lo contrario, el nombre completo de archivo tendría que ser escrito para cada archivo.

Mediante el uso de la opción -i, o de la opción –source y la opción -f, los programas awk desde la línea de comandos pueden utilizar las características de archivos de biblioteca awk. La ruta de búsqueda no se lleva a cabo si gawk está en modo de compatibilidad. Esto es cierto para ambos –tradicional y –posix.

Si el código fuente no se encuentra después de la búsqueda inicial, de nuevo se busca el camino después de el sufijo por defecto “.awk” al nombre de archivo.

NOTA: Para incluir el directorio actual en la ruta, ya sea colocando explícitamente la ruta o escribiendo una entrada nula en la ruta. (Una entrada nula se indica empeando y finalizando la ruta con dos puntos, o colocando dos signos de dos puntos seguidos “::“.) Este mecanismo de búsqueda de ruta es similar a la del Shell.
Sin embargo, gawk siempre busca en el directorio actual antes de buscar en AWKPATH, por lo que no hay ninguna razón real para incluir el directorio actual en la ruta de búsqueda.

Si AWKPATH no se define en el entorno, gawk pone su ruta de búsqueda predeterminada en ENVIRON[“AWKPATH”]. Esto hace que sea fácil determinar la ruta de búsqueda real que gawk utilizará dentro de un programa awk.

Aunque es posible cambiar ENVIRON[“AWKPATH”] dentro de un programa awk, esto no tiene ningún efecto en el comportamiento del programa en ejecución. Lo que sí tiene sentido es que la variable de entorno AWKPATH se utiliza para encontrar los archivos de código fuente del programa. Una vez que el programa se está ejecutando, todos los archivos ya han sido encontrados, por lo que gawk ya no necesita utilizar AWKPATH.

La variable de entorno AWKLIBPATH

La variable de entorno AWKLIBPATH es similar a la variable AWKPATH, pera esta se usa para buscar bibliotecas compartidas que hayan sido especificadas con la opción -l en lugar de los archivos de origen. Si no se encuentra la biblioteca, entonces se busca de nuevo la ruta después de agregar el sufijo de biblioteca compartida respectivo de la plataforma. Por ejemplo, en los sistemas GNU/Linux se utiliza el sufijo de plataforma.so“. La ruta de búsqueda especificada también se utiliza para las bibliotecas cargadas mediante la palabra clave “@ load

Otras variables de entorno

Es posible afectar el comportamiento de gawk con el uso de otras variables de entorno, pero son más especializadas. Los que se mencionan en la siguiente lista están destinados a ser utilizados por usuarios comunes.

POSIXLY_CORRECT

Le dice a gawk que cambie a modo de compatibilidad POSIX, desactivando todas las extensiones tradicionales y GNU.

GAWK_SOCK_RETRIES

Controla la cantidad de tiempo que gawk intentará una conexión TCP/IP bidireccional (socket) antes de abandonar. Ver redes TCP/IP.

GAWK_MSEC_SLEEP

Especifica el intervalo entre reintentos de conexión, en milisegundos. En los sistemas que no soporten la llamada de sistema usleep(), el valor se redondea a un número entero de segundos.

GAWK_READ_TIMEOUT

Especifica el tiempo, en milisegundos, para que gawk que espere por la entrada antes de regresar con un error.

“Testing and Tuning”

Las variables de entorno siguientes son apropiados para los desarrolladores de gawk, para realizar pruebas y afinar. Se encuentran sujetas a cambios. Las variables son:

AVG_CHAIN_MAX

El número promedio de items que gawk mantendrá en una cadena hash en la gestión de arreglos o matrices.

AWK_HASH

Si esta variable existe con un valor de “gst”, gawk entonces usará la función hash de GNU Smalltalk para la gestión de arreglos o matrices. Esta función puede ser marginalmente más rápida que la función estándar.

AWKREADFUNC

Si la variable existe, gawk entonces leerá los archivos de código fuente una línea a la vez, en lugar de leerlos en bloques. Esto existe para depurar problemas en sistemas de archivos en sistemas operativos que no son POSIX donde I/O se lleva a cabo en los registros, no en bloques.

GAWK_NO_DFA

Si la variable existe, gawk no utiliza el “DFA regexp matcher” para el tipo de pruebas “does it match”. Esto puede causar que gawk sea más lento. Su propósito es ayudar a aislar las diferencias entre los dos comparadores de expresiones regulares que gawk utiliza internamente. (Se supone que no hay diferencias, pero en ocasiones la teoría y la práctica no se coordinan entre sí.)

GAWK_STACKSIZE

Esto especifica la cantidad en que gawk debe crecer su pila (stack) de evaluación interna, cuando sea necesario.

TIDYMEM

Si la variable existe, gawk usa las llamadas de librería mtrace() desde GNU LIBC para ayudar a localizar posibles pérdidas de memoria.

Estado de salida de gawk (Exit Status)

Si la instrucción de salida se utiliza con un valor, entonces gawk termina devolviendo ese valor numérico.

De lo contrario, si no hay problemas durante la ejecución, gawk termina con el valor de la constante C, EXIT_SUCCESS. Por lo general el valor es cero = 0.

Si se produce un error, gawk termina con el valor de la constante C, EXIT_FAILURE. Por lo general el valor es uno = 1.

Si gawk termina por causa de un error grave, el estado de salida es 2. En los sistemas no POSIX, este valor puede ser asignado a EXIT_FAILURE.

Incluyendo otros archivos (@include)

Esta sección describe una característica que es específica de gawk.

La palabra clave “@include” se utiliza para leer archivos awk de origen externos. Esto permite dividir grandes archivos de origen awk en partes manejables y más pequeñas. También permite reutilizar el código awk desde varios scripts awk.

En otras palabras, se puede agrupar funciones awk, en archivos externos, con funciones esenciales para llevar a cabo ciertas tareas específicas.

Estos archivos pueden ser utilizados como bibliotecas de funciones, usando la palabra clave “@include” en combinación con la variable de entorno AWKPATH.

Hay que tener en cuenta que los archivos de origen también pueden incluidos con el uso de la opción -i.

Veamos un ejemplo. Vamos a empezar con dos scripts awk (trivial), es decir, con el script llamado test1 y con el script llamado test2. A continuación, el script test1 contiene:

BEGIN {
       print "This is script test1."
}

y el script test2 contiene:

@include "test1"

BEGIN {
       print "This is script test2."
}

Correr gawk con el script test2 produce produce el siguiente resultado:

gawk -f test2
This is script test1.
This is script test2.

gawk corre el script test2 que a su vez incluye test1 utilizando la palabra clave “@include“. Por lo tanto, para incluir archivos awk de origen externo, se tiene que utilizar “@include” seguido por el nombre del archivo que se quiere incluir, el nombre debe ir entre comillas dobles.

NOTA: Hay que recordar que esto es un “language construct” por lo que el nombre del archivo no puede ser una cadena variable, pero sí una sola cadena literal entre comillas dobles.

Los archivos que se vayan a incluir pueden estar anidados, por ejemplo, si incluimos un tercer archivo llamado script test3 con el siguiente contenido:

@include "test2"

BEGIN {
       print "This is script test3."
}

Correr gawk con el script test3 produce el siguiente resultado:

gawk -f test3
This is file test1.
This is file test2.
This is file test3.

Por supuesto que el nombre de archivo puede ser una ruta. Por ejemplo:

@include "../io_funcs"

también se puede usar algo como:

@include "/usr/awklib/network"

ambos usos son válidos. La variable de entorno AWKPATH puede ser muy útil cuando se utiliza “@include“. Además las mismas reglas que aplican para el uso de la variable AWKPATH en búsquedas de archivos desde la línea de comandos también se aplican a “@include“.

Es muy útil para la construcción de bibliotecas con funciones gawk. Si se tiene un gran script con varias funciones awk útiles y generales, entonces se puede dividir en archivos de bibliotecas, además podemos colocar los archivos en un directorio especial.

Entonces se puede incluir esas nuevas “bibliotecas”, ya sea utilizando la ruta completa de los archivos, o configurando la variable de entorno AWKPATH para luego ser usada con “@include” con sólo la parte del archivo de la ruta completa. Por supuesto, se puede tener más de un directorio especial para conservar los archivos de biblioteca, mientras más complejo sea el entorno de trabajo, más directorios van a ser necesarios de organizar para los archivos que vayan a necesitar ser incluidos.

Gracias a que se puede utilizar mútiples veces la opción -f , el mecanismo “@include” no es estrictamente necesario. Sin embargo, la palabra clave “@include” puede ayudar en la construcción de programas gawk autónomos, lo que reduce la necesidad de escribir líneas de comandos complejos y tediosos. En lo particular, “@include” es muy útil cuando se escriben scripts CGI que se corren desde páginas web.

Como se mencionó, para la Variable AWKPATH, siempre se busca primero en el directorio actual por los archivos de origen, antes de buscar en AWKPATH, y esto también aplica para los archivos nombrados con “@include“.

Cargando bibliotecas compartidas (@load)

Esta sección describe una característica que es específica de gawk.

La palabra clave “@load” se puede utilizar para leer bibliotecas compartidas awk externas. Esto permite enlazar código compilado que ofrece un mayor rendimiento y/o dar acceso a características extendidas que no son soportadas por el lenguaje awk.

La variable AWKLIBPATH se utiliza para buscar por bibliotecas compartidas. Usar “@load” equivale a utilizar la opción -l desde la línea de comandos.

Si inicialmente la biblioteca compartida no se encuentra en AWKLIBPATH, otra búsqueda se lleva a cabo, agregando el sufijo de plataforma por defecto de biblioteca compartida para el nombre de archivo. Por ejemplo, en los sistemas GNU/Linux se utiliza el sufijo de plataforma “.so“.

gawk '@load "ordchr"; BEGIN {print chr(65)}'

Esto es equivalente a:

gawk -lordchr 'BEGIN {print chr(65)}'

Para el uso desde la línea de comandos, es más conveniente la opción -l, pero “@load” es útil para incorporar dentro de un archivo de origen awk que requiere el acceso a una biblioteca compartida.

Las Extensiones Dinámicas, describen cómo escribir extensiones (en C o C++) se pueden cargar con cualquiera “@load” o la opción -l.

Funciones y opciones obsoletas

En esta sección se describen las características y opciones desde la línea de comandos, de versiones anteriores de gawk que, o bien no están disponibles en la versión actual o que todavía están soportadas, pero en desuso (lo que significa que no estarán disponibles en la próxima versión).

Los archivos relacionados con procesos especiales /dev/pid, /dev/ppid, /dev/pgrpid y /dev/user fueron desaprobados en gawk 3.1, pero todavía funcionan. Desde la versión 4.0, ya no son interpretados por gawk. (Mejor utilizar PROCINFO.)

Opciones y características sin documentación

Use the Source, Luke!

--Obi-Wan.

Esta sección ha quedado en blanco de manera intencional.

Expresiones regulares

Una expresión regular (RegExp) es una manera de describir un conjunto de cadenas. Dado que las expresiones regulares son una parte fundamental de la programación en awk, su formato y uso merecen un capítulo aparte.

Una expresión regular encerrada entre barras (‘/’) es un patrón de awk que puede coincidir con cada registro de entrada cuyo texto pertenece a ese conjunto. La expresión regular más simple es una secuencia de letras, números o ambos. Como esta expresión regular puede coincidir con cualquier cadena que contenga esa secuencia. Por ejemplo, la expresión regular “foo” coincide con cualquier cadena que contiene “foo”. Por lo tanto, el patrón /foo/ coincide con cualquier registro de entrada que contiene los tres carácteres “foo” en cualquier parte del registro. Otros tipos de expresiones regulares también permiten especificar clases de cadenas más complicadas.

Inicialmente, los ejemplos que vienen a continuación son simples. De acuerdo a como se explica más acerca de cómo funcionan las expresiones regulares, se van a ir presentando casos más complicados.

Cómo utilizar expresiones regulares

Una expresión regular se puede utilizar como un patrón dentro de barras “/“. Entonces la expresión regular se compara con el texto completo de cada registro. (Normalmente, sólo tiene que coincidir con una parte del texto con el fin de tener éxito.)

Por ejemplo, a continuación se imprime el segundo campo de cada registro que contiene la cadena “foo” en cualquier parte de ella:

awk '/foo/ { print $2 }' BBS-list

Las expresiones regulares también se pueden utilizar en la coincidencia de expresiones. Estas expresiones permiten especificar la cadena en contra a coincidir, no tiene que ser todo el registro de entrada actual.

Los dos operadores “~” y “!~” realizan comparaciones de expresiones regulares. Expresiones que utilizan estos operadores pueden ser utilizados como patrones, o en “if“, “while“, “for“, y sentencias “do“. Por ejemplo:

exp ~ /regexp/

es cierto si la expresión exp (tomada como una cadena) coincide con regexp.

En el siguiente ejemplo coincide, o selecciona, todos los registros de entrada con la letra mayúscula “J” en algún lugar en el primer campo:

awk '$1 ~ /J/' inventory-shipped

Lo mismo hace lo siguiente:

awk '{ if ($1 ~ /J/) print }' inventory-shipped

El siguiente ejemplo es verdadero si la expresión exp (tomada como una cadena de caracteres) no coincide con regexp:

exp !~ /regexp/

En el siguiente ejemplo coincide, o selecciona, todos los registros de entrada cuyo primer campo no contiene la letra mayúscula “J”:

awk '$1 !~ /J/' inventory-shipped

Cuando una expresión regular está encerrada entre barras, como /foo/, esto lo podemos llamar una expresión regular constante, al igual que 5,27 es una constante numérica y “foo” es una constante de cadena.

Secuencias de escape

Un uso de una secuencia de escape es incluir un carácter de comillas dobles dentro de una cadena constante. Debido a que una comilla doble terrmina una cadena, se debe usar \” para representar un carácter de comillas dobles real como parte de la cadena, por ejemplo:

awk 'BEGIN { print "He said \"hi!\" to her." }'

El propio carácter de barra invertida es otro carácter que no se puede incluir de manera normal, se debe escribir “\\” para colocar un barra invertida en la cadena o expresión regular. por lo tanto, la cadena cuyo contenido son los dos caracteres ” y \ se debe escribir \”\\.

Otras secuencias de escape representan caracteres que se imprimen, como TAB o nueva línea. Aunque nada impide introducir carácteres que no se imprimen directamente en una constante de cadena o en una expresión regular constante, es posible que no se vean muy bien.

La siguiente tabla muestra todas las secuencias de escape utilizadas en awk y lo que representan. A menos que se indique lo contrario, todas estas secuencias de escape se aplican tanto a las constantes de cadena y a las constantes de expresiones regulares:

\\

Literalmente una barra invertida (backslash) “\”.

\a

El carácter de “alerta”, Ctrl-g, el código ASCII 7 (BEL).
(Por lo general, produce una especie de ruido audible.)

\b

Retroceso (backspace), Ctrl-h, el código ASCII 8 (BS).

\f

Formfeed, Ctrl-l, el código ASCII 12 (FF).

\n

Nueva línea (newline), Ctrl-j, el código ASCII 10 (LF).

\r

Retorno de carro (carriage return), Ctrl-m, el código ASCII 13 (CR).

\t

TAB horizontal, Ctrl-i, el código ASCII 9 (HT).

\v

Tab vertical, Ctrl-k, el código ASCII 11 (VT).

\nnn

El valor octal nnn, donde nnn es sinónimo de 1 a 3 dígitos entre 0 y 7. Por ejemplo, el código para el carácter ASCII ESC (escape) es “\033”

\xhh...

El valor hexadecimal hh, donde hh representa una secuencia de dígitos hexadecimales (0-9, o bien A-F o a-f). Al igual que la misma construcción que sucede en ISO C, la secuencia de escape continúa hasta que se vea el primer dígito no-hexadecimal. Sin embargo, el uso de más de dos dígitos hexadecimales produce resultados no definidos. (La secuencia de escape “\x” no está permitida en POSIX awk.)

\/

Literalmente una barra diagonal (slash) (necesaria sólo para las constantes de expresiones regulares). Esta secuencia se utiliza cuando se quiere escribir una constante de expresión regular que contiene una barra (slash). Debido a que la expresión regular está delimitada por barras, es que se necesita escapar la barra que forme parte del patrón, con el fin de decirle a awk que procese el resto de la expresión regular.

\"

Literalmente una comilla doble (necesaria sólo para las constantes de cadena). Esta secuencia se utiliza cuando se quiere escribir una constante de cadena que contiene comillas dobles. Dado que la cadena está delimitada por comillas dobles, es que se debe escapar la comilla que forma parte de la cadena, con el fin de decirle a awk procese el resto de la cadena.

En gawk, una serie de secuencias de dos caracteres adicionales que comienzan con una barra invertida tiene un significado especial en expresiones regulares.

En una expresión regular, una barra invertida antes de cualquier carácter que no esté en la lista anterior y no aparece en expresiones regulares de Operadores GNU, significa que el siguiente carácter debe ser tomado de manera literal, aunque normalmente sea un operador de expresión regular. Por ejemplo, /a\+b/ coincide con los tres carácteres “a+b“.

Para mantener una portabilidad completa, no utilice una barra invertida antes de cualquier carácter que no aparezca en la lista anterior.

En resumen

Las secuencias de escape en la tabla anterior se procesan siempre de primero, tanto para cadenas constantes como para constantes de expresiones regulares. Esto ocurre muy temprano, tan pronto como awk lee un programa.

gawk procesa ambas, las constantes de expresiones regulares y las expresiones regulares dinámicas, para los operadores especiales listados en los Operadores RegExp GNU.

Una barra invertida antes de cualquier otro carácter significa que se va a tratar a ese carácter de manera literal.

Barra invertida antes carácteres normales

Si se coloca una barra invertida en una cadena constante antes de algo qu eno sea uno de los caráccteres mencionados arriba, awk POSIX awk deliberadamente permite lo que pase como indefinido. Hay dos opciones:

Quite las barras invertidas “Strip the backslash out”

Esto es lo que awk de Brian Kernighan y gawk hacen. Por ejemplo, “a\qc” es el mismo que “aqc“. (Debido a que este es un error muy fácil cometer, al menos gawk advierte al respecto.) Considere FS = “[ \t]+\|[ \t]+” para utilizar barras verticales rodeadas por espacios en blanco como separador de campo. Por esta razón deberían haber dos barras invertidas en la cadena: FS = “[ \t]+\\|[ \t]+”

Deja sola la barra invertida

Algunas otras implementaciones de awk hacen esto. En tales implementaciones, si se escribe “a\qc” es lo mismo que escribir “a\\qc“.

Secuencias de escape para Metacaracteres

Supongamos que se usa un escape octal o un escape hexadecimal para representar metacaracter en una expresión regular. ¿awk trata el carácter como un carácter literal o como un operador de expresión regular?

Históricamente, estos carácteres fueron tomadas literalmente. Sin embargo, el estándar POSIX indica que deben ser tratados como metacaracteres reales, que es lo que gawk hace.

En modo de compatibilidad, gawk trata a los carácteres representados por el escape octal y el escape hexadecimal, literalmente, cuando se utiliza en constantes de expresiones regulares. Por lo tanto, /a\52b/ es equivalente a /a\*b/.

Operadores de expresiones regulares

Se puede combinar expresiones regulares con carácteres especiales, llamados operadores de expresiones regulares o metacaracteres, esto para aumentar la potencia y la versatilidad de las expresiones regulares.

Las secuencias de escape descritas anteriormente, son válidas dentro de una expresión regular. Se introducen mediante un “\” y se reconocen y convierten en su correspondientes caracteres reales, esto como el primer paso en el procesamiento de expresiones regulares (RegExp).

A continuación una lista de los metacaracteres. Todos los caracteres que no son secuencias de escape y no están listados en la tabla por sí mismos:

\

Se utiliza para suprimir el significado especial de un carácter cuando hay coincidencia. Por ejemplo, “\$” coincide con el carácter “$“.

^

Se coincide con el inicio de una cadena. Por ejemplo, “^@chapter” coincide con “@chapter” al principio de una cadena y se puede utilizar para identificar capítulo iniciales en los archivos fuente del tipo Texinfo.

El “^” se conoce como un ancla, porque fija el patrón para que coincida sólo al inicio de la cadena.

Es importante recordar que “^” no coincida con el comienzo de una línea integrada en una cadena. La condición no es verdadera en el siguiente ejemplo:

if ("line1\nLINE 2" ~ /^L/) ...
$

Es similar a “^“, pero sólo coincide con al final de una cadena. Por ejemplo, “p$” coincide con un registro que termine en una “p“. El ancla “$” no coincide con el final de una línea incrustada en una cadena. La condición en el siguiente ejemplo no es verdadera:

if ("line1\nLINE 2" ~ /1$/) ...
. (period)

Coincide con cualquier carácter único, incluido el carácter de nueva línea. Por ejemplo “.P” coincide con cualquier carácter en la cadena seguido por una “P“. Utilizando concatenación, podemos hacer una expresión regular como “U.A“, que coincide con cualquier secuencia de tres caracteres que comienza con “U” y termina con una “A“.

En el modo estricto POSIX, “.” no coincide con el carácter NUL, el cual es un caracter con todos sus bits iguales a cero. Por lo contrario, NUL es otro caracter más. Otras versiones de awk pueden ser incapaces coincidir con el carácter NUL.

[…]

Se le conoce como un ua expressión entre corchetes. Coincide con cualquiera de los caracteres que se incluyen entre los corchetes cuadrados. Por ejemplo, “[MVX]” coincide con cualquiera de los caracteres “M“, “V” o “X” en una cadena.

[^ …]

Se le conoce como el complemento de una expresión de corchetes. El primer carácter después del “[” debe ser un “^“. Coincide con cualquier carácter excepto con los que sencuentran entre los corchetes cuadrados. Por ejemplo “[^awk]” coincide con cualquier carácter que no sea una “a“, “w“, o “k“.

|

Este es el operador de alternancia, se utiliza para especificar alternativas.

El operador “|” tiene la prioridad más baja entre todos los operadores de expresiones regulares. Por ejemplo “^P|[[:digit:]]” coincide con cualquier cadena que coincide ya sea “^P” o “[[:digit:]]“. Esto significa que coincide con cualquier cadena que comience con una “P” o que contiene un dígito.

La alternancia se aplica a las expresiones regulares más grandes posibles en cada lado.

(…)

En expresiones regulares los paréntesis se utilizan para agrupar, en aritmética también. Se pueden utilizar para concatenar expresiones regulares que contienen el operador de alternancia “|“. Por ejemplo, “@(samp|code)\{[^}]+\}” coincide tanto con “@code{foo}” como con “@samp{bar}“. (Estas son secuencias de control en formato Texinfo. El “+” se explica más adelante.)

*

Este símbolo significa que la expresión regular anterior debe repetirse tantas veces como sea necesario para encontrar una coincidencia. Por ejemplo, “ph*” aplica el símbolo “*” a la “h” anterior y busca la coincidencias de una “p” seguida por cualquier número de h. Además también coincide con una sóla “p” si no hay “h” presentes.

El “*” repite la más pequeña expresión posible anterior. (Se utilizan paréntesis para repetir toda una expresión mayor.) Se encuentran tantas repeticiones como sea posible. Por ejemplo, “awk ‘/\(c[ad][ad]*r x\)/ { print }’ sample” imprime cada registro del archivo “sample” que contiene una cadena de la forma “(car x)“, “(cdr x)“, “(cadr x)” y así sucesivamente. Observe el escape de los paréntesis, precedidos por barras invertidas (backslashes).

+

Este operador es similar a “*“, excepto que la expresión precedente debe coincidir al menos una vez. Esto significa que “wh+y” coincidiría con “why” y con “whhy” pero no con “wy“, mientras que “wh*y” si puede coincidir con las tres cadenas. La siguiente, es una manera más simple de escribir el último ejemplo “*“:

awk '/\(c[ad]+r x\)/ { print }' sample
?

Este operador es similar a “*“, excepto que la expresión anterior puede coincidir una vez o ninguna en absoluto. Por ejemplo, “fe?d” coincide con “fed” y “fd“, pero nada más.

{n}
{n,}
{n,m}

Uno o dos números dentro de llaves denotan una expresión de intervalo. Si hay un número entre las llaves, la expresión regular anterior se repite n veces. Si hay dos números separados por una coma, la expresión regular anterior se repite desde n hasta m veces. Si hay un número seguido de una coma, entonces la expresión regular anterior se repite al menos n veces:

wh{3}y

Coincide con “whhhy“, pero no con “why” o con “whhhhy”.

wh{3,5}y

Coincide sólo con “whhhy“, “whhhhy” o “whhhhhy“, nada más.

wh{2,}y

Coincide con “whhy” o “whhhy“, y así sucesivamente.

Las expresiones de intervalos no se encuentran disponibles de manera tradicional en awk. Esto se agregó como parte del estándar POSIX para que awk y egrep fueran coherentes entre sí.

En un principio, porque los programas viejos usaban “{” y “}” en las constantes de expresiones regulares, gawk no coincide con expresiones de intervalo en las expresiones regulares.

Sin embargo, a partir de la versión 4.0, gawk por defecto sí coincide con las expresiones de intervalo. Esto se debe a que la compatibilidad con POSIX se ha vuelto más importante para la mayoría de usuarios gawk que la compatibilidad con programas viejos.

Para los programas que utilizan “{” y “}” en las constantes de expresiones regulares, es una buena práctica siempre escaparlas con una barra invertida. Por eso las constantes de expresiones regulares son válidas y funcionan de la manera que se quiere, usando cualquier versión de awk.

Por último, cuando “{” y “}” aparecen en contantes de expresiones regulares de una manera que no puede ser interpretada como una expresión de intervalo (por ejemplo /q{a}/), entonces se representan a sí mismos.

En expresiones regulares, los operadores “*“, “+” y el “?“, así como las llaves “{” y “}“, tienen la prioridad más alta, seguido por la concatenación, y finalmente por “|“. Al igual que en la aritmética, los paréntesis pueden cambiar cómo se agrupan los operadores.

En POSIX awk y gawk, los operadores “*“, “+” y el “?” se representan a sí mismos cuando no hay nada en la expresión regular que les precede. Por ejemplo, /+/ coincide literalmente con el signo de más. Sin embargo, muchas otras versiones de awk tratan este uso como un error de sintaxis.

Si gawk está en modo de compatibilidad, las expresiones de intervalo no se encuentran disponibles en las expresiones regulares.

Linux – Arbol de directorios y tamaños de archivos

“tree” usando “ls”:

ls -R /etc | grep ":$" | sed -e 's/:$//' -e 's/[^-][^\/]*\//--/g' -e 's/^/   /' -e 's/-/|/'

Los archivos/directorios de mayor tamaño dentro de /var:

du -a /var | sort -nr | head -n20
for i in G M K; do du -ah /var | grep [0-9]$i | sort -k1 -nr; done | head -n20

Sólo los archivos de mayor tamaño dentro de /var:

find /var -type f -ls | sort -k7 -nr | awk '{print $7 " " $11}' | head -n20

Sólo los archivos de iguales o mayores a cierto tamaño dentro de /var:

find /var -type f -size +1024k -exec ls -lh {} \; | awk '{ print $5 ": " $9 }' | sort -k1 -hr | head -n20
find /var -type f -size +5M -exec ls -lh {} \; | awk '{ print $5 ": " $9 }' | sort -k1 -hr | head -n20

Encontrar los 25 archivos mayores a 1024kB que existen dentro de /var/log:

find /var/log -type f -size +1024k -exec ls -lS {} \+ | head -n25

Directorios iguales o mayores a 1GB:

du -h / | grep ^[0-9.]*G
find / -type d -size +1G

Direcotorios iguales o mayores a 10GB:

du -h / | grep ^[1-9][0-9][0-9.]*G | sort -rn

Direcotorios iguales omayores a 200GB:

du -h / | grep ^[2-9][0-9][0-9][0-9.]*G

Listar los 10 archivos de mayor tamaño (sin directorios), en el directorio actual, de manera recursiva:

find . -printf '%s %p\n' | sort -nr | head -n20

Para restringir el resultado al directorio actual:

find . -maxdepth 1 -printf '%s %p\n'|sort -nr| head -n20

Para listar los 20 archivos-directorio mayores en tamaño:

du -a . | sort -nr | head -n20

Encontrar los 25 directorios de mayor tamaño, de manera recursiva, en el directorio actual:

du -sm */ | sort -rn | head -n25

Encontrar los 25 directorios de mayor tamaño, de menera recursiva, dentro del directorio /var/log/:

du -sm /var/log/* | sort -k1rn | head -n25

El tamaño total de /var/log:

du -sm /var/log
du -sh /var/log

Por favor consulte:

Linux – Encontrando lo recién modificado

Ordenados en orden inverso al tiempo de actualización (es decir, los archivos recientes de primero):

find /etc -type f -printf '%TY-%Tm-%Td %TT %p\n' | sort -r | more
find /etc -type f -exec stat --format '%Y :%y %n' {} \; | sort -nr | cut -d: -f2- | head -n50

Uso de -print0 para soportar espacios y también “linefeeds” en los nombres de archivo:

find /etc -type f -print0 | xargs -0 stat --format '%Y :%y %n' | sort -nr | cut -d: -f2- | head -n50

Utilizando stat estando en el directorio actual:

stat --printf="%y %n\n" $(ls -tr $(find * -type f)) | sort -k1 -k2 -r | head -n50

Para buscar archivos dentro de /etc y todos sus sub-directorios, los archivos que hayan sido modificado en los últimos 45 minutos:

find /etc -type f -mmin -45

Para buscar archivos dentro de /etc y todos sus sub-directorios, los archivos que hayan sido modificado en los últimos 7 días:

find /etc -type f -mtime -7
for f in `find /etc -type f -mtime -7`; do ls -l $f; done

Por favor consulte:

Linux – Niveles de ejecución y Servicios

SysV Init Runlevels

El sistema de niveles de ejecución SysV init provee un proceso estándar para controlar cuáles programas init lanza o detiene cuando se inicializa un nivel de ejecución. SysV init fué escogido porque es más fácil de usar y más flexible que el proceso init estilo-BSD tradicional.

Los archivos de configuración para SysV init están en el directorio /etc/rc.d/

Dentro se encuentran los scripts:

  • rc
  • rc.local
  • rc.sysinit
  • rc.serial (opcional)

También se encuentran los siguientes directorios:

init.d/ rc0.d/ rc1.d/ rc2.d/ rc3.d/ rc4.d/ rc5.d/ rc6.d/

El directorio init.d/ contiene los scripts usados ​​por el comando /sbin/init utilizados para controlar los servicios. Cada uno de los directorios numerados representan los seis niveles de ejecución configurados por defecto bajo Red Hat Enterprise Linux.

Runlevels

La idea detrás de los niveles de ejecución SysV init gira alrededor del concepto de que diferentes sistemas se pueden utilizar de diferentes maneras.

Por ejemplo:

  • Un servidor corre de forma más eficiente sin el consumo de recursos del sistema absorbidos por “X Window System”.
  • En ocasiones un sysadmin puede necesitar operar el sistema en un nivel inferior, esto para realizar tareas de diagnóstico, como solucionar daños en el nivel de ejecución 1, en el disco .

Las características de un nivel de ejecución dado determinan qué servicios son detenidos o iniciados por init. Por ejemplo:

  • El nivel de ejecución 1 (single user mode) detiene cualquier servicio de red.
  • Mientras que el nivel 3 arranca estos servicios de red.

Al detener e iniciar diferentes servicios en diversos niveles dado, permite que con init se pueda cambiar de manera fácil el modo de la máquina, sin que el usuario deba arrancar o detener servicios de manera manual.

Por defecto, en Red Hat Enterprise Linux se encuentran definidos los siguientes niveles de ejecución:

0 — Halt

1 — Single-user text mode

2 — Not used (user-definable)

3 — Full multi-user text mode

4 — Not used (user-definable)

5 — Full multi-user graphical mode (with an X-based login screen)

6 — Reboot

En general, usuarios operan Red Hat Enterprise Linux en el nivel de ejecución 3 o en el nivel de ejecución 5. Ambos modos son multi-usuarios. Los usuarios a veces personalizan los niveles de ejecución 2 y 4 para satisfacer necesidades específicas, ya que no se utilizan.

Para conocer el nivel de ejecución por defecto del sistema, busque por la línea similar a la siguiente en la parte superior de

cat /etc/inittab

id: 5: initdefault:

El nivel de ejecución predeterminado en este ejemplo es 5, como lo indica el número después de los primeros dos puntos. Para cambiarlo, se puede modificar /etc/inittab como usuario root.

Advertencia

Hay que tener mucho cuidado cuando se modifica /etc/inittab. Errores muy simples pueden hacer que el sistema deje de arrancar. Si esto ocurre, hay que moverse, por ejemplo, para usar un disquete de arranque, seguidamente entrar en modo de usuario único o entrar en modo de rescate para iniciar el equipo y reparar el archivo.

Por favor consulte:

Imprimir nivel de ejecución actual

who -r

Archivo de configuración del nivel de ejecución

cat /etc/inittab
grep "^id:" /etc/inittab

Verficando el estado de un servicio

Con el parametro “–list” se pueden listar todos los servicios y su actual estado “start-up” en cada configuración de nivel de ejecución (run-level configuration).

chkconfig --list | egrep 'apache|http'

httpd      0:off  1:off  2:on   3:on   4:on   5:on   6:off

Iniciar un servicio en sus niveles de ejecución

chkconfig --level 35 httpd on
chkconfig --list | grep httpd

httpd      0:off 1:off 2:off 3:on 4:off 5:on 6:off

Verificar si un servicio se encuentra encendido

chkconfig rsync

rsync on
chkconfig --list | egrep 'network.*:on'

networking      0:on   1:off  2:off  3:off  4:off  5:off  6:off

Servicios encendidos

chkconfig --list | egrep '(3|5):on'
chkconfig --list | grep '0:on'
chkconfig --list | egrep '[1-6]:on'
chkconfig --list | grep ':on'

Servicios apagados

chkconfig --list | egrep '(3|5):off'
chkconfig --list | grep ':off'

Apagar un servicio en un cierto nivel de ejecución

chkconfig --level 2335 httpd off

Lista de programas escuchando y los puertos que usan

netstat -plnt

En Ubuntu es más simple

service --status-all | grep '?'
service --status-all | grep '+'
service --status-all | grep '-'

Por ejemplo, para verificar el estado de un servicio se puede usar:

service cron status
service networking status
service ssh status
service rsync status
service sudo status
service mysql status
service apache2 status
service monit status
service fail2ban status
service ufw status

¿Dónde está la configuración de los niveles de ejecución?

  • /etc/init es donde viven los archivos de configuración de upstart. Si bien no son scripts en si, en esencia ejecutan lo que sea necesario para reemplazar los scripts sysvinit.
    ls /etc/init
  • /etc/init.d es donde viven todos los scripts sysvinit tradicionales y los scripts compatibles con versiones anteriores de upstart. Los comandos compatibles con versiones anteriores, básicamente se ponen a funcionar usando: service SERVICIO start, Algunos sólo muestran un aviso para que se utilice el comando “service”.
    ls /etc/init.d
  • /etc/init/rc-sysinit.conf se controla la ejecución de los scripts agregados manualmente o con update-rc.d hacia niveles de ejecución tradicionales en /etc/rc*

    cat /etc/init/rc-sysinit.conf

    Instalar y quitar enlaces de scripts estilo System-V

    update-rc.d actualiza los enlaces de los scripts estilo System V/etc/rc{[0-9S]}.d/NN{Name}” cuyo objetivo es el script “/etc/init.d/name“. Estos enlaces son dirigidos por init cuando se cambian los niveles de ejecución, en general se utiliza para iniciar y detener servicios del sistema como demonios. El nivel de ejecución es uno de los niveles de ejecución soportados por init, a saber, {[0-9S]} y NN es el número de secuencia de dos dígitos que determina el lugar de la secuencia donde init ejecutará los scripts.

    man update-rc.d
  • /etc/default tiene archivos de configuración que le permiten controlar el comportamiento de los scripts sysvinit tradicionales y los nuevos scripts upstart.
    ls /etc/default
ls -ld /etc/init.d/rc*

-rwxr-xr-x 1 root root 8635 jul 26  2012 /etc/init.d/rc
-rwxr-xr-x 1 root root  801 jul 26  2012 /etc/init.d/rc.local
-rwxr-xr-x 1 root root  117 jul 26  2012 /etc/init.d/rcS
ls -d /etc/init.d/rc* | xargs file

/etc/init.d/rc:       POSIX shell script, ASCII text executable
/etc/init.d/rc.local: POSIX shell script, ASCII text executable
/etc/init.d/rcS:      POSIX shell script, ASCII text executable
ls -d /etc/rc*.d

/etc/rc0.d  /etc/rc1.d  /etc/rc2.d  /etc/rc3.d  /etc/rc4.d  /etc/rc5.d  /etc/rc6.d  /etc/rcS.d
ls -ld /etc/rc*.d

drwxr-xr-x 2 root root 4096 ago  4 11:51 /etc/rc0.d
drwxr-xr-x 2 root root 4096 ago  4 11:51 /etc/rc1.d
drwxr-xr-x 2 root root 4096 ago  4 11:51 /etc/rc2.d
drwxr-xr-x 2 root root 4096 ago  4 11:51 /etc/rc3.d
drwxr-xr-x 2 root root 4096 ago  4 11:51 /etc/rc4.d
drwxr-xr-x 2 root root 4096 ago  4 11:51 /etc/rc5.d
drwxr-xr-x 2 root root 4096 ago  4 11:51 /etc/rc6.d
drwxr-xr-x 2 root root 4096 may  8 19:07 /etc/rcS.d
find /etc/ -maxdepth 1 -name 'rc[0-5].d' | sort

/etc/rc0.d
/etc/rc1.d
/etc/rc2.d
/etc/rc3.d
/etc/rc4.d
/etc/rc5.d
find /etc/ -maxdepth 1 -name 'rc*' | sort

/etc/rc0.d
/etc/rc1.d
/etc/rc2.d
/etc/rc3.d
/etc/rc4.d
/etc/rc5.d
/etc/rc6.d
/etc/rc.local
/etc/rcS.d
find /etc/ -maxdepth 1 -name 'rc*' | sort | xargs file

/etc/rc0.d:    directory
/etc/rc1.d:    directory
/etc/rc2.d:    directory
/etc/rc3.d:    directory
/etc/rc4.d:    directory
/etc/rc5.d:    directory
/etc/rc6.d:    directory
/etc/rc.local: POSIX shell script, ASCII text executable
/etc/rcS.d:    directory

Por favor consulte:

Linux – Conversando con el aparato

uname -r

0.0.0-0-generic-pae

Versión del Kernel

uname -mrs

Linux 0.0.0-0-generic x86_64
cat /etc/redhat-release
cat /etc/*release

DISTRIB_ID=Josoroma
DISTRIB_RELEASE=00.00
DISTRIB_CODENAME=josoroma
DISTRIB_DESCRIPTION="Josoroma 00.00"
NAME="Ubuntu"
VERSION="00.00, Josoroma"
ID=josoroma
ID_LIKE=debian
PRETTY_NAME="Josoroma (00.00)"
VERSION_ID="00.00"
cat /etc/*version
josoroma/sid
cat /etc/*issue

Josoroma 00.00.0 \n \l
cat /proc/*version

Linux version 0.0.0-0-generic-pae (buildd@josoroma) (gcc version 0.0.0 (Josoroma/Linaro 0.0.0-1josoroma5) )

#77-Josoroma SMP Wed March 00 00:00:00 UTC 2013
lsb_release -a

Distributor ID: Josoroma
Description: Josoroma 00.00
Release: 00.00
Codename: name

Conociendo el hardware

Con lshw se pueden conocer detalles de la configuración de una máquina, por ejemplo:

  • Versión del firmware.
  • Configuración de la placa o tarjeta principal.
  • Versión y velocidad del CPU.
  • Configuración de la caché.
  • Velocidad del bus.

Compatible con

  • DMI (x86 y IA-64).
  • “OpenFirmware device tree” (PowerPC).
  • PCI / AGP.
  • CPUID (x86).
  • IDE / ATA / ATAPI.
  • PCMCIA (sólo probado en x86).
  • SCSI.
  • USB.
lshw -short | egrep -i 'system|processor|System Memory|Bios|display|multimedia|network|disk|volume'

system MacBookPro4,1 (System SKU#)
/0/0 processor Intel(R) Core(TM)2 Duo CPU T9500 @ 2.60GHz
/0/3 processor CPU
/0/6 memory 4GiB System Memory
/0/e memory 1MiB BIOS
/0/100/1/0 display G84M [GeForce 8600M GT]
/0/100/1b multimedia 82801H (ICH8 Family) HD Audio Controller
/0/100/1c.4/0 eth1 network BCM4321 802.11a/b/g/n
/0/100/1c.5/0 eth0 network 88E8058 PCI-E Gigabit Ethernet Controller
/0/2/0.0.0 /dev/cdrom disk DVDRW GSA-S10N
/0/5/0.0.0 /dev/sda disk 200GB Hitachi HTS72202
/0/5/0.0.0/1 volume 2047KiB EFI GPT partition
/0/5/0.0.0/2 /dev/sda2 volume 244MiB Linux filesystem partition
/0/5/0.0.0/3 /dev/sda3 volume 186GiB Non-FS data partition
Por favor consulte:
lshw -class display
lshw -class multimedia
lshw -class network

Información del CPU

cat /proc/cpuinfo | egrep -i 'procesor|vendor|cpu family|model|cpu cores' | sort -u

cpu cores : 2
cpu family : 6
model : 23
model name : Intel(R) Core(TM)2 Duo CPU T9500 @ 2.60GHz
vendor_id : GenuineIntel

CPUs

cat /proc/cpuinfo | egrep -i 'proc|vendor|name'

processor : 0
vendor_id : GenuineIntel
model name : Intel(R) Core(TM)2 Duo CPU T9500 @ 2.60GHz
processor : 1
vendor_id : GenuineIntel
model name : Intel(R) Core(TM)2 Duo CPU T9500 @ 2.60GHz

Con el comando lscpu podemos obtener información detallada como:

  • Cantidad de CPUs.
  • Threads (hilos).
  • Cores (núcleos).
  • Sockets (conexiones).
  • Nodos NUMA.
  • Caches de CPU.
  • Familia de CPU.
  • Modelo.
  • bogoMIPS.
  • Orden de bytes y el paso a paso de sysfs y /proc/cpuinfo.

También es compatible con CPUs fuera de línea. Se puede imprimiren un formato “parseable”, incluyendo cómo diferentes memorias de caché son compartidas por CPUs diferentes y también lo qué puede ser alimento para otros programas.

lscpu | egrep -i 'Arch|CPU|Vendor|Model'

Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
CPU(s): 2
On-line CPU(s) list: 0,1
Vendor ID: GenuineIntel
CPU family: 6
Model: 23
CPU MHz: 800.000
NUMA node0 CPU(s): 0,1

La memoria libre y en uso del sistema

cat /proc/meminfo | egrep -i 'Mem(T|F)' | awk '{ printf ( "%.0fMB \n", ($2/1024) ); }';

3935MB
714MB
free -m | grep -i 'mem' | awk '{print $2 "MB " $3 "MB " $4 "MB" }'

3935MB 3221MB 714MB

Slot de la memoria de video

lspci | grep -i 'VGA' | awk '{print $1}'

01:00.0

Cantidad de memoria de video

lspci | grep -i 'VGA' | awk '{print $1}' | xargs lspci -vs | egrep ' prefetchable\) \[size=[0-9]+M' | perl -pe 's/.*size=([0-9]+)M.*/$1/g'

256

Descripcion de la tarjeta de video

lspci -v | grep -i -A12 --color 'VGA'

01:00.0 VGA compatible controller: NVIDIA Corporation G84M [GeForce 8600M GT] (rev a1) (prog-if 00 [VGA controller])
Subsystem: Apple Inc. Device 00a3
Physical Slot: 1
Flags: bus master, fast devsel, latency 0, IRQ 16
Memory at d2000000 (32-bit, non-prefetchable) [size=16M]
Memory at c0000000 (64-bit, prefetchable) [size=256M]
Memory at d0000000 (64-bit, non-prefetchable) [size=32M]
I/O ports at 7000 [size=128]
[virtual] Expansion ROM at d3000000 [disabled] [size=128K]
Capabilities:
Kernel driver in use: nvidia
grep -i --color 'memory' /var/log/Xorg.0.log

[ 27.073] (--) NVIDIA(0): Memory: 524288 kBytes
[ 28.105] (II) NVIDIA: Using 768.00 MB of virtual memory for indirect memory access.
[ 28.482] (==) NVIDIA(0): Disabling shared memory pixmaps

Buses PCI

lspci es útil para conocer información sobre los buses PCI en el sistema y los dispositivos que se encuentran conectados a ellos.

Por defecto, se muestra una lista breve de dispositivos. Para informar sobre errores en los controladores de dispositivos PCI o sobre lspci en sí, se recomienda incluir la salida de “lspci-vvx” o mejor aún de “lspci-vvxxx” (sin embargo, ver a continuación las posibles salvedades).

Algunas partes de la salida anterior, especialmente en los modos altamente detallados, probablemente son interesantes sólo para hackers apasionados.

Para conocer las definiciones exactas de los campos, se puede consultar cualquiera de las especificaciones de PCI o el header.h, y también /usr/include/linux/pci.h

Buses USB

lsusb es útil para conocer información sobre los buses USB en el sistema y los dispositivos que se encuentran conectados a ellos.

Con la opción “-v, –verbose“:

Se le dice a lsusb que sea más explícito y que presente información más detallada sobre los dispositivos que se muestran. Esto incluye descriptores de configuración sobre la velocidad actual del dispositivo. Los descriptores de clase se muestran, cuando esté disponible, para las clases de dispositivos USB incluyendo:

  • hub.
  • audio.
  • HID.
  • comunicaciones.
  • tarjetas chip.

Dispositivos SCSI (o hosts) y sus atributos

Utiliza la información de sysfs (desde el Linux kernel serie 2.6 y posteriores) para listar los dispositivos scsi (o hosts) que se encuentren conectados al sistema. Las opciones se pueden usar ​​para controlar la cantidad y el tipo de información de cada dispositivo.

Por defecto, los nombres de los nodos de los dispositivos (por ejemplo, “/dev/sda” o “/dev/root_disk“) se obtienen mediante la anotación de los números mayores y menores para el dispositivo obtenido desde sysfs (por ejemplo, el contenido de “/sys/block/sda/dev“) seguidamente busca una coincidencia en el directorio “/dev“. Esta coincidencia “match by major and minor” permite que los dispositivos con un nombre diferente por causa de udev (por ejemplo) sean informados correctamente en esta utilidad.

En algunas situaciones es muy útil ver el nombre de nodo de dispositivo que Linux produce de forma predeterminada, por esto se ofrece la opción –kname. Un ejemplo donde esta opción puede ser útil es cuando el registro de errores del kernel se reportan los mensajes de error de disco utilizando el nombre del kernel por defecto.

lsscsi --kname

[0:0:0:0]    cd/dvd  HL-DT-ST DVDRW  GSA-S10N  AP12  /dev/sr0 
[2:0:0:0]    disk    ATA      Hitachi HTS72202 DC4A  /dev/sd

Dispositivos de bloques del sistema

lsblk muestra información sobre algunos o todos los dispositivos de bloque especificados. El comando lee el sistema de ficheros sysfs para recopilar información.

Por defecto, lsblk imprime todos los bloques dispositivos de bloque (excepto los discos RAM) con un formato de árbol. Por favor utilice lsblk –help para conocer la lista con todas las columnas disponibles.

lsblk -m

NAME SIZE OWNER GROUP MODE
sr0 1024M root cdrom brw-rw----
sda 149,1G root disk brw-rw----
├─sda1 243M root disk brw-rw----
├─sda2 1K root disk brw-rw----
└─sda5 148,8G root disk brw-rw----
├─scorpion-root (dm-0) 146,8G root disk brw-rw----
└─scorpion-swap_1 (dm-1) 2G root disk brw-rw----
lsblk -f

NAME FSTYPE LABEL MOUNTPOINT
sr0
sda
├─sda1 ext2 /boot
├─sda2
└─sda5 LVM2_member
├─scorpion-root (dm-0) ext4 /
└─scorpion-swap_1 (dm-1) swap [SWAP]

Sondear el hardware presente en el sistema

hwinfo se utiliza para generar un reporte general que más tarde pueda ser utilizado por el equipo de soporte para solucionar problemas.

hwinfo --short --partition 2>&1 | grep '/dev/'

/dev/sda1 Partition
/dev/sda2 Partition
/dev/sda3 Partition
Información disponible:
all, bios, block, bluetooth, braille, bridge, camera, cdrom, chipcard,
cpu, disk, dsl, dvb, fingerprint, floppy, framebuffer, gfxcard, hub,
ide, isapnp, isdn, joystick, keyboard, memory, modem, monitor, mouse,
netcard, network, partition, pci, pcmcia, pcmcia-ctrl, pppoe, printer,
scanner, scsi, smp, sound, storage-ctrl, sys, tape, tv, usb, usb-ctrl,
vbe, wlan, zip
hwinfo --short --cpu 2>&1 | grep -v 'cpu:' | grep -i 'cpu'

Intel(R) Core(TM)2 Duo CPU T9500 @ 2.60GHz, 2400 MHz
Intel(R) Core(TM)2 Duo CPU T9500 @ 2.60GHz, 2600 MHz
hwinfo --disk 2>&1 | egrep -i 'Model|Vendor|Device|Driver|Status' | egrep -v 'Device Files|Device Link'

Model: "Hitachi HTS72202"
Vendor: "Hitachi"
Device: "HTS72202"
Driver: "ata_piix", "sd"
Driver Modules: "ata_piix"
Device File: /dev/sda
Device Number: block 8:0-8:15
Config Status: cfg=new, avail=yes, need=no, active=unknown
hwinfo --gfxcard 2>&1 | egrep -i 'Model:|Vendor:|Device:|Driver:|Modules:|Status:'

Model: "nVidia GeForce 8600M GT"
Vendor: pci 0x10de "nVidia Corporation"
Device: pci 0x0407 "GeForce 8600M GT"
SubVendor: pci 0x106b "Apple Computer Inc."
SubDevice: pci 0x00a3
Driver: "nvidia"
Driver Modules: "nvidia"
Config Status: cfg=new, avail=yes, need=no, active=unknown
hwinfo --memory 2>&1 | egrep -i 'memory size'

Memory Size: 3 GB + 768 MB
hwinfo --netcard 2>&1 | egrep -i 'Model:|^Vendor:|^Device:|Driver:|Device File:|HW Address:|Status:|Cmd:'

Model: "Broadcom BCM4328 802.11a/b/g/n"
Driver: "wl"
Device File: eth1
HW Address: 00:1f:5b:d0:7b:5b
Driver Status: ssb is not active
Driver Activation Cmd: "modprobe ssb"
Driver Status: wl is active
Driver Activation Cmd: "modprobe wl"
Config Status: cfg=new, avail=yes, need=no, active=unknown

Model: "Marvell Yukon 88E8058 PCI-E Gigabit Ethernet Controller"
Driver: "sky2"
Device File: eth0
HW Address: 00:1f:f3:d7:33:a9
Driver Status: sky2 is active
Driver Activation Cmd: "modprobe sky2"
Config Status: cfg=new, avail=yes, need=no, active=unknown
hwinfo --network 2>&1 | egrep -i 'Model:|Driver:|Modules:|Device File:|HW Address:|Link detected:|Config Status'

Model: "Ethernet network interface"
Driver: "sky2"
Driver Modules: "sky2"
Device File: eth0
HW Address: 00:1f:f3:d7:33:a9
Link detected: no
Config Status: cfg=new, avail=yes, need=no, active=unknown

Model: "Ethernet network interface"
Driver: "wl"
Driver Modules: "wl"
Device File: eth1
HW Address: 00:1f:5b:d0:7b:5b
Link detected: yes
Config Status: cfg=new, avail=yes, need=no, active=unknown

Model: "Loopback network interface"
Device File: lo
Link detected: yes
Config Status: cfg=new, avail=yes, need=no, active=unknown
hwinfo --sound 2>&1 | egrep -i 'Model:|Vendor:|Device:|Driver:|Modules:|Status:|Cmd:'

Model: "Intel 82801H (ICH8 Family) HD Audio Controller"
Vendor: pci 0x8086 "Intel Corporation"
Device: pci 0x284b "82801H (ICH8 Family) HD Audio Controller"
SubVendor: pci 0x106b "Apple Computer Inc."
SubDevice: pci 0x00a3
Driver: "snd_hda_intel"
Driver Modules: "snd_hda_intel"
Driver Status: snd_hda_intel is active
Driver Activation Cmd: "modprobe snd_hda_intel"
Config Status: cfg=new, avail=yes, need=no, active=unknow

Tablas de particiones

fdisk -l 2>&1 | egrep -v "warning|doesn't" | egrep 'dev/'

Disk /dev/sda: 200.0 GB, 200049647616 bytes
/dev/sda1 1 4095 2047+ ee GPT
/dev/sda2 * 4096 503807 249856 83 Linux
/dev/sda3 503808 390721535 195108864 da Non-FS data
Disk /dev/mapper/ubuntu--vg-root: 195.5 GB, 195513286656 bytes
Disk /dev/mapper/ubuntu--vg-swap_1: 4273 MB, 4273995776 bytes
cat /proc/partitions

major minor #blocks name

11 0 1048575 sr0
8 0 195360984 sda
8 1 1024 sda1
8 2 249856 sda2
8 3 195108864 sda3
252 0 190930944 dm-0
252 1 4173824 dm-1

Parámetros del hardware de los discos IDE y SATA

hdparm es una utilidad de línea de comandos que permite ver y ajustar los parámetros del hardware de los discos IDE y SATA (aunque los SATA también cuentan con una utilidad específica llamada sdparm). Con esta utilidad se pueden ajustar parámetros como el caché de disco, el modo de descanso, el control de energía, la gestión acústica y los ajustes DMA. Suele venir instalado por defecto en la mayoría de distribuciones GNU/Linux.

hdparm proporciona una interfaz de línea de comandos para diferentes interfaces del kernel que son soportadas por el subsistema Linux SATA/PATA/SAS “libata”, también soporta susbsistemas más viejos de controladores IDE.

Muchos Unidades USB recientes (2008 y posteriores) también son compatibles con “SAT” (Traducción de comandos SCSI-ATA) por lo tanto pueden trabajar con hdparm.

Algunas opciones pueden funcionar correctamente sólo con los núcleos (kernels) más recientes.

hdparm -i /dev/sda | egrep -i 'Model|DMA modes|Drive'

Model=Hitachi HTS722020K9SA00, FwRev=DC4AC77A, SerialNo=080520DP0440DTGJKPZP
DMA modes: mdma0 mdma1 mdma2
UDMA modes: udma0 udma1 udma2 udma3 udma4 udma5 *udma6
Drive conforms to: unknown: ATA/ATAPI-2,3,4,5,6,7

Tabla de Contenidos DMI (algunos dicen SMBIOS)

Permite conocer la Tabla de Contenidos DMI (algunos dicen SMBIOS) en un formato legible. Esta tabla contiene una descripción de los componentes de hardware del sistema, así como de otras piezas útiles de información como: números de serie y la revisión del BIOS.

Gracias a la Tabla de Contenidos DMI, se puede recuperar esta información sin tener que probar el hardware actual. Si bien permite un reporte agil y seguro, también puede ser probable que la información presentada algunas veces pueda ser poco fiable.

Por favor consulteHow to Forge: dmidecode

dmidecode -t 16 -t 17 | egrep -i 'capacity|devices|width|size|locator:|type:|speed' | egrep -iv 'error|bank'

Maximum Capacity: 4 GB
Number Of Devices: 2
Total Width: 64 bits
Data Width: 64 bits
Size: 2048 MB
Locator: DIMM0
Type: DDR2
Speed: 667 MHz
Total Width: 64 bits
Data Width: 64 bits
Size: 2048 MB
Locator: DIMM1
Type: DDR2
Speed: 667 MHz

Dispositivos de audio

arecord --list-devices

**** List of PLAYBACK Hardware Devices ****
card 0: Intel [HDA Intel], device 0: ALC889A Analog [ALC889A Analog]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 0: Intel [HDA Intel], device 1: ALC889A Digital [ALC889A Digital]
Subdevices: 1/1
Subdevice #0: subdevice #0
cat /proc/asound/cards

0 [Intel]: HDA-Intel - HDA Intel
           HDA Intel at 0xdb500000 irq 46
En este caso sólo hay una tarjeta de sonido, la cual es la tarjeta de sonido incorporada HDA-Intel.
ls /proc/asound/card*

/proc/asound/cards

/proc/asound/card0:
codec#0  id  pcm0c  pcm0p  pcm1c  pcm1p  pcm2c

Donde X indica el número de tarjeta, por ejemplo, si se muestra card0 y card1, esto quiere decir que hay dos tarjetas de sonido.

ls -ld /proc/asound/card* | grep ^d

dr-xr-xr-x 7 root root 0 ago 11 11:06 /proc/asound/card0

Cantidad de dispositivos conectados a la tarjeta de sonido

cat /proc/asound/devices

1: : sequencer
2: [ 0- 2]: digital audio capture
3: [ 0- 1]: digital audio playback
4: [ 0- 1]: digital audio capture
5: [ 0- 0]: digital audio playback
6: [ 0- 0]: digital audio capture
7: [ 0- 0]: hardware dependent
8: [ 0] : control
33: : timer

Detalles del módulo del núcleo o del driver para una tarjeta de sonido

El módulo relacionado con la tarjeta de sonido se representa con la cadena de texto “snd” en su nombre. Por lo tanto, si podemos buscar sobre /proc/asound/modules o sobre la salida del comando lsmod, entonces si podremos encontrar fácilmente qué tarjeta de sonido está en uso, por ejemplo:

grep snd /proc/asound/modules

0 snd_hda_intel

La versión de software de la tarjeta de sonido

cat /proc/asound/version

Advanced Linux Sound Architecture Driver Version k0.0.0-0-generic.

Linux networking – Descubriendo vecinos en la red

arp-scan -I eth1 192.168.0.0/24 10.0.0.0/8
nmap -sP 192.168.0.0/24 10.0.0.0/8
fping -g -r1 -s 192.168.0.0/24
arp-scan --interface=eth1 --localnet
for ip in $(seq 1 254); do ping -c1 -w1 192.168.0.$ip &>/dev/null; [ $? -eq 0 ] && echo "192.168.0.$ip"; done
for ip in 192.168.0.{1..254}; do if ping -c1 -w1 $ip &>/dev/null; then echo $ip; fi done

LAN IP

hostname -Iip
ifconfig | grep 'eth0' | tr -s ' ' | cut -d ' ' -f5
ifconfig | grep 'eth1' | tr -s ' ' | cut -d ' ' -f5
cat /sys/class/net/eth0/address
cat /sys/class/net/eth1/address

Router

netstat -r
route -n
traceroute -m 1 -N 1 1.2 | grep ms | perl -nle'/\((\S+)/&&print$1' | tr -d \)

Por favor consulte:

Linux networking – Solución simple de problemas

Es muy probable que la mayoría de los problemas relacionados con la red aparecen de las siguientes dos formas:

Lentitud

  • “NIC Duplex” y las incompatibilidades de velocidad.
  • Congestión de la red.
  • Pobre enrutamiento.
  • Error en el cableado.
  • Interferencia eléctrica.
  • Un servidor sobrecargado en el extremo remoto de la conexión.
  • DNS mal configurados.

Todas las fuentes de lentitud pueden llegar a ser tan severas que se termina perdiendo la conectividad.

Falta de conectividad

  • Fallos de alimentación de poder.
  • El servidor remoto está apgando.
  • Un servicio en el servidor remoto se encuentra abajo.

Pruebas de cableado y estado del enlace

Un servidor no puede comunicarse con otro dispositivo de la red a menos que la luz “link” de la tarjeta de red (NIC) se encuentre encendida. Esto indica que la conexión entre el servidor y el switch/router está funcionando de manera correcta.

En la mayoría de los casos, la falta de un enlace es debido al uso equivocado del tipo de cable. Por ejemplo, hay dos tipos de cables Ethernet, uno es “crossover” y el otro es “straight-through”. Otras fuentes de fallo de enlace pueden ser:

  • Los cables no funcionan.
  • El switch o router al que está conectado el servidor está apagado.
  • Los cables no están bien conectados.

Si se cuenta con una red extensa, la inversión en un probador de cable es esencial para realizar pruebas básicas de conectividad. Los modelos más sofisticados en el mercado pueden indicar la ubicación aproximada donde ocurre la rotura del cable, también cuando un cable Ethernet es demasiado largo para ser utilizado.

Probando la NIC

En la solución de problemas, es una buena práctica dar seguimiento al estado de una tarjeta NIC desde la línea de comandos.

Viendo sólo las interfaces activas

ifconfig
netstat -ie
ifconfig | egrep 'Link encap|HWaddr|inet addr|RX|TX|errors|collisions'

Todas las interfaces, aunque no estén activas

ifconfig -a

Consideraciones sobre DHCP

Los clientes DHCP de manera automática proporcionan sus tarjetas de red (NICs) y direcciones IP que comienzan con 169.254.xx hasta que puedan entrar en contacto con el servidor DHCP. Cuando se logra el contacto se reconfiguran las direcciones IP a los valores proporcionados por el servidor DHCP. Por lo tanto, una interfaz con una dirección 169.254.xx significa que hay un fallo en la comunicación con el servidor DHCP.

Estado del enlace (link status)

Conocer información sobre las velocidades de autonegociación compatibles de la tarjeta de red, es útil para resolver problemas de velocidad y dúplex.

mii-tool

mii-tool -v | egrep -i 'eth|link ok'
eth0: negotiated 100baseTx-FD flow-control, link ok
basic status: autonegotiation complete, link ok

eth1: negotiated 100baseTx-FD, link ok
basic status: autonegotiation complete, link ok

apt-get install ethtool

El comando ethtool proporciona mucha más información que el comando mii-tool, además pronto el comando mii-tool será obsoleto en Linux.

ethtool
ethtool eth0 | grep detected
ethtool eth0 | grep Speed

Errores en la tarjeta de red (NIC) 0.5%

Los errores son un síntoma común de una conectividad lenta debido a:

  • Una mala configuración.
  • Un uso excesivo del ancho de banda.

Las tasas de error superiores a 0.5% pueden causar una lentitud bastante notable.

ethtool -S eth0

Con la opción -S de ethtool se puede consultar un dispositivo de red específico con el objetivo de obtener estadísticas sobre:

  • La tarjeta de red NIc
  • El controlador.

netstat

El comando netstat es bastante útil en los sistemas que no cuentan con los comandos mii-tool y ethtool.

Muestra información relacionada con todas las interfaces de red. Datos de las transacciones de paquetes de red, incluyendo tanto la transferencia de paquetes como la recepción de paquetes con un tamaño de MTU.

netstat -i
  • RX-OK: Correct packets received on this interface.
  • RX-ERR: Incorrect packets received on this interface
  • RX-DRP: Packets that were dropped at this interface.
  • RX-OVR: Packets that this interface was unable to receive.

Definiciones similares para las columnas TX que describen los paquetes transmitidos.

Tabla de enrutamiento IP del núcleo (kernel)

netstat -r
route -e
  • A Receive all multicast at this interface.
  • B OK broadcast.
  • D Debugging ON.
  • M Promiscuous Mode.
  • O No ARP at this interface.
  • P P2P connection at this interface.
  • R Interface is running.
  • U Interface is up.
  • G Not a direct entry.

Nombre de servicio con PID

netstat -tp

Monitoreo constante

netstat -ic

Posibles causas de errores de Ethernet

  • Colisiones: Cuando la tarjeta NIC se detecta así misma y otro servidor en la LAN trata de transmitir datos al mismo tiempo. Las colisiones se puede esperar como una parte normal de la operación de Ethernet y están típicamente por debajo de 0,1% de todas las tramas enviadas (frames sent). En general, las altas tasas de error son probablemente causadas ​​por tarjetas de red NIC defectuosas o cables mal terminados.
  • Colisiones individuales: La trama Ethernet atravesada después de sólo una colisión.
  • Colisiones múltiples: La NIC tuvo que intentar varias veces antes de enviar con éxito la trama debido a las colisiones.
  • CRC: Cuando las tramas son eviadas pero se corrompen en el tránsito. La presencia de errores CRC, pero sin muchas colisiones por lo general es una indicación de que existe ruido eléctrico. Hay que verificar el tipo correcto de cable, que el cableado no se encuentre dañado y que los conectores estén bien fijados.
  • Trama (Freme errors): Un CRC incorrecto y un número no entero de bytes se reciben. Esto suele ser el resultado de colisiones o porque un dispositivo Ethernet se encuentra defectuoso.
  • FIFO y saturación: El número de veces que la NIC no fue capaz de entregar datos a sus buffers de memoria debido la tasa de datos de las capacidades del hardware. Esto suele ser un signo de exceso de tráfico.
  • Longitud: La longitud de la trama recibida fue menor o superior al estándar Ethernet. En general, se debe a una configuración dúplex incompatible.
  • Carrier: Debido a que la tarjeta NIC pierde su conexión de enlace (link connection) con el hub o switch. Verifique que el cableado, las interfaces NIC y los equipos de red no encuentren defectuosos.

¿Cómo se ven las direcciones MAC?

Hay momentos en que se puede perder conectividad con otro servidor que está directamente conectado a nuestra red local. Echar un vistazo a la tabla ARP desde el servidor con problemas puede ayudar a determinar si la tarjeta de red NIC del servidor remoto está respondiendo bien a cualquier tipo de tráfico desde mi equipo Linux. La falta de comunicación a este nivel puede significar:

  • Cualquier servidor puede estar desconectado de la red.
  • Es posible que haya cableado de la red dañado.
  • Una tarjeta de red NIC podría estar deshabilitada o el servidor remoto se encuentra abajo.
  • El servidor remoto puede estar corriendo un firewall tal como iptables o como el firewall propio de Windows o Mac. Típicamente, en este caso, se puede ver la dirección MAC y que el servidor está corriendo el software adecuado, pero la comunicación deseada no parece estar ocurriendo para el cliente en la misma red.

A continuación, una descripción de los comandos que se pueden usar para determinar los valores ARP:

El comando ifconfig -a muestra tanto la dirección de MAC de la NIC como las direcciones IP asociadas al servidor en el que nos encontramos. Por lo tanto puede ser posible que una sola interfaz pueda tener dos direcciones atadas al mismo tiempo.

El comando arp -a muestra las direcciones MAC en la tabla ARP del servidor y todos los demás servidores de la red conectada directamente. En general, se puede ver que se tiene algún tipo de conexión con algún router en alguna dirección.

arp -e

Nota: En ambos lados se recomienda verificar que las direcciones IP que aparecen en la tabla ARP coinciden con los de los servidores esperados y aceptables en la red. Si no coinciden, el servidor puede estar conectado en el interruptor del switch o router equivocado.

Si servidor problemático está conectado a la red local o no, es una buena práctica forzar una respuesta de él.

Ping

Uno de los métodos más comunes utilizados para probar la conectividad a través de múltiples redes es el comando ping.

ping envía paquetes “ICMP echo” que solicitan una respuesta “ICMP echo-reply” correspondiente del dispositivo en la dirección de destino. Como la mayoría de los servidores responden a consultas de ping, este comando se convierte en una herramienta muy útil. Una falta de respuesta de ping podría ser debido a:

  • Un servidor con esa dirección IP no existe.
  • El servidor ha sido configurado para no responder a consultas de ping.
  • Un firewall o router a lo largo de la ruta de red está bloqueando el tráfico ICMP.
  • Hay un enrutamiento incorrecto. Compruebe las rutas y las máscaras de subred en ambos lados, los servidores locales y remotos, también en los routers en el medio. Un síntoma clásico de rutas incorrectas en un servidor es la capacidad de sólo hacer ping a los servidores de la red local y no a ninguna otra parte. Podemos usar traceroute para verificar que se está tomando el camino correcto.
  • Cualquiera de los dos, el dispositivo origen o destino tiene una dirección IP o una máscara de subred incorrecta.

Notas:

  • El comando ping Linux envia pings continuos, uno cada segundo, hasta que se detiene con Ctrl-C.
  • Hay una variedad de códigos de respuesta ICMP que pueden ayudar en la solución de problemas.

Si se obtiene un mensaje “Destination Host Unreachable“. Es probable que el mensaje es causado por el router o servidor sabiendo que la dirección IP de destino es parte de una red válida, pero no recibe ninguna respuesta por parte del servidor de destino. Hay un número de razones para esto:

Si se está tratando de hacer ping a un host en una red directamente conectada:

  • El cliente o el servidor puede estar abajo, o desconectado de la red.
  • La NIC no tiene la configuración dúplex adecuada, esto se puede verificar esto con el comando mii-tool.
  • Es posible que se cuente con un tipo incorrecto de cable de conexión desde nuestra máquina Linux hacia la red. Hay dos tipos básicos, “straight through” y “crossover”.
  • En el caso de una red inalámbrica, puede ser que los SSID o las claves de cifrado pueden estar incorrectas.

Si se está tratando de hacer ping a un host de red remoto:

  • El dispositivo de red no tiene una ruta en su tabla de enrutamiento para la red de destino y envía una respuesta ICMP tipo 3 que desencadena el mensaje. El mensaje resultante podría ser “Destination Host Unreachable” o “Destination Network Unreachable”.

Probando la conectividad de red con telnet

Una manera fácil de saber si un servidor remoto está escuchando en un puerto TCP específico es utilizar el comando telnet. De forma predeterminada, telnet intentará conectarse en el puerto TCP 23, pero se pueden especificar otros puertos TCP después de la dirección IP de destino. Por ejemplo, HTTP utiliza el puerto TCP 80 y HTTPS utiliza el puerto 443.

Al usar telnet para la solución de problemas, hay algunas pautas útiles que permiten aislar el origen del problema:

  • Pruebe la conectividad desde el equipo remoto.
  • Verificar la conectividad en el propio servidor. Trate de hacer la conexión a la dirección “loopback”, así como la dirección IP del NIC. Si el servidor se encuentra usando un firewall tal como iptables, se verifica que “loopback” permita toda conectividad, aunque algunas veces la conectividad a ciertos puertos TCP en la interfaz de red NIC algunas vences pueden estar bloqueados.
  • Pruebe la conectividad desde otro equipo de la misma red que el servidor destino. Esto ayuda a eliminar la influencia de “firewalls” que protegen toda la red desde fuera.

Encontrando solución de problemas con telnet

Recuerde iptables. Es probable que muchos servidores de Linux tienen el firewall iptables instalado por defecto. Esto muy a menudo es la causa de muchos problemas de conectividad, por lo que las reglas del “firewall” deben actualizarse de la manera adecuada. En algunos casos en que la red ya está protegida por un “firewall”, iptables pueden ser apagado de forma segura.

En Linux una conexión telnet con éxito siempre presenta un saludo de conexión.

Mensajes de rechazo de conexión

  • Se puede recibir un mensaje de rechazo de conexión por una de las siguientes razones:
  • La aplicación que estamos tratando de probar no se ha iniciado en el servidor remoto.
  • Existe un “firewall” bloqueando y rechazando el intento de conexión.
telnet 192.168.0.20 22
Trying 192.168.0.20...

telnet: Unable to connect to remote host: Connection timed out

Solución de problemas en Windows

A veces hay que solucionar servidores Linux desde un equipo con Windows. Los comandos de telnet son los mismos, pero los resultados son diferentes. Si la pantalla queda en blanco, entonces la conexión es correcta. Si hay conectividad, la pantalla del símbolo del sistema se mostrará en blanco. Con la combinación de teclas Ctrl-C le se puede salir del intento de telnet.

Mensajes “Connect Failed”

Los mensajes “Connect Failed” en Windows son el equivalente de “Connection refused” en Linux.

Tiempo de espera se cuelga usando telnet

Como se menciona arriba, si no hay conectividad, la sesión aparecerá como colgada o agotada. De manera general, esto es causado porque el servidor de destino está apagado o por que un “firewall” se encuentra bloqueando la conexión.

Probando sitios Web con las utilidades curl y wget

Obtener una buena idea de la fuente de rendimiento de un servidor web utilizando sólo un navegador Web es insuficiente. Muchos códigos de error HTTP útiles a menudo no se muestran en los navegadores, lo que hace difícil la solución de problemas.

Una mejor combinación de herramientas es utilizar telnet para probar el tiempo de respuesta del puerto TCP 80 de un sitio en conjunto con los datos obtenidos por utilidades como curl y wget.

Tiempos rápidos de respuesta TCP, con tiempos lentos de curl y wget apunta a que no es un problema de red, pero sí puede ser un problema de lentitud en la configuración del servidor Web, los servidores de aplicación o en la base de datos que se utilizan para generar la página Web.

Usando curl

La utilidad curl actúa como un navegador Web basado en texto en el que se puede elegir si se desea ver sólo el encabezado o sólo cuerpo completo del código HTML de una página Web que se muestra en la pantalla.

Un buen comienzo es usar el comando curl -I para ver sólo el encabezado de la página Web y el código de estado HTTP. Si no utiliza la bandera -I entonces se desplegará todo el código HTML de la página Web que se muestra en la pantalla. Cualquier método puede proporcionar una buena idea del rendimiento de su servidor.

curl -I www.josoroma.com

Usando wget

Se puede usar wget para descargar un directorio local y de forma recursiva todas las páginas de un sitio Web, incluyendo la estructura de directorios del sitio Web.

Sin usar recursividad, y activando la función de “timestamp” (la opción -N), permite no sólo ver el contenido HTML de la página del index del sitio Web en el directorio local, también se puede ver la velocidad de descarga, el tamaño del archivo y el tiempo preciso de inicio y finalizacón de la descarga. Esto puede ser muy útil para obtener “snapshots” de rendimiento del servidor.

El comando netstat

Tal como curl y wget, netstat puede ser muy útil para ayudar a determinar el origen de los problemas. Usar netstat, con la opción -an permite listar todos los puertos TCP en los que el servidor Linux está escuchando, incluyendo todas las conexiones de red activas desde y hacia el servidor. Esto puede ser muy útil para determinar si la lentitud se debe a los altos volúmenes de tráfico:

netstat -an

La mayoría de las conexiones TCP crean conexiones permanentes, HTTP es diferente porque las conexiones se cierran por sí solas después de un tiempo de espera predeterminado de inactividad o de “time_wait” en el servidor Web. Por lo tanto, es una buena idea centrarse en este tipo de conexiones de corta duración también.

Se puede determinar el número de conexiones establecidas y el número de conexiones “time_wait” TCP en el servidor usando el comando netstat, seguidamente filtrado por los comandos grep y egrep y, con el número de coincidencias (matches) que sean contabilizados por el comando wc.

netstat -an | grep tcp | egrep -i 'established|time_wait' | wc -l

El famoso firewall iptables

Una fuente inesperada de problemas de conectividad en servidores nuevos, con frecuencia, puede ser por el firewall iptables. Algunas veces es posible tratar de detener iptables mientras se solucionan problemas.

La gestión de iptables es fácil de hacer, pero el procedimiento es suele ser diferente entre las diversas distribuciones de Linux. Algunas cosas que hay que tener en mente son las siguientes:

  • En primer lugar, las diferentes distribuciones de Linux utilizan diferentes sistemas de gestión de demonios. Cada sistema tiene su propio conjunto de comandos para hacer operaciones similares. Los sistemas de gestión de demonio más comunes son SysV y Systemd.
  • En segundo lugar, el nombre demonio necesita ser conocido. En el caso de iptables el nombre del demonio es iptables.

Con esta información, se puede saber cómo:

  • Comenzar demonios automáticamente en el arranque (booting).
  • Detener, iniciar y reiniciar demonios al momento de resolver problemas.
  • Cuando un cambio en un archivo de configuración necesita y debe aplicarse.

Probando la conectividad con traceroute

Otra herramienta para solucionar problemas de red es el comando traceroute. Ofrece una lista con todos los nodos (hops) de enrutador entre nuestro servidor origien y el servidor de destino. Esto ayuda a verificar que el enrutamiento a través de las redes en el medio es correcto.

El comando traceroute funciona enviando un paquete UDP hacia el destino con un TTL de 0. El primer router en la ruta reconoce que el TTL de hecho ya ha se ha excedido en tiempo, por esta razón descarta el paquete, pero también envía un mensaje ICMP de tiempo excedido de regreso a la fuente. El programa traceroute registra la dirección IP del router que envía el mensaje y sabe que ese es el primer nodo en la ruta hacia el destino final. Seguidamente el programa traceroute intenta de nuevo, esta vez con un TTL de 1. El primer nodo de la ruta no ve nada extraño con el paquete, entonces disminuye el TTL a 0 como se esperaba, y reenvía el paquete al segundo nodo en la ruta. Router 2, ve el TTL de 0, descarta el paquete y responde con un mensaje ICMP de tiempo excedido. Por lo tanto, ahora traceroute conoce bien la dirección IP del segundo router. Esto continúa de nodo en nodo hasta que se alcanza el destino final.

Usando traceroute sólo se reciben respuestas de dispositivos que funcionan. Si un dispositivo responde quiere decir que es menos probable que sea la fuente de los problemas de conectividad.

50 ms es aceptable

Observe que todos los tiempos en los diversos nodos de la ruta sean inferiores a 50 milisegundos (ms), lo cual es bastante aceptable.

traceroute google.com

Respuesta dentro de 5 segundos

Si no hay respuesta dentro de un intervalo de 5 segundos de tiempo de espera, la prueba se marca con asterisco (*).

Algunos dispositivos evitan paquetes traceroute dirigidos a sus interfaces, pero sí permiten paquetes ICMP. Usar traceroute con la opción -I fuerza traceroute a utilizar paquetes ICMP. En ese caso, el esado de mensaje *** desaparece:

traceroute -I google.com

Falsa alarma de lentitud

Muchas veces traceroute da la impresión de que un sitio Web o una Ip puede ser lenta porque hay alguna congestión en el camino en el sector, entre por ejemplo el nodo 6 y 7 de la ruta, donde algun tiempo de respuesta puede ser de más de 200ms.

Esto indica que sólo los dispositivos en los nodos 6 y 7 de la ruta están lentos para responder con mensajes ICMP de TTL excedido, pero no es una indicación de: congestión, latencia o pérdida de paquetes. Si alguna de estas condiciones existiera entonces todos los puntos anteriores en el vínculo problemático mostrarían alta latencia.

Muchos dispositivos de enrutamiento en la Internet dan muy poca prioridad al tráfico relacionado con traceroute para favorecer el tráfico de generación de ingresos (revenue generating traffic).
Muere en el router justo antes del servidor

En este caso, el último dispositivo en responder a traceroute es el router que actúa como puerta de enlace predeterminada del servidor. Entonces el problema no es con el router, pero sí con el servidor. Recuerde, usted sólo recibirá respuestas traceroute desde dispositivos que sí funcionan. Las posibles causas de este problema podrían ser las siguientes:

  • Un servidor tiene una puerta de enlace predeterminada mala.
  • El servidor se encuentra ejecutando algún tipo de “firewall” que bloquea traceroute.
  • El servidor está apagado, desconectado de la red o tiene un NIC mal configurado.

Siempre probar un traceroute bidireccional

Es mejor obtener un traceroute desde la IP origen hasta la IP destino y también desde la IP de destino hasta la IP origen. Esto se debe a que la ruta de retorno de paquetes desde el destino a veces no es la misma ruta tomada para llegar allí.

Un traceroute alto equivale al tiempo de ida y vuelta (round trip time), tanto para la consulta traceroute inicial para cada nodo de la ruta y la respuesta de cada nodo de la ruta.

Resolución de problemas con ping y traceroute

En este ejemplo, un ping a una IP da un mensaje de tiempo de espera TTL (TTL timeout message). Los tiempo de espera ocurren sólo si hay un bucle de enrutamiento en el que el paquete rebota entre dos enrutadores en su camino hacia el destino. Cada rebote hace que el TTL disminuya su conteo en 1 hasta que el TTL alcanza 0, en este momento se obtiene el “TTL timeout message”.

Estos problemas reconfigurando (reseteando) ambos routers. El problema inicial fue provocado por un enlace inestable en la red que causaba cálculos de enrutamiento frecuentes. Dicha actividad constante dañó las tablas de enrutamiento en uno de los routers.

traceroute para Sitios Web

Muchos ISP ofrecen la posibilidad de hacer un traceroute desde servidores llamados “Internet looking glass”. Permiten correr traceroute desde una variedad de lugares que pueden ayudar a identificar si el problema es con el ISP del servidor Web o con el ISP utilizado que usamos acceder a la Internet desde nuestra casa o trabajo. Una forma cómoda de hacerlo es utilizando el sitio www.traceroute.org que proporciona una lista de espejos por país.

Razones por las que puede fallar traceroute

Un traceroute puede fallar en alcanzar su destino por una serie de razones, incluyendo las siguientes:

  • Los paquetes traceroute están siendo bloqueando por un router en el camino. El router inmediatamente después del último visible suele ser el culpable. Por lo tanto es bueno revisar la tabla de enrutamiento y/o cualquier otro estado de este siguiente dispositivo en la ruta.
  • El servidor destino no existe en la red. Podría estar desconectado o apagado. (Se pueden producir los mensajes !H o N!).
  • La red en la que se espera que el host destino puede residir no existe en la tabla de enrutamiento de uno de los routers en el camino. (Se pueden producir los errores !H o !N).
  • Puede haber un error tipográfico en la dirección IP del servidor de destino.
  • Puede haber un bucle de enrutamiento en que los paquetes rebotan entre dos routers y nunca llegan al destino deseado.
  • Los paquetes no tienen una ruta apropiada de retorno a nuestro servidor. El último nodo visible es el último nodo en el que los paquetes vuelven correctamente. El router inmediatamente después del último nodo visible es en el que el enrutamiento cambia. Por lo general es bueno hacer lo siguiente:
    • Iniciar sesión en el último nodo enrutador visible.
    • Mira la tabla de enrutamiento para determinar cuál es el siguiente nodo destino previsto.
    • Iniciar sesión en el siguiente router.
    • Hacer un traceroute desde este router hacia servidor destino previsto.
    • Si esto funciona: El enrutamiento hacia servidor de destino está bien. Hacer un traceroute de nuevo hacia nuestro servidor de origen. Entonces probablemente el traceroute fallará en el router malo que se encuentra en el camino de regreso.
    • Si esto no funciona: Hay que porbar la tabla de enrutamiento y/o cualquier estado de todos los nodos entre este y y el destino previsto.

Nota: Si no hay algo que bloquee el tráfico traceroute, entonces el último enrutador visible de un traceroute es el último router bueno en el camino, o el último router que tiene un retorno válido hacia el servidor emitiendo el traceroute.

Por favor consulte: Simple Network Troubleshooting

Linux Networking: Lo que sucede en la Red

“Siempre hay que guardar los registros para que otros también puedan interpretar los reportes tal y como los vimos.”

Probando la conectividad con ping

No es un secreto que ping es la herramienta número uno para comprobar la conectividad.

ping -c3 scanme.nmap.org

Se recomienda no bloquear los siguientes mensajes:

  • echo-request
  • echo-reply
  • time-exceeded
  • destination-unreachable

Algunos administradores de sistemas bloquean los mensajes de ping en sus firewalls, y este es un error y un problema porque la mayoría de las funciones de las redes ocupan que al menos estos 4 mensajes operen de manera adecuada.

Perfile y compare la red con FPing y Nmap

Primero descubramos todos los hosts de la red, los que conforman la subred:

arp-scan -I eth0 192.168.0.0/24 10.0.0.0/8

nmap -sP 192.168.0.0/24 10.0.0.0/8

Seguidamente podemos establecer la línea base de rendimiento de la red mediante ping, lo cual es útil para tener con que comparar al momento de tratar de encontrar soluciones a problemas de rendimiento. Muchas de estas características se pueden automatizar con ping, con un script que reporte el rendimiento de toda una subred.

Por favor consulte:

fping -c1 -sdg 192.168.0.0/24 2>&1 | egrep -v "ICMP|xmt"

Encontrando IPs duplicadas

arping -c5 -D 192.168.0.1

arping -c5 -D 192.168.0.15

arping también es esencial para ver si un host se encuentra arriba cuando ping falla, pero usar arping no va a funcionar cuando ping se encuentre bloqueado.

Pruebas de latencia y rendimiento HTTP

httping -c5 -g scanme.nmap.org

httping -c5 -Gg scanme.nmap.org

httping -c5 -h scanme.nmap.org -p 80

httping -c5 -Gsbrg scanme.nmap.org

Escarbando y localizando los problemas de red

Si existe un problema tratando de alcanzar algún host o equipo en la red y además ping lo confirma, hay que imaginar que deben de haber varios routers entre nosotros y el problema, por esta razón es que es necesario escarbar un poco más, gracias a la bondad esto se puede hacer con:

traceroute scanme.nmap.org

traceroute -n scanme.nmap.org

traceroute -q5 -w1 scanme.nmap.org

Traceroute significa seguir la ruta de los paquetes desde una IP de la red en su camino hacia un host determinado. Utiliza el tiempo de vida (TTL) del protocolo IP e intenta provocar una respuesta ICMP TIME_EXCEEDED para cada puerta de enlace a lo largo de la ruta necesaria para llegar al host destino.

Si por alguna razón traceroute no funciona sobre la Internet, ya que algunos routers pueden estar programados para ignorar datagramas UDP. Por esta razón, si vemos muchos “timeouts”, podemons intentar con la opción -I, le dice a traceroute que envíe peticiones ICMP ECHO en lugar de peticiones TCP SYN.

También se puede usar tcptraceroute, el cual envía paquetes TCP SYN en lugar de paquetes UDP o paquetes ICMP ECHO. Estos son más propensos a pasar a través de firewalls, y van a ser menos ignorados por routers. Una vez que el host responde, tcptraceroute envía TCP RST para cerrar la conexión, por lo que el “TCP three-way handshake” nunca es completado. Este es igual a las opciones (-sS) de exploración medio-abierta utilizada por Nmap.

Como alternativa, también se puede usar tcptraceroute:

tcptraceroute scanme.nmap.org

Cuando se inicia mtr, investiga la conexión de red entre el host donde se corre mtr y el host destino HOSTNAME. Lo que hace es enviar paquetes con un TTL bajo, entonces continúa enviando paquetes con un TTL bajo, considerando el tiempo de respuesta de los routers intermedios. Esto le permite a mtr desplegar el porcentaje de respuesta y los tiempos de respuesta de la ruta vía internet hacia nombre el host destino HOSTNAME. Por lo tanto, un aumento repentino en la pérdida de paquetes o en el tiempo de respuesta, a menudo es una indicación de problemas de sobrecarga en un enlace.

mtr scanme.nmap.org

mtr -n scanme.nmap.org

mtr -c60 scanme.nmap.org

Debido a que mtr puede generar una gran cantidad de tráfico de red, se recomienda no dejarlo corriendo de manera indefinida.

Entonces si un router se presenta caido de manera constante, o si mtr consistentemente muestra más de un 5 por ciento en la pérdida de paquetes o largos tiempos de tránsito en el mismo router, entonces es seguro decir que ese router en particular tiene un problema. Si se trata de un router que podemos controlar, entonces hay buenos motivos para intentar arreglarlo. Si no es así, entonces podemos usar dig o whois para averiguar a quién pertenece, incluso para avisarles sobre el problema por si no se han dado cuenta.