miércoles, 27 de noviembre de 2013

Tuberías y concatenación de comandos

Resto de entradas con intenciones didácticas en la etiqueta Aprendizaje.

Esta entrada está estrechamente relacionada con la última publicada en este blog. Si con la redirección de comandos empezamos a tomar contacto con una forma de introducir órdenes en la terminal de forma que no se tratara de simplemente de teclear el comando, con las tuberías y las concatenaciones aumentaremos las prestaciones de nuestra shell hasta límites que solo nuestra imaginación podrá establecer.

Pipes o tuberías

Describir las pipes o tuberías es sencillo: se trata de utilizar la salida de un comando (su resultado) como entrada de otro. Hablando en términos matemáticos, 3 + 4 - 5 x 8 sería como una tubería; el resultado de 3 + 4 es el primer operando (la entrada) de la siguiente operación, y su resultado el primer operando la de la siguiente operación.

Para construir una tubería utilizamos en carácter | (Alt Gr + 1) y lo colocamos entre la sucesión de comandos que queremos ejecutar. Para trabajar con tuberías es muy frecuente emplear el comando tee.

tee
Sirve para enviar la entrada del teclado a la pantalla y a uno o más ficheros.
tee -a: inserta los datos al final del archivo.
Veamos algunos ejemplos:
cat grupos001.txt | tee grupos002.txt
De esta forma hemos listado el contenido del fichero grupos001.txt con el comando cat y la salida de dicho comando la hemos enviado, mediante una tubería, al comando tee, el cual nos muestra en pantalla ese contenido y, al mismo tiempo, nos lo inserta en el archivo grupos002.txt que, si no existe, será creado. Sería otra manera de duplicar un archivo, pero es solo un ejemplo de uso.
cat puesto01.txt 2>&1 | tee puesto02.txt
Lo que hemos hecho ahora es listar el archivo puesto01.txt, enviar el error estándar a la pantalla y enviar la salida del comando cat al comando tee, tubería mediante, para crear puesto02.txt.
cat archivo1 2>&1 | tee -a archivo2
Este tercer ejemplo es igual que el anterior pero al incluir el modificador -a al comando tee lo que hacemos en añadir los datos listados de archivo1 en archivo2 si este ya existiera.

Son ejemplos muy simples pero sirven para observar el potencial que pueden tener varias tuberías consecutivas a la hora de simplificar operaciones en el terminal de comandos.

Concatenación de comandos

La concatenación funciona de manera similar a las tuberías pero con una salvedad: en esta ocasión hablamos de comandos ejecutados consecutivamente, uno tras otro y en la misma línea, pero independientes entre sí. Se pueden separar de dos formas obteniendo dos diferentes resultados:
Ejemplo 1: cd /etc ; ls -l
Aquí, los comandos cd /etc y ls -l están separados por el carácter ; lo que significa que aunque el primero de un error el siguiente se ejecuta de todas formas, y así sucesivamente en caso de haber más.
Ejemplo 2: cd /etc && ls -l
En cambio, si están separados por && al primer error la secuencia de comandos se detiene, sea la concatenación tan larga como sea.

Un ejemplo clásico de concatenación es teclear en el terminal la siguiente línea:
sudo apt-get update ; sudo apt-get upgrade
Suele ocurrir que cuando queremos actualizar repositorios y sistema con estos dos comandos el primero se toma su tiempo antes de que podamos ejecutar el segundo, lo que nos lleva a estar pendiente del monitor pasa saber cuando introducir la segunda orden. De este modo actualizaremos nuestros repositorios con apt-get update y nuestra distribución con apt-get upgrade de una sola vez. Es como dejar programadas varias tareas para que se vayan realizando una detrás de la otra hasta quedar todas acabadas.

Y como hemos hablado de pipes escuchemos a la que fue banda de Pepper Keenan, Corrosion Of Conformity, en el vídeoclip de "Albatross".



sábado, 23 de noviembre de 2013

Redirección de comandos

Resto de entradas con intenciones didácticas en la etiqueta Aprendizaje.

Hoy vamos a conocer como redireccionar el resultado de un comando hacia la pantalla o hacia un archivo. Se emplean unos caracteres llamados operadores de redirección o redireccionadores para enviar el resultante de la ejecución de un comando al lugar donde nos interesa tenerlo.

Lo primero a tener claro es que los procesos en GNU/Linux tienen asociados tres archivos ubicados en el directorio /dev y denominados:

/dev/stdin o entrada estándar
/dev/stdout o salida estándar
/dev/stderr o salida de errores

La entrada estándar o stdin es el lugar desde donde un comando obtiene la información a procesar, y por defecto es el teclado.

