Una parte importante de aprender a trabajar con Ubuntu, y con las distribuciones de Linux en general, implica ganar destreza en el trabajo en el entorno del shell. Mientras que los entornos gráficos de escritorio como GNOME incluidos en Linux proporcionan una interfaz amigable con el sistema operativo, en la práctica el entorno shell proporciona capacidades, flexibilidad y automatización mucho mayores que las que se pueden lograr utilizando herramientas gráficas de escritorio. El entorno shell también proporciona un medio para interactuar con el sistema operativo cuando un entorno de escritorio no está disponible; algo común cuando se trabaja con un sistema operativo basado en un servidor como Ubuntu o un sistema dañado que no arranca completamente.

El objetivo de este capítulo, por lo tanto, es proporcionar una visión general del entorno de shell por defecto en Ubuntu (específicamente el shell Bash).

1.1 ¿Qué es un Shell?

El shell es un entorno interactivo de interpretación de comandos dentro del cual los comandos pueden ser escritos en un prompt o introducidos en un archivo en forma de script y ejecutados. Los orígenes del shell se remontan a los primeros días del sistema operativo UNIX. De hecho, en los primeros días de Linux, antes de la introducción de los escritorios gráficos, el shell era la única forma de que un usuario interactuara con el sistema operativo.

A lo largo de los años se han desarrollado diversos entornos de shell. El primer shell ampliamente utilizado fue el shell Bourne, escrito por Stephen Bourne en los laboratorios Bell.

Otra de las primeras creaciones fue el shell C, que compartía algunas similitudes sintácticas con el lenguaje de programación C e introducía mejoras de usabilidad como la edición de la línea de comandos y el historial.

El intérprete de comandos Korn (desarrollado por David Korn en los Laboratorios Bell) se basa en características proporcionadas por el intérprete de comandos Bourne y el intérprete de comandos C.

El intérprete de comandos por defecto en Ubuntu es el intérprete de comandos Bash (abreviatura de Bourne Again SHell). Este intérprete de comandos, que comenzó su vida como una versión de código abierto del intérprete de comandos Bourne, fue desarrollado para el Proyecto GNU por Brian Fox y se basa en las características proporcionadas por el intérprete de comandos Bourne y el intérprete de comandos C.

1.2 Cómo acceder al intérprete de comandos

Desde el entorno de escritorio GNOME, se puede acceder al intérprete de comandos desde una ventana de Terminal seleccionando la opción Actividades en la barra superior, introduciendo Terminal en la barra de búsqueda y haciendo clic en el icono de Terminal.

Cuando se inicia la sesión de forma remota en un servidor de Ubuntu, por ejemplo utilizando SSH, el usuario también se presenta con un intérprete de comandos. Los detalles sobre el acceso a un servidor remoto utilizando SSH se cubrirán en el capítulo titulado «Configuración de la autenticación basada en clave SSH en Ubuntu». Cuando se arranca un sistema basado en un servidor en el que no se ha instalado un entorno de escritorio, se entra en el shell inmediatamente después de que el usuario complete el procedimiento de inicio de sesión en la terminal de la consola física o en la sesión de inicio de sesión remota.

1.3 Introducción de comandos en el prompt

Los comandos se introducen en el prompt del shell simplemente escribiendo el comando y pulsando la tecla Enter. Mientras que algunos comandos realizan tareas en silencio, la mayoría mostrará algún tipo de salida antes de volver al prompt. Por ejemplo, el comando ls se puede utilizar para mostrar los archivos y directorios en el directorio de trabajo actual:

$ ls

Escritorio Documentos Descargas Música Imágenes Plantillas Públicas Vídeos

Los comandos disponibles están incorporados en el propio shell, o residen en el sistema de archivos físico. La ubicación en el sistema de archivos de un comando puede ser identificada usando el comando which. Por ejemplo, para saber dónde reside el ejecutable ls en el sistema de archivos:

$ which ls alias ls='ls --color=auto' /usr/bin/ls

Está claro que el comando ls reside en el directorio /usr/bin. Observe también que se ha configurado un alias, un tema que se tratará más adelante en este capítulo. El uso del comando which para localizar la ruta de acceso a los comandos que están incorporados en el shell dará como resultado un mensaje indicando que no se puede encontrar el ejecutable. Por ejemplo, al intentar encontrar la ubicación del comando history (que en realidad está incorporado en el shell en lugar de existir como un ejecutable en el sistema de archivos) resultará en una salida similar a la siguiente:

$ which history/usr/bin/which: no history in (/home/demo/.local/bin:/home/demo/bin:/usr/share/Modules/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin)

1.4 Obtener información sobre un comando

