Raspberry Pi® a fondo para desarrolladores

Text
0
Kritiken
Leseprobe
Als gelesen kennzeichnen
Wie Sie das Buch nach dem Kauf lesen
Schriftart:Kleiner AaGrößer Aa

pi@erpi /var/log $ sudo sh -c "cat /dev/null > dpkg.log"

La llamada sh -c ejecuta todo el comando incluido en las comillas con permisos de superusuario. Esto es obligatorio porque, en el comando sudo cat /dev/null > dpkg.log, sudo por sí solo no efectúa la redirección de la salida >, sino que esta se intenta llevar a cabo como el usuario pi y, por tanto, falla porque sus permisos son insuficientes. Este es el problema con la redirección que presenta sudo, al que nos referimos anteriormente en el capítulo.

El comando lsblk (list block devices, listar dispositivos de bloques) presenta una lista concisa, estructurada en forma de árbol, con dispositivos tales como tarjetas SD, lápices de memoria USB y lectores de tarjetas (si los hubiera) conectados al RPi. Como se muestra en la salida siguiente, podemos ver que mmcblk0 (la tarjeta SD de arranque) se divide en dos particiones: p1, fijada a /boot, y p2, fijada a la raíz del sistema de archivos /. En este ejemplo, hay un lector USB para tarjetas micro-SD con una tarjeta de 32 GB (véase la figura 1-8(b)) conectado a uno de los puertos USB. Se muestra como el dispositivo de bloques sda con una sola partición, sda1:

pi@erpi ~ $ lsblk

NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT

sda 8:0 1 29.8G 0 disk

└─sda1 8:1 1 29.8G 0 part

mmcblk0 179:0 0 14.9G 0 disk

├─mmcblk0p1 179:1 0 56M 0 part /boot

└─mmcblk0p2 179:2 0 14.8G 0 part /

Claramente, los puertos USB sirven para conectar almacenamiento adicional, lo que resulta útil si capturamos datos de vídeo y la capacidad de la tarjeta

SD del sistema no es suficiente. Podemos probar el rendimiento de las tarjetas SD para asegurarnos de que se ajustan a las necesidades de nuestras aplicaciones mediante el ejemplo de la página siguiente.

Utilizar el comando mount sin argumentos nos facilita más información del sistema de archivos en el RPi.

pi@erpi ~ $ mount

/dev/mmcblk0p2 on / type ext4 (rw,noatime,data=ordered)

sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)

proc on /proc type proc (rw,relatime) ...

Como ya vimos, el sistema de archivos se organiza como un árbol único fijado al directorio raíz: /. Escribir cd / nos lleva directamente a la raíz del sistema. El comando mount se puede emplear para montar el sistema de archivos propio de un dispositivo de almacenamiento en este árbol. Los sistemas de archivos en dispositivos físicos separados se pueden montar en puntos definidos (named points) en ubicaciones del árbol. La tabla 3-5 describe algunos de los comandos del sistema de archivos que podemos utilizar para gestionarlo. Después se exponen dos ejemplos que demuestran cómo utilizar el comando mount para realizar importantes tareas de administración del sistema en el RPi.


Tabla 3-5: Comandos útiles para los sistemas de archivos.