La salida estándar o stdout es el lugar donde un comando envía el resultado de su ejecución, y por defecto es la pantalla del terminal.

La salida de errores o stderr es el lugar donde un comando envía un mensaje de error en caso de que se produzca; por defecto es la pantalla pero también puede ser un archivo.

Cada uno de estos tres archivos lleva también asociado un número descriptor:

stdin - 0
stdout - 1
stderr - 2

Luego están los operadores, que son los símbolos < y >. Con estos caracteres realizaremos la operativa de redirección. Resumiendolo en una tabla:
  1. stdin  -  entrada estándar (teclado)  - Descriptor: 0  - Operador: <
  2. stdout  -  salida estándar (terminal)  - Descriptor: 1  - Operador: >
  3. stderr  - salida de errores (pantalla o archivo)  - Descriptor: 2  -  Operador: >
Para entender todo esto lo mejor es verlo con ejemplos.

Imaginemos que queremos enviar la salida de un comando a un fichero para verlo con posterioridad, por ejemplo, el listado del contenido de nuestro directorio actual (comando ls -l) al archivo lista.txt. Lo haríamos así:
1) De salida estándar stdout (pantalla) a archivo -1er caso-: ls -l > lista.txt
Así, en lugar que ver el resultado del comando ls -l por pantalla obtendríamos un archivo llamado lista.txt en el que aparece el contenido de nuestro directorio actual según los términos del comando ls -l. Si este archivo ya existiera lo sobreescribiría. Veamos más ejemplos.
2) De salida estándar stdout (pantalla) a archivo -2º caso-: ls -l >> lista.txt
En este caso el redireccionador es >> y lo que conseguimos con él es añadir el resultado del comando ls -l al archivo lista.txt ya existente. Podemos así añadir contenido al archivo repetidas veces si no queremos crear uno nuevo cada vez o machacar el ya existente.
3) De error estándar stderr a archivo (1er caso): ls -l 2> errores.txt
Habrá ocasiones en que un comando nos de error al ejecutarse, total o parcialmente, y en esa ocasión quizá sea útil ver pausadamente en qué consiste ese error. Para eso está la salida de errores y lo más común es derivarla a un archivo, en este caso errores.txt. Recuerden que si ya existe lo sobreescribirá. Si no se produce ningún error el archivo se creará sin contenido alguno. No saldrá nada por pantalla.
4) De error estándar stderr a a archivo (2º caso)ls -l 2>> errores.txt
Mismo caso que el que vimos más arriba; si el redireccionador es doble lo que hacemos es añadir contenido al archivo de errores designado (que sigue siendo errores.txt). Tampoco saldrá nada por pantalla.
5) De error estándar stderr a la salida estándar stdout (pantalla): cp * 2>&1
En esta ocasión usando los descriptores hemos redireccionado la salida de error del comando cp * (copiar todo) a la salida estándar (la pantalla) mediante el carácter &. De esta forma si no es posible copiar todo lo designado con el comando cp por el motivo que sea (como puede ser no tener privilegios para hacerlo) los mensajes de error serán visualizados por la salida estándar (pantalla).
6) De un archivo al comando por la entrada estándar stdin (teclado): grep "López" < empleados.txt
Aquí hemos empleado el comando grep, el cual sirve para filtrar resultados en función del parámetro introducido, que ha sido "López". De este modo, dentro de un hipotético archivo llamado empleados.txt se han buscado todas las líneas de texto que contengan "López" y el resultado de esta búsqueda se ha enviado a la salida estándar (pantalla). Dicho de otro modo, el resultado de la búsqueda se emplea como entrada del comando grep y el resultado de su ejecución lo vemos por la pantalla.
7) De error estándar stderr a dispositivo nulo: ls -l 2> /dev/null
De esta forma los errores producidos al ejecutar el comando ls -l irán a un dispositivo nulo y se perderán.
8) De salida estándar stdout a dispositivo nulo: ls -l > /dev/null
No hay mucho más que explicar de este caso: el comando se ejecuta y su resultado se pierde por el agujero negro de la salida nula.

Como siempre digo, conviene consultar toda la documentación que cada uno tenga a mano para completar y terminar de entender el concepto de redirección. Y practicar, practicar mucho.

Parece que la ocasión la pintan calva para engarzar un vídeo de One Direction, ¿verdad? Pues lo siento, se van a quedar con las ganas. Ahí tienen a la extinta formación post-metalera Isis que, digamos, transitaron por senderos ligeramente dispares.



sábado, 9 de noviembre de 2013

Más comandos para operar con archivos y directorios