Muchos de los comandos disponibles en el shell de Linux pueden parecer crípticos para empezar. Para encontrar información detallada sobre lo que hace un comando y cómo utilizarlo, utilice el comando man especificando el nombre del comando como argumento. Por ejemplo, para saber más sobre el comando pwd:

$ man pwd

Cuando se ejecuta el comando anterior, se muestra una descripción detallada del comando pwd. Muchos comandos también proporcionarán información adicional cuando se ejecutan con la opción de línea de comandos -help:

$ wc --help

1.5 Edición de la línea de comandos de Bash

Los primeros entornos de shell no proporcionaban ninguna forma de capacidad de edición de líneas. Esto significaba que si se detectaba un error al principio de una larga línea de comandos que se estaba escribiendo, había que borrar todos los caracteres siguientes, corregir el error y volver a introducir el resto del comando. Afortunadamente, Bash ofrece una amplia gama de opciones de edición de la línea de comandos, como se indica en la siguiente tabla:

Secuencia de teclas Acción
Ctrl-b o Flecha izquierda Mover el cursor hacia atrás una posición
Ctrl-f o Flecha derecha Mover el cursor hacia delante una posición
Borrar Borrar el carácter que se encuentra debajo del cursor
Retroceso Borrar el carácter a la izquierda del cursor
Ctrl-_ Deshacer el cambio anterior (puede repetirse para deshacer todos los cambios anteriores)
Ctrl-a Mover el cursor al inicio de la línea
Ctrl-e Mover el cursor al final de la línea
Meta-f o Esc y luego f Mover el cursor hacia adelante una palabra
Meta-b o Esc y luego b Mover el cursor hacia atrás una palabra
Ctrl-l Borrar la pantalla de todo excepto del comando actual
Ctrl-k Borrar hasta el final de la línea desde la posición actual del cursor
Meta-d o Esc entonces d Borrar al final de la palabra actual
Meta-DEL o Esc entonces DEL Borrar al principio de la palabra actual
Ctrl-w Borrar desde la posición actual del cursor hasta el espacio en blanco anterior

Tabla 9-1

1.6 Trabajar con el historial del shell

Además de las características de edición de la línea de comandos, el shell Bash también proporciona soporte para el historial de la línea de comandos. Se puede ver una lista de comandos ejecutados previamente utilizando el comando history:

$ history1ps2ls3ls –l /4ls5man pwd6man apropos

Además, se puede utilizar Ctrl-p (o flecha hacia arriba) y Ctrl-n (o flecha hacia abajo) para desplazarse hacia adelante y hacia atrás a través de los comandos introducidos previamente. Cuando aparezca el comando deseado del historial, pulse la tecla Enter para ejecutarlo.

Otra opción es introducir el carácter ‘!’ seguido de los primeros caracteres del comando que se va a repetir, seguido de la tecla Enter.

1.7 Abreviatura de nombre de archivo

Muchos comandos del shell toman uno o más nombres de archivo como argumentos. Por ejemplo, para mostrar el contenido de un archivo de texto llamado list.txt, el comando cat se utilizaría de la siguiente manera:

$ cat list.txt

De manera similar, el contenido de múltiples archivos de texto podría mostrarse especificando todos los nombres de archivo como argumentos:

$ cat list.txt list2.txt list3.txt list4.txt

En lugar de escribir cada nombre, se puede utilizar la coincidencia de patrones para especificar todos los archivos con nombres que coincidan con ciertos criterios. Por ejemplo, el carácter comodín «*» puede utilizarse para simplificar el ejemplo anterior:

$ cat *.txt

El comando anterior mostrará el contenido de todos los archivos que terminen con una extensión .txt. Esto podría restringirse a cualquier nombre de archivo que comience con list y termine en .txt:

$ cat list*.txt

Se pueden especificar coincidencias de un solo carácter utilizando el carácter ‘?’:

$ cat list?.txt

1.8 Completar el nombre de archivo y la ruta

En lugar de escribir un nombre de archivo o una ruta completos, o utilizar la coincidencia de patrones para reducir la cantidad de escritura, el shell proporciona la función de completar el nombre de archivo. Para utilizar la función de completar el nombre del archivo, simplemente introduzca los primeros caracteres del nombre del archivo o de la ruta y, a continuación, pulse la tecla Esc dos veces. El intérprete de comandos completará el nombre del archivo con el primer nombre de archivo o ruta del directorio que coincida con los caracteres introducidos. Para obtener una lista de posibles coincidencias, pulse Esc = después de introducir los primeros caracteres.

1.9 Redirección de entrada y salida