ComandoDescripción
du -h /optdu -hs /opt/*du -hc *.jpgUtilización de disco: muestra el espacio ocupado por un árbol de directorios. Opciones: (-h) formato legible para las personas, (-s) resumen, (-c) total. El último comando encuentra el tamaño total del los archivos JPG en el directorio actual.
df -hMuestra el espacio del disco del sistema en formato legible (-h).
lsblkLista los dispositivos de bloques.
dd if=test.img of=/dev/sdXdd if=/dev/sdX of=test.imgdd convierte y copia un archivo, donde if es el archivo de entrada (input file) y of es el de salida (output file). Use este comando en Linux para escribir una imagen en una tarjeta SD. En Linux de escritorio, se suele utilizar así:sudo dd if=./RPi*.img of=/dev/sdXdonde /dev/sdX es el dispositivo de lectura/escritura de la tarjeta SD.
cat /proc/partitionsLista todas las particiones registradas.
mkfs /dev/sdXCrea un sistema de archivos Linux. También mkfs.ext4, mkfs.vfat. Se debe usar con precaución porque destruye todos los datos del dispositivo. ¡Téngalo presente!
fdisk -lObserve que fdisk se puede usar para gestionar discos, crear y eliminar particiones, etc. El comando fdisk -l muestra todas las particiones existentes.
badblocks /dev/mmcblkXLocaliza sectores erróneos en la tarjeta SD. Las tarjetas SD incorporan circuitos para nivelación de desgaste. Si se presentan errores, es hora de adquirir una tarjeta nueva. Es mejor no grabarlos con fsck. Ejecutamos este comando con privilegios de root, siempre teniendo en cuenta que tarda un tiempo en completarse.
mount /media/storeMonta una partición si aparece en /etc/fstab.
umount /media/storeDesmonta una partición. Se nos informa antes si hay algún archivo abierto en esta partición.
sudo apt install treetree ~/exploringrpiInstalamos el comando tree y lo utilizamos para mostrar el repositorio de código de este libro con estructura de árbol de directorios.



Los comandos find y whereis

El comando find resulta útil para buscar un archivo concreto en una estructura de directorios. Tiene un alcance enormemente amplio. Escriba man find para obtener un listado completo de las opciones. Por ejemplo, utilice la llamada siguiente para encontrar el archivo de cabecera C++ iostream en el sistema de archivos RPi; usar sudo evita problemas con los permisos de acceso:

pi@erpi / $ sudo find . -name iostream*

./usr/include/c++/4.9/iostream

./usr/include/c++/4.6/iostream

Usar -iname en lugar de name no discrimina mayúsculas y minúsculas en la búsqueda.

En el ejemplo siguiente se buscan los archivos en el directorio /home que hayan sido modificados en las últimas 24 y antes de las últimas 24 horas, respectivamente:

pi@erpi ~ $ echo "RPiTest File" >> new.txt

pi@erpi ~ $ sudo find /home -mtime -1

/home/pi

/home/pi/.bash_history

/home/pi/new.txt

pi@erpi ~ $ sudo find /home -mtime +1

/home/pi/.profile

/home/pi/.bashrc ...

Otra posibilidad es utilizar las opciones momento de acceso (-atime), tamaño (-size), propietario (-user), grupo (-group) y permiso (-perm).

NOTA Use el comando grep para buscar en un directorio de forma recursiva archivos que contengan una cadena de texto concreta, donde -r especifica que la búsqueda será recursiva, -n muestra el número de línea de la ubicación y -e viene seguido de un patrón de búsqueda:

pi@erpi ~ $ sudo grep -rn /home -e "RPiTest"

/home/pi/new.txt:1:RPiTest File

Para consultar más opciones, utilice man grep.

El comando whereis es distinto en el sentido de que puede buscar binarios ejecutables, código fuente y páginas de manual (man pages) de un programa concreto:

pi@erpi ~ $ whereis find

find: /usr/bin/find /usr/share/man/man1/find.1.gz

En este caso, los comandos binarios están en /usr/bin y la página de manual está en /usr/share/man/man1 (almacenada en formato gzip para ahorrar espacio).

Los comandos more y less

El comando more (más, en inglés) ya se ha utilizado varias veces, y seguramente el lector habrá ya deducido para qué sirve. Nos permite ver un archivo grande, o una corriente de salida (output stream) muy larga, página a página. Así pues, para ver un archivo largo podemos escribir more filename. Por ejemplo, el archivo de log /var/log/dmesg contiene todos los mensajes de salida del núcleo. Podemos revisar el archivo página a página con el comando more /var/log/dmesg. Sin embargo, si queremos que la información en la pantalla sea concisa, podemos utilizar el valor -5 para que solo se muestren cinco líneas en cada página.

pi@erpi ~ $ more -5 /var/log/dmesg

[ 0.000000] Booting Linux on physical CPU 0xf00

[ 0.000000] Initializing cgroup subsys cpu

[ 0.000000] Initializing cgroup subsys cpuacct

[ 0.000000] Linux version 3.18.11-v7+ (dc4@dc4-XPS13-9333)(gcc version 4.8.3

20140303 (prerelease)(crosstool-NG linaro-1.13.1+bzr2650-Linaro GCC 2014.03)

--More--(2%)

Con la barra espaciadora pasamos las páginas y pulsando Q (Quit) salimos del archivo. Existe un comando, less (menos, en inglés), que resulta aún más potente:

pi@erpi ~ $ less /var/log/dmesg

El comando less nos proporciona una vista completamente interactiva que podemos manejar desde el teclado. Tiene, no obstante, demasiadas opciones como para listarlas aquí. Por ejemplo, podemos utilizar las teclas de cursor para movernos arriba y abajo, pasar de página con la barra espaciadora, buscar una cadena de texto escribiendo / (por ejemplo: /usb, para encontrar mensajes relacionados con dispositivos USB) y, luego, pulsar la tecla N para ir a la siguiente ocurrencia de la cadena buscada, o bien Mayús+N para ir a la ocurrencia anterior.

 

La fiabilidad de los sistemas de archivos en las tarjetas SD

Uno de los puntos críticos del RPi es su tarjeta SD, o como se la conoce más genéricamente, su MMC (MultiMedia Card, tarjeta multimedia). La memoria flash NAND, como la de las MMC, ofrece gran espacio de almacenamiento con bajo coste, pero presenta una cierta tendencia al desgaste que puede resultar en errores del sistema de archivos.

La amplia capacidad de las MMC se debe en gran medida al desarrollo de las memorias MLC (Multi-Level Cell) o de celda multinivel. A diferencia de la memoria SLC (Single-Level Cell) o de celda mononivel, las MLC son capaces de guardar más de 1 bit en una sola celda de memoria. Los altos niveles de voltaje necesarios para borrar una celda perjudican a las celdas adyacentes, así que la memoria flash NAND se borra en bloques de 1 a 4 KB. Con el paso del tiempo, el proceso de escritura en la memoria flash NAND hace que los electrones queden atrapados y que se reduzca la diferencia de conductividad entre los estados "guardado" y "borrado" (disponible) del sustrato semiconductor de la memoria. (El lector interesado podrá encontrar un análisis (en inglés) más profundo de las diferencias entre SLC y MLC para aplicaciones de elevada fiabilidad en la dirección web tiny.cc/erpi305.) Las MLC utilizan niveles de carga diferentes y voltajes superiores para almacenar más estados en cada celda individual. Los productos comerciales MLC suelen ofrecer entre 4 y 16 estados por celda. Como las SLC solo guardan un estado, gozan de ventaja en cuanto a fiabilidad, con unos 60.000 a 100.000 ciclos de borrado/escritura frente a los 10.000 que suelen ofrecer las memorias flash MLC. Las tarjetas MMC son perfectas para un uso cotidiano en aplicaciones como fotografía digital, donde 10.000 ciclos de escritura/borrado deberían garantizar más de 25 años de vida útil (con un ciclo de escritura/borrado de la tarjeta completa cada día, lo que tampoco suele ocurrir).

Sin embargo, los dispositivos Linux empotrados realizan constantemente tareas de escritura en sus MMC, como el registro de eventos del sistema en /var/log. Conque el RPi escriba en un archivo de log unas 20 veces diarias, la vida útil de una tarjeta SD sería de unos ocho meses. Tales cifras son conservadoras, no obstante, y gracias a la tecnología ya mencionada con algoritmos de nivelación de desgaste (wear leveling algorithms) la vida útil puede ser mucho más larga. Las MMC usan los algoritmos de nivelación de desgaste durante la escritura de datos para asegurar que las reescrituras se distribuyen uniformemente en todo el espacio de almacenamiento. De este modo se logran evitar los fallos de sistema de Linux ocasionados por una excesiva concentración de modificaciones, tales como cambios en los mismos archivos de log.

En el caso de nuestro RPi, debemos asegurarnos de adquirir una tarjeta SD de la mejor calidad posible, y mejor si es de una marca reconocida. Además, debe ser de gran capacidad. La razón es sencilla: cuanto más espacio quede sin usar en la SD, mejor funcionarán los algoritmos de nivelación de desgaste, siquiera por motivos físicos. Como nota al margen, decir que otras placas con Linux empotrado, como la BeagleBone Black, utilizan almacenamiento eMMC (embedded MMC, MMC empotrado); básicamente, una MMC en un chip soldado en la placa. Estas memorias eMMC suelen ser también MLC y ofrecen una fiabilidad análoga a la de las tarjetas SD. Sin embargo, una de sus ventajas es que el fabricante posee el control sobre la calidad y las especificaciones de la eMMC que desea incluir en su placa. Por último, la mayoría de los discos duros de estado sólido SSD (Solid State Disk) también incorporan tecnología MLC, mientras que los más caros y profesionales emplean la (más fiable) SLC.

Para aplicaciones en el RPi que requieran mayor fiabilidad, se puede utilizar un sistema de archivos basado en RAM (tmpfs) en los directorios /tmp y /var/cache, y para los archivos de log, especialmente /var/log/apt. Lograremos esto editando el archivo /etc/fstab para que los directorios necesarios se monten en memoria. Por ejemplo, si tenemos procesos que requieran compartir datos de archivos entre ellos para intercambiar datos, podríamos usar el directorio /tmp como sistema de archivos RAM (tmpfs) editando el archivo /etc/fstab del siguiente modo:

pi@erpi /etc $ sudo nano fstab

pi@erpi /etc $ more fstab

proc /proc proc defaults 0 0

/dev/mmcblk0p1 /boot vfat defaults 0 2

/dev/mmcblk0p2 / ext4 defaults,noatime 0 1

tempfs /tmp tmpfs size=100M 0 0

Seguidamente, aplicaríamos estos ajustes utilizando el comando mount.

pi@erpi /etc $ sudo mount -a

Y, luego, comprobamos que dichos ajustes se han añadido a la configuración:

pi@erpi /etc $ mount

...

tempfs on /tmp type tmpfs (rw,relatime,size=102400k)

El directorio raíz se monta de forma predeterminada con el atributo noatime activo, lo cual reduce drásticamente el número de accesos de escritura e incrementa el rendimiento de E/S, como ya vimos anteriormente en el capítulo. Siempre que sea posible debemos aplicar este atributo a todos los dispositivos de almacenamiento de estado sólido, como lápices USB, pero no es necesario para el almacenamiento basado en RAM.

Recuerde que cualquier dato que escribamos en un sistema de archivos temporal, tempfs, se perderá al reiniciar. Así pues, si utilizamos un tmpfs para /var/log, cualquier error del sistema que haga colgarse a la tarjeta no será visible en el reinicio. Podemos comprobarlo creando un archivo en el directorio /tmp con la configuración anterior y reiniciando acto seguido.

La asignación real de la RAM crece y mengua dependiendo del uso que el archivo haga del disco tmpfs. Así pues, podemos ser razonablemente generosos con la asignación de memoria. Por ejemplo, con los 100 MB del directorio /tmp montados en tmpfs:

pi@erpi /tmp $ cat /proc/meminfo | grep MemFree:

MemFree: 824368 kB

pi@erpi /tmp $ fallocate -l 75000000 test.txt

pi@erpi /tmp $ ls -l test.txt

-rw-r--r-- 1 pi pi 75000000 Jul 17 00:04 test.txt

pi@erpi /tmp $ cat /proc/meminfo | grep MemFree:

MemFree: 750788 kB

Ciertas distribuciones para el RPi emplean un sistema de archivos de solo lectura para mejorar la vida útil de la tarjeta SD, así como la estabilidad del propio sistema. Como ejemplo citaremos OpenELEC y el sistema de archivos comprimido SquashFS. No obstante, esto requiere mucho esfuerzo y no resulta práctico para el tipo de trabajo de prototipado que exponemos en este libro. Sin embargo, parece conveniente no perder esto de vista porque nos puede venir muy bien para el despliegue final del proyecto, donde la estabilidad del sistema resulta de extrema importancia.

Comandos de Linux

Cuando trabajamos en el terminal de Linux y escribimos comandos como date, el resultado de los mismos se envía a la "salida estándar" (standard output). Y vemos dicho resultado en nuestra ventana de terminal.

Redirección de entrada y salida (>, >> y <)

Es posible redirigir la salida a un archivo usando los operadores de redirección > y >>. El símbolo >> se usó anteriormente en este capítulo para añadir texto a archivos temporales. El operador > se puede emplear para enviar la salida a un nuevo archivo. Por ejemplo:

pi@erpi ~ $ cd /tmp

pi@erpi /tmp $ date > a.txt

pi@erpi /tmp $ more a.txt

Sat 20 Jun 12:59:43 UTC 2015

pi@erpi /tmp $ date > a.txt

pi@erpi /tmp $ more a.txt

Sat 20 Jun 12:59:57 UTC 2015

El operador >> manifiesta nuestro deseo de añadir contenido al archivo. El ejemplo siguiente ilustra el uso del operador >> con el nuevo archivo a.txt:

pi@erpi /tmp $ date >> a.txt

pi@erpi /tmp $ more a.txt

Sat 20 Jun 12:59:57 UTC 2015

Sat 20 Jun 13:00:17 UTC 2015

La salida estándar usando el símbolo < funciona de forma muy parecida. La inclusión de -e facilita el análisis de los caracteres de escape, como el de retorno (\n), que sitúa cada especie animal en una nueva línea:

pi@erpi /tmp $ echo -e "dog\ncat\nyak\ncow" > animals.txt

pi@erpi /tmp $ sort < animals.txt

cat

cow

dog

yak

Podemos combinar los operadores de redirección de entrada y de salida. Usando el archivo animals.txt podemos realizar operaciones como la siguiente:

pi@erpi /tmp $ sort < animals.txt > sorted.txt

pi@erpi /tmp $ more sorted.txt

cat

cow

dog

yak

Tuberías (| y tee)

Dicho simplemente: las tuberías (pipes) ,|, nos permiten conectar comandos de Linux. Al igual que redirigimos la salida a un archivo, podemos redirigir la salida de un comando para que sirva de entrada a otro comando. Por ejemplo, para listar el directorio raíz desde cualquier lugar del sistema y enviar (o "canalizar" como por una "tubería", pipe) la salida al comando sort, donde se colocará en orden inverso (reverse) merced al parámetro -r, escribiremos lo siguiente:

pi@erpi ~ $ ls / | sort -r

var

usr

...

bin

Podemos identificar qué instalaciones del usuario en el directorio /opt ocupan más espacio en disco: du nos facilita el tamaño de disco usado. Pasar el argumento -d1 significa que solo listaremos los tamaños 1 nivel por debajo del nivel del directorio actual, mientras que -h hace que los valores se muestren en formato legible. Podemos canalizar esta salida hacia el comando de filtro sort para realizar un ordenamiento numérico en orden inverso, es decir, colocando el más grande en el lugar más alto. De este modo, el comando es:

pi@erpi ~ $ du -d1 -h /opt | sort -nr

113M /opt

69M /opt/sonic-pi

41M /opt/vc

4.4M /opt/minecraft-pi

Otra herramienta útil, tee, nos permite al mismo tiempo redirigir una salida a un archivo y pasarlo al siguiente comando en la tubería; por ejemplo, guardar y ver. Usando el ejemplo anterior, si deseamos enviar la salida sin ordenar del comando du a un archivo, y mostrar una salida ordenada por la consola, escribiremos:

pi@erpi ~ $ du -d1 -h /opt | tee /tmp/unsorted.txt | sort -nr

113M /opt

69M /opt/sonic-pi

41M /opt/vc

4.4M /opt/minecraft-pi

pi@erpi ~ $ more /tmp/unsorted.txt

4.4M /opt/minecraft-pi

69M /opt/sonic-pi

41M /opt/vc

113M /opt

Asimismo, podemos utilizar tee para escribir la salida de varios archivos:

pi@erpi ~ $ du -d1 -h /opt | tee /tmp/1.txt /tmp/2.txt /tmp/3.txt

Comandos de filtro (de sort a xargs)

Cada uno de los comandos de filtro ofrece una función útil:

❏sort: este comando presenta varias opciones, por ejemplo: -r aplica un orden inverso, -f ignora mayúsculas y minúsculas, -d ordena siguiendo un diccionario e ignora la puntuación, -n ordenación numérica, -b ignora espacios en blanco, -i ignora los caracteres de control, -u muestra las líneas duplicadas una sola vez y -m une varias entradas en una sola salida.

❏wc (contar palabras): calcula el número de palabras, líneas o caracteres en una corriente (stream). Por ejemplo:

pi@erpi /tmp $ wc < animals.txt

4 4 16

Indica que hay 4 líneas, 4 palabras y 16 caracteres. Podemos seleccionar los valores independientemente usando -l para contar líneas, -w palabras, o -m caracteres, mientras que con -c imprimimos la cuenta de bytes (que en este caso también son 16).

❏head: muestra las primeras líneas de la salida, lo que resulta útil si tenemos un archivo o corriente de información y deseamos examinar solo las primeras líneas. De manera predeterminada, muestra las primeras diez líneas. Podemos especificar el número de líneas con la opción -n. Por ejemplo, para obtener las dos primeras líneas de salida del comando dmesg (display message, mostrar mensaje, o driver message, mensaje del controlador), que muestra el buffer de mensajes del núcleo, escribimos:

pi@erpi ~ $ dmesg | head -n2

[ 0.000000] Booting Linux on physical CPU 0xf00

[ 0.000000] Initializing cgroup subsys cpu

❏tail: funciona igual que head salvo porque muestra las últimas líneas de un archivo o corriente de datos. Usándolo en combinación con dmesg aporta unas salidas muy útiles, por ejemplo:

pi@erpi ~ $ dmesg | tail -n2

 

[ 8.896654] smsc95xx 1-1.1:1.0 eth0:link up,100Mbps,full-duplex...

[ 9.340019] Adding 102396k swap on /var/swap.

❏grep: analiza líneas utilizando texto y expresiones regulares. Podemos utilizar este comando para filtrar la salida con distintas opciones: -i ignora mayúsculas y minúsculas, -m 5 se detiene tras dar con cinco ocurrencias, -q realiza la búsqueda "en silencio" y la detiene y devuelve el estado 0 si encuentra alguna ocurrencia, -e para especificar algún patrón, -c muestra una cuenta de ocurrencias, -o solo muestra el texto que se corresponde con la búsqueda y -l muestra el nombre del archivo que contenga el texto buscado. Por ejemplo, el siguiente caso examina la salida dmesg hasta dar con las primeras tres ocurrencias de la cadena usb, usando el parámetro -i para ignorar mayúsculas y minúsculas:

pi@erpi ~ $ dmesg | grep -i -m3 usb

[ 1.280089] usbcore: registered new interface driver usbfs

[ 1.285762] usbcore: registered new interface driver hub

[ 1.291220] usbcore: registered new device driver usb

Las tuberías se pueden combinar. Por ejemplo, obtenemos exactamente la misma salida utilizando head y mostrando únicamente las tres primeras líneas de la salida de grep:

pi@erpi ~ $ dmesg | grep -i usb | head -n3

[ 1.280089] usbcore: registered new interface driver usbfs

[ 1.285762] usbcore: registered new interface driver hub

[ 1.291220] usbcore: registered new device driver usb

❏xargs: nos permite construir una lista de argumentos que utilizaremos para llamar a otro comando o herramienta. En el ejemplo siguiente, el archivo de texto args.txt, que contiene tres cadenas, se utiliza para crear tres nuevos archivos. La salida de cat se canaliza a xargs, donde pasa las tres cadenas como argumentos del comando touch, que crea tres nuevos archivos: a.txt, b.txt y c.txt:

pi@erpi /tmp $ echo "a.txt b.txt c.txt" > args.txt

pi@erpi /tmp $ cat args.txt | xargs touch

pi@erpi /tmp $ ls

args.txt a.txt b.txt c.txt

Existen más comandos de filtro muy útiles, entre ellos: awk, que programa cualquier tipo de filtro; fmt, que da formato al texto; uniq, que encuentra líneas únicas, y sed, para manipular una corriente de datos. Estos comandos van mucho más allá del ámbito de este libro. Por ejemplo, awk es un lenguaje de programación completo en sí mismo. La tabla 3-6 describe comandos útiles para emplear con tuberías y ofrece buenas ideas para usarlos.

Tabla 3-6: Comandos útiles para usar con tuberías


ComandoDescripción
apt list --installed | grep cameraLista los paquetes instalados y busca uno que contenga la cadena de caracteres "camera". Cada comando en esta tabla se escribe en una sola línea.
ls -lt | headMuestra los archivos del directorio actual por orden de antigüedad.
cat urls.txt | xargs wgetDescarga los archivos listados en URL dentro de un archivo de texto urls.txt.
dmesg | grep -c usbCuenta el número de veces que aparece la cadena usb en la salida de dmesg.
find . -name "*.mp3" | grep -vi "effects" > /tmp/playlist.txtBusca en el RPi (es decir, se ejecuta desde /con sudo) archivos mp3, ignorando cualquier archivo de efectos de sonido, para crear una lista de reproducción en /tmp.

Los comandos echo y cat

El comando echo se limita a reproducir (como el eco) una cadena de texto, la salida de un comando o un valor determinado por la salida estándar. Veamos unos ejemplos:

pi@erpi /tmp $ echo 'hello'

hello

pi@erpi /tmp $ echo "Today's date is $(date)"

Today's date is Sat 20 Jun 14:31:21 UTC 2015

pi@erpi /tmp $ echo $PATH

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

En el primer caso se reproduce una cadena de texto sencilla. En el segundo caso, las comillas," ", representan un comando emitido dentro de la llamada echo, y en el último caso se repite (echo) la variable de entorno PATH.

El comando echo nos permite también contemplar el estado de la salida de un comando usando $?. Por ejemplo:

pi@erpi ~ $ ls /tmp

args.txt a.txt b.txt c.txt playlist playlist.txt

pi@erpi ~ $ echo $?

0

pi@erpi ~ $ ls /nosuchdirectory

ls: cannot access /nosuchdirectory: No such file or directory

pi@erpi ~ $ echo $?

2

Claramente, el estado de salida para ls es 0 para una llamada con éxito, y 2 para un argumento no válido. Esto puede resultar útil cuando escribimos scripts y programas propios que devuelven un valor desde la función main().

El comando cat (concatenation, concatenar) nos facilita la unión de dos archivos desde la línea de comandos. El ejemplo siguiente usa echo para crear dos archivos, a.txt y b.txt. Luego, cat los concatena para crear uno nuevo, c.txt. Debemos utilizar el parámetro -e si queremos habilitar la interpretación de los caracteres de escape en la cadena que se pase a echo

pi@erpi ~ $ cd /tmp

pi@erpi /tmp $ echo "hello" > a.txt

pi@erpi /tmp $ echo -e "from\nthe\nRPi" > b.txt

pi@erpi /tmp $ cat a.txt b.txt > c.txt

pi@erpi /tmp $ more c.txt

hello

from

the

RPi

diff

El comando diff nos facilita la búsqueda de diferencias entre dos archivos. Ofrece una salida básica:

pi@erpi /tmp $ echo -e "dog\ncat\nbird" > list1.txt

pi@erpi /tmp $ echo -e "dog\ncow\nbird" > list2.txt

pi@erpi /tmp $ diff list1.txt list2.txt

2c2

< cat

---

> cow

El valor 2c2 en la salida indica que la línea 2 del primer archivo ha cambiado (changed) a la línea 2 del segundo, y que el cambio es cat a cow. El carácter a significa añadido o anexado (appended), y el d, borrado (deleted). Para una comparación lado a lado podemos usar lo siguiente:

pi@erpi /tmp $ diff -y -W70 list1.txt list2.txt

dog dog

cat | cow

bird bird

donde -y habilita la vista lado a lado y -W70 establece la anchura del texto que se muestra en la pantalla en 70 caracteres (columnas).

Si queremos utilizar una vista para las diferencias entre dos archivos más intuitiva, pero exigente, podemos usar el comando vimdiff (instalado mediante sudo apt install vim), que muestra una comparación lado a lado de los archivos usando el editor de texto vim (Vi IMproved). Escribimos vimdiff list1.txt list2.txt y usamos la secuencia de teclas vim: Escape : q ! dos veces para salir, o bien Escape : w q para guardar los cambios y salir. Vim requiere mucha práctica para dominar las secuencias de teclas.

tar

El comando tar es una utilidad para combinar archivos y directorios en un solo archivo (como un archivo zip descomprimido). Este archivo puede ser comprimido para ahorrar espacio. Para archivar y comprimir directorios o archivos, como /tmp, escribimos:

pi@erpi ~ $ tar cvfz tmp_backup.tar.gz /tmp

donde c significa nuevo archivo, v mostrar (verbose) el listado de archivos, z comprimir con gzip y f indica que lo que sigue es el nombre de archivo. También podemos encontrarnos la extensión .tar.gz representada como .tgz. Véase la tabla 3-7 para más ejemplos.

Tabla 3-7: Comandos útiles de tar.


ComandoDescripción
tar cvfz name.tar.gz /tmpComprimir en formato gzip.
tar cvfj name.tar.bz2 /tmpComprimir en formato bzip2, que generalmente tarda más pero genera archivos más pequeños. Introduzca cada comando de esta tabla en una sola línea.
tar cvfJ name.tar.xz /tmpComprimir en formato xz (usado en los archivos de paquete .deb).
tar xvf name.tar.*Descomprimir archivo comprimido (x indica extraer). Detectará automáticamente el tipo de compresión, como gzip o bz2.
tar xvf name.tar.* /dir/fileExtrae un archivo de otro. También funciona para un solo directorio.
tar rvf name.tar filenameAñade otro archivo.
tar cfz name-$(date +%m%d%y).tar.gz /dir/filenameCrea un archivo con la fecha actual, opción útil para los scripts y para jobs de copia de respaldo. Observe que debe hacer un espacio entre date y +%m%d%y.

md5sum

El comando md5sum nos permite verificar el código hash que garantiza la integridad de los archivos y que no se han corrompido ni maliciosa ni accidentalmente. En el ejemplo siguiente descargamos la herramienta wavemon como paquete .deb, pero no la instalamos. El comando md5sum sirve para generar la suma de verificación (checksum) md5:

pi@erpi ~ $ sudo apt-get download wavemon

Get:1 http://mirrordirector.raspbian.org/raspbian/ jessie/main

wavemon armhf 0.7.6-2 [48.2 kB] Fetched 48.2 kB in 0s (71.4 kB/s)

pi@erpi ~ $ ls -l *.deb

-rw-r--r-- 1 root root 48248 Mar 28 2014 wavemon_0.7.6-2_armhf.deb

pi@erpi ~ $ md5sum wavemon_0.7.6-2_armhf.deb

1dffa011736e25b63a054f1515d18b3e wavemon_0.7.6-2_armhf.deb

Ahora podemos comprobar la suma de verificación obtenida frente a la oficial para asegurarnos de que tenemos un archivo válido. Desgraciadamente, puede resultar difícil encontrar las sumas de verificación de cada paquete en línea. Si tenemos instalado wavemon, las sumas de verificación estarán en /var/ lib/dpkg/info/wavemon.md5sums. Podemos instalar una utilidad en Debian llamada debsums para comprobar la integridad del archivo, así como de todas sus partes.

pi@erpi ~ $ sudo apt install debsums wavemon

pi@erpi ~ $ debsums wavemon_0.7.6-2_armhf.deb

/usr/bin/wavemon OK

/usr/share/doc/wavemon/AUTHORS OK

/usr/share/doc/wavemon/NEWS.gz OK

...

Si compilamos nuestros propios paquetes para distribuirlos, resultaría útil distribuir los archivos con la suma de verificación correspondiente para que los usuarios puedan comprobar su integridad. Existe una alternativa a md5sum ,sha256sum, que se puede utilizar del mismo modo.