Resto de entradas con intenciones didácticas en la etiqueta Aprendizaje.

Ya hemos hablado de como trabajar con archivos y directorios pero no es posible condensar todo el material que bajo ese título podría caber sin convertir la entrada en interminable. De tal modo, nuevamente vamos a vernos las caras con mandatos de terminal que nos ofrecen distintas prestaciones según la tarea que estemos realizando.

alias
Este comando ya fue tratado en el blog para un ejemplo concreto, pero no quiero que se quede fuera del tratamiento general que es la tónica del blog. Sirve para crear un atajo a un comando fijándole un nombre.
alias -a: elimina las definiciones de alias en el entorno de ejecución actual.
alias -p: muestra la lista de alias existente en el archivo .bashrc con el formato nombre_alias=valor.
alias instalar="sudo apt-get install":  crea un atajo para el comando sudo apt-get install llamado instalar.
alias lhost="cd /var/www/html": crea un atajo de acceso al directorio /var/www/html/ llamado lhost.
/comando_alias: tecleado de esta manera, en caso de invocar un alias cuyo nombre coincida con el de otro comando, no se tiene en cuenta dicho alias.
~/.bashrc: archivo oculto donde se incluyen los alias que deseamos que se vuelvan permanentes. 
unalias
Sirve para eliminar un alias existente.

ln
Comando para crear enlaces a archivos. Hay enlaces dos tipos de enlaces: duros y simbólicos. El enlace duro es un duplicado del archivo al que enlaza pero con otro nombre. Comparte inodo (estructura de datos que conserva cada archivo) con el original por lo que no pueden crearse en particiones o unidades distintas. El enlace simbólico funciona como un acceso directo de Windows, tenga o no el mismo nombre. Pueden crearse al margen de la unidad o partición donde se encuentren.
ln archivo1 archivo2: crea el enlace duro archivo2 a partir de archivo1.
ln -s archivo1 archivo2: crea el enlace simbólico archivo2 a partir de archivo1.
stat
Comando que muestra una serie de datos precisos acerca de un archivo o un directorio como nombre, tamaño, bloques que ocupa, tipo de archivo, inodo, enlaces, ID, GUID, propietario, grupos y fechas de acceso y modificación.

file
Comando simple que nos informa de si un objeto es un directorio o un archivo, y de qué tipo si es lo segundo.

cmp
Compara dos archivos y nos dice si son o no distintos. Nos informa en qué número de línea está la diferencia.

diff
Compara dos archivos línea a línea y nos dice las diferencias, algo que resulta más útil cuando se trata de archivos de texto.

wc
Cuenta las líneas, palabras y caracteres de un archivo.
wc -c: muestra solo el número de caracteres.
wc -w: muestra solo el número de palabras.
wc -l: muestra solo el número de líneas.
alien
Este comando no siempre viene por defecto en nuestra distribución por lo que, en tal caso, hay que instalarlo si lo queremos usar. Sirve para convertir paquetes de software de, entre otros, formato .deb (Debian), .rpm (Red Hat) y .tar.gz (Slackware).
alien -d archivo.rpm/tar.gz: para generar un paquete .deb a partir de un .rpm o un .tar.gz. (opción por defecto).
alien -t archivo.deb/rpm: para generar un paquete .tar.gz a partir de un .deb o un .rpm.
alien -r archivo.deb/tar.gz: para generar un paquete .rpm a partir de un .deb o un .tar.gz.
Nuevamente les recuerdo que solo una pequeña muestra de las opciones existentes son las mostradas aquí. Acudan a la ayuda del terminal para recabar más información.

Y como hemos hablado del comando alien, nada más apropiado que evocar el trailer original de 1979 de la mítica película de Ridley Scott.


jueves, 7 de noviembre de 2013

Obtener información del sistema

Resto de entradas con intenciones didácticas en la etiqueta Aprendizaje.

Hay ocasiones en que es útil o necesario conocer determinados aspectos de nuestra máquina, ya sean detalles técnicos (modelo de tarjeta de red, p.e.) o eminentemente prácticos (espacio libre en disco). En esta entrada vamos a contemplar comandos para terminal que nos van a proporcionar este tipo de información.

arch
Comando que muestra la arquitectura del PC (el procesador). En mi caso el dato obtenido es i686, que se refiere al modelo Pentium PRO o Pentium II de Intel.

df
Comando para comprobar el espacio libre en disco duro (en bloques).
df -h: se muestra la misma información pero en unidades estándar (megas, gigas...)
top
Sirve para visualizar los procesos en ejecución en tiempo real.

free
Muestra la cantidad de memoria libre y usada que tenemos.