Como se ha mencionado anteriormente, muchos comandos del shell emiten información cuando se ejecutan. Por defecto esta salida va a un archivo de dispositivo llamado stdout que es esencialmente la ventana de terminal o consola en la que se ejecuta el shell. A la inversa, el shell toma la entrada de un archivo de dispositivo llamado stdin, que por defecto es el teclado.

La salida de un comando puede ser redirigida desde stdout a un archivo físico en el sistema de archivos usando el carácter ‘>’. Por ejemplo, para redirigir la salida de un comando ls a un archivo llamado files.txt, se requeriría el siguiente comando:

$ ls *.txt > files.txt

Al terminar, files.txt contendrá la lista de archivos en el directorio actual. Del mismo modo, el contenido de un archivo puede ser introducido en un comando en lugar de stdin. Por ejemplo, para redirigir el contenido de un archivo como entrada a un comando:

$ wc –l < files.txt

El comando anterior mostrará el número de líneas contenidas en el archivo files.txt.

Es importante tener en cuenta que el operador de redirección ‘>’ crea un nuevo archivo, o trunca un archivo existente cuando se utiliza. Para añadir a un archivo existente, utilice el operador ‘>>’:

$ ls *.dat >> files.txt

Además de la salida estándar, el shell también proporciona una salida de error estándar utilizando stderr. Mientras que la salida de un comando se dirige a stdout, cualquier mensaje de error generado por el comando se dirige a stderr. Esto significa que si stdout se dirige a un archivo, los mensajes de error seguirán apareciendo en el terminal. Este es generalmente el comportamiento deseado, aunque stderr también puede ser redirigido si se desea utilizando el operador ‘2>’:

$ ls dkjfnvkjdnf 2> errormsg

Al finalizar el comando, un error informando el hecho de que el archivo llamado dkjfnvkjdnf no pudo ser encontrado será contenido en el archivo errormsg.

Tanto stderr como stdout pueden ser redirigidos al mismo archivo usando el operador &>:

$ ls /etc dkjfnvkjdnf &amp;&gt; alloutput

Al finalizar la ejecución, el archivo alloutput contendrá tanto un listado del contenido del directorio /etc, como el mensaje de error asociado con el intento de listar un archivo inexistente.

1.10 Trabajando con Tuberías en el Shell Bash

Además de la redirección de E/S, el shell también permite que la salida de un comando sea canalizada directamente como entrada a otro comando. Una operación de tubería se logra colocando el carácter ‘|’ entre dos o más comandos en una línea de comandos. Por ejemplo, para contar el número de procesos que se ejecutan en un sistema, la salida del comando ps se puede canalizar a través del comando wc:

$ ps –ef | wc –l

No hay límite en el número de operaciones de canalización que se pueden realizar en una línea de comandos. Por ejemplo, para encontrar el número de líneas en un archivo que contienen el nombre Smith:

$ cat namesfile | grep Smith | wc –l

1.11 Configuración de alias

A medida que adquiera destreza con el entorno del shell es probable que se encuentre emitiendo frecuentemente comandos con los mismos argumentos. Por ejemplo, puede utilizar a menudo el comando ls con las opciones l y t:

$ ls –lt

Para reducir la cantidad de escritura que implica la emisión de un comando, es posible crear un alias que se asigna al comando y los argumentos. Por ejemplo, para crear un alias de forma que al introducir la letra l se ejecute el comando ls -lt, se utilizaría la siguiente sentencia:

$ alias l="ls –lt"

Al introducir l en el símbolo del sistema se ejecutará la sentencia original.

1.12 Variables de entorno

Las variables de entorno del shell proporcionan un almacenamiento temporal de datos y ajustes de configuración. El propio shell establece una serie de variables de entorno que pueden ser cambiadas por el usuario para modificar el comportamiento del shell. Se puede obtener una lista de las variables definidas actualmente utilizando el comando env:

$ envSSH_CONNECTION=192.168.0.19 61231 192.168.0.28 22MODULES_RUN_QUARANTINE=LD_LIBRARY_PATHLANG=en_US.UTF-8HISTCONTROL=ignoredupsHOSTNAME=demo-pc.ebookfrenzy.comXDG_SESSION_ID=15MODULES_CMD=/usr/share/Modules/libexec/modulecmd.tclUSER=demoENV=/usr/share/Modules/init/profile.shSELINUX_ROLE_REQUESTED=PWD=/home/demoHOME=/home/demoSSH_CLIENT=192.168.0.19 61231 22SELINUX_LEVEL_REQUESTED= ...

Tal vez la variable de entorno más útil es PATH. Ésta define los directorios en los que el shell buscará los comandos introducidos en el símbolo del sistema, y el orden en que lo hará. La variable de entorno PATH para una cuenta de usuario en un sistema Ubuntu recién instalado probablemente estará configurada como sigue:

$ echo $PATH/home/demo/.local/bin:/home/demo/bin:/usr/share/Modules/bin:/usr/local/bin:/usr/ bin:/usr/local/sbin:/usr/sbin

Otra variable útil es HOME, que especifica el directorio de inicio del usuario actual. Si, por ejemplo, quieres que el shell busque también comandos en el directorio de scripts situado en tu directorio personal, modificarías la variable PATH de la siguiente manera:

$ export PATH=$PATH:$HOME/scripts

El valor actual de una variable de entorno existente puede mostrarse utilizando el comando echo:

$ echo $PATH

Puedes crear tus propias variables de entorno utilizando el comando export. Por ejemplo:

$ export DATAPATH=/data/files

Un truco útil para asignar la salida de un comando a una variable de entorno implica el uso de comillas (`) alrededor del comando. Por ejemplo, para asignar la fecha y la hora actuales a una variable de entorno llamada AHORA:

$ export NOW=`date`$ echo $NOWTue Apr 2 13:48:40 EDT 2020

Si hay configuraciones de variables de entorno o alias que necesita que se configuren cada vez que entra en el entorno del shell, pueden añadirse a un archivo en su directorio personal llamado .bashrc. Por ejemplo, el siguiente archivo .bashrc está configurado para establecer la variable de entorno DATAPATH y un alias:

# .bashrc # Source global definitionsif ; then . /etc/bashrcfi # User specific environmentPATH="$HOME/.local/bin:$HOME/bin:$PATH"export PATH # Uncomment the following line if you don't like systemctl's auto-paging feature:# export SYSTEMD_PAGER= # User specific aliases and functionsexport DATAPATH=/data/filesalias l="ls -lt"

1.13 Escribir scripts de shell

Hasta ahora nos hemos centrado exclusivamente en la naturaleza interactiva del shell Bash. Por interactivo nos referimos a introducir manualmente los comandos en el prompt uno a uno y ejecutarlos. De hecho, esto es sólo una pequeña parte de lo que el shell es capaz de hacer. Podría decirse que uno de los aspectos más poderosos del shell es la capacidad de crear scripts de shell. Los scripts de la shell son esencialmente archivos de texto que contienen secuencias de sentencias que pueden ser ejecutadas dentro del entorno de la shell para realizar tareas. Además de la capacidad de ejecutar comandos, el shell proporciona muchas de las construcciones de programación, como los bucles for y do y las sentencias if, que razonablemente podría esperar encontrar en un lenguaje de scripting.

Desgraciadamente, una visión detallada del shell scripting está más allá del alcance de este capítulo. Sin embargo, hay muchos libros y recursos web dedicados al shell scripting que hacen mucha más justicia al tema de lo que podríamos esperar aquí. En esta sección, por lo tanto, sólo proporcionaremos una pequeña muestra de shell scripting.

El primer paso en la creación de un shell script es crear un archivo (para los propósitos de este ejemplo lo llamaremos simple.sh) y añadir lo siguiente como primera línea:

#!/bin/sh

El #! se denomina «shebang» y es una secuencia especial de caracteres que indica que la ruta al intérprete necesario para ejecutar el script es el siguiente elemento de la línea (en este caso el ejecutable sh ubicado en /bin). Esto podría ser igualmente, por ejemplo, /bin/csh o /bin/ksh si cualquiera de los dos fuera el intérprete que se desea utilizar.

El siguiente paso es escribir un simple script:

#!/bin/shfor i in *do echo $idone

Todo lo que hace este script es iterar a través de todos los archivos en el directorio actual y mostrar el nombre de cada archivo. Esto puede ser ejecutado pasando el nombre del script como argumento a sh:

$ sh simple.sh

Para hacer que el archivo sea ejecutable (negando así la necesidad de pasarlo al comando sh) se puede utilizar el comando chmod:

$ chmod +x simple.sh

Una vez que el bit de ejecución se ha establecido en los permisos del archivo, se puede ejecutar directamente. Por ejemplo:

$ ./simple.sh

1.14 Resumen

En este capítulo de Ubuntu Essentials hemos hecho un breve recorrido por el entorno del shell Bash. En el mundo de los entornos gráficos de escritorio es fácil olvidar que la verdadera potencia y flexibilidad de un sistema operativo a menudo sólo se puede utilizar bajando por debajo de la interfaz de escritorio amigable y utilizando un entorno de shell. Además, la familiaridad con el shell es una necesidad cuando se requiere administrar y mantener sistemas basados en servidores que no tienen el escritorio instalado o cuando se intenta reparar un sistema que está dañado hasta el punto de que el escritorio o la interfaz Cockpit ya no se inician.

Deja una respuesta

Tu dirección de correo electrónico no será publicada.