uname
Nos sirve para conocer la versión del kernel que tenemos instalada.
uname -a: visualiza toda la información que proporciona este comando de una sola vez.
dmidecode
Herramienta que permite conocer a fondo el hardware que compone nuestro equipo, ofreciendo información acerca del fabricante del sistema, versión del BIOS, memorias, procesador y mucha otra. Este comando valdría para una sola entrada por sí solo.

lshw
Similar al anterior, ofrece un listado de especificaciones de hardware.

hostname
Muestra o establece el nombre de la máquina.
hostame [nuevo_hostname]: para establecer un nuevo hostname (solo para la sesión actual). Hablé de ello aquí.
ifconfig
Para ver los interfaces de red instalados.

iwconfig
Para ver los adaptadores de red inalámbrica (wi-fi) instalados.

lspci
Para listar los componentes instalados tipo PCI (Peripheal Component Interconnect) como tarjetas de red, de sonido o de TV.

dmesg
Lista el búffer de mensajes del kernel relativos al arranque del sistema, depuración de aplicaciones o funcionamiento del hardware.

iwlist
Obtiene información de la red inalámbrica (wi-fi)
iwlist wlan0: informa con detalle sobre las distintas redes wi-fi detectadas por la interfaz wlan0.
lshal
Ofrece información diversa sobre el hardware y el software.

lscpu
Informa sobre la arquitectura de la CPU.

lsusb
Para ver los buses y los dispositivos USB instalados.

date
Para visualizar y cambiar la fecha y la hora del sistema.
date -d 06/15/13: cambia la fecha a mes 06, día 15, año 2013.
date -s 18:21:45:  cambia la hora a las 18 horas, 21 minutos y 45 segundos.
history
Comando que lista los últimos comandos utilizados por el usuario (por defecto, los últimos 500). Cada línea de este historial recibe un número.
$ !264: ejecuta el comando correspondiente a la línea 264 del historial de comandos.
history 5: lista los últimos 5 comandos utilizados.
history c: limpia el historial de comandos.
HISTSIZE: variable ubicada en el archivo oculto /home/usuario/.bashrc donde se establece su valor (por defecto, 500). Aquí hable de las formas de cambiar el valor de una variable.
Si antecedemos un comando con un espacio no se guarda en el historial. 
Vuelvo a advertir: aquí solo dejo constancia de algunas de las opciones (y solo en determinados casos) de que disponen los comandos. Acudan a la ayuda de man, a --help (ya saben como funciona) y a Google para encontrar más información.

Hemos hablado de como obtener información del sistema, y de golpear el sistema hablaban los legendarios Yes en esta interpretación en vivo del tema "Shock to the system" allá por 1991.



domingo, 3 de noviembre de 2013

VirtualBox sin puertos USB: solucionado

Después de cargarme el programa de arranque he optado por renovarlo todo e instalar Debian 7.2, nuevamente con GNOME como entorno de escritorio, lo cual es todo un alivio. Como novedad en esta ocasión decidí he decidido que usaré Windows a través de una máquina virtual dentro de Debian, así que instalé VirtualBox desde la línea de comandos. Una vez instalada designé Windows 7 (en mi caso, la Home Basic a 32 bits) como sistema anidado y todo fue bien salvo, como diría Rajoy, por alguna cosa: los puertos USB.

Como no me funcionaban lo primero que hice fue instalar las Guest Additions que encontraremos en el menú Dispositivos de la ventana de nuestro Windows virtual. Como aún así me seguían sin funcionar (fallo al acceder el subsistema USB) hice lo que todo buen internauta debe hacer en estos casos: navegar por la red en busca de la solución. Y (casi) nunca falla.

Abrimos la terminal y tecleamos:

paco@paco-pc:~/$ sudo nano /etc/fstab

Es decir, editamos con el editor de texto nano el fichero fstab situado en el directorio /etc. En este archivo encontramos la lista de discos y particiones disponibles. Lo que le añadiremos será lo siguiente:

#usbfs
none /proc/bus/usb usbfs devgid=46,devmode=664 0 0

Pulsamos Ctrl + o para guardar cambios y Ctrl + x para salir. A continuación tecleamos lo siguiente:

paco@paco-pc:~/$ mount -a

Con esto último lo que hacemos es montar todos los dispositivos que tenemos especificados en el fichero /etc/fstab, justo el que acabamos de modificar. Reiniciamos la máquina virtual y ahí están los dispositivos USB, listos para ser usados.

Y como hemos hablado de VirtualBox, vamos con "Man in a box", tema de 1990 a cargo de la banda de rock norteamericana Alice In Chains.