Apuntes mientras aprendo sobre software y computadoras.

Linux

Cómo convertir código de Bash en comandos personalizados

En este apunte rápido voy a estar revisando cómo agregar comandos personalizados en Bash para una mejor experiencia de uso.

La idea es la siguiente: tengo un script escrito en Bash y me interesa poder utilizarlo como un comandó mas. Mi objetivo es entender cómo hacer eso.

Antes de empezar: este texto es parte de mi “Guía básica para aprender a programar en Bash.” Se trata de mi diario de aprendizaje, en el que voy creando apuntes para entender mejor las cosas que estoy estudiando de manera autodidacta.

Planteando el problema:

Tengo un programa llamado “frase.sh”, y el contenido de este programa es el siguiente:

#!/bin/bash
echo "Este texto es un borrador"

El programa “frase.sh” se encuentra en el directorio “home”, dentro de la carpeta “ejemplo”. Puedo darme cuenta de eso con el comando “ls”:

gus@apunte:~/ejemplo$ ls
frase.sh

Ahora bien, lo primero que tengo que hacer si quiero invocar este programa esa darle permiso de ejecución.

chmod +rx frase.sh

Sin embargo… ¿Puedo ejecutar este programa desde cualquier lugar?

En un principio este código solamente puede ejecutarse si el directorio de trabajo en la terminal coincide con el directorio donde el programa esta guardado.

En mi ejemplo, “frase.sh” solamente puede invocarse cuando la terminal esta abierta en la carpeta ejemplo”.

Y lo puedo hacer escribiendo “./frase.sh”, en el directorio en el que el programa se encuentra, de la siguiente forma:

gus@apunte:~/ejemplo$ ./frase.sh
Este texto es un borrador

Tengo que recordar que el signo “$” indica que me encuentro posicionado en ese directorio.

El problema es que aunque el programa esta funcionando, es poco práctico poder utilizarlo solamente de esta forma.

Para compararlo con un script del sistema, puedo utilizar el comando “date” desde cualquier directorio. No importa en que directorio me encuentre, si escribo “date” recibo por respuesta la fecha y hora en la terminal.

En contraste si escribo “frase.sh” en otro directorio que no sea “/home/ejemplo”, recibo un error. Me dice que el comando no existe.

gus@apunte:~$ ./frase.sh
bash: ./frase.sh: No such file or directory

Existe una forma rápida de resolver esto, pero es una forma de poca ayuda en el largo plazo. Puedo escribir todo el camino al directorio donde se aloja el programa.

Digamos que al saber que mi programa se encuentra en la carpeta “ejemplo”, puedo invocarlo al escribir:

~/ejemplo/frase.sh
Este texto es un borrador

Si escribo todo el camino al programa puedo ejecutar el script desde cualquier directorio. Pero es una solución difícil de recordar y sin dudas mucho menos concreta que escribir solamente algo como “date”.

Pero hay un modo más fácil de hacerlo, y es el que voy a detallar a continuación.

¿Qué busco ahora? Básicamente quiero poder ejecutar estos nuevos programas desde cualquier directorio, del mismo modo que hago con los otros comandos del sistema.

Cómo agregar nuevos comandos en Linux

¿Qué es el command path?

Command Path (o el “camino hacia los comandos”, si me piden mi propia traducción) es una variable de entorno del sistema.

Se trata de un archivo de texto que contiene una lista, y que le informa al sistema en que directorios tiene que buscar comandos que se pueden ejecutar.

Cuando invoco un comando, la shell busca ese comando en los distintos directorios definidos en el Command Path. Si el comando esta en uno de esos directorios, la shell puede usarlo.

Por otra parte, si el comando no aparece en ningún lado dentro de la lista, la terminal devuelve un error del estilo “comando no encontrado”.

El beneficio de añadir un script al Command Path es que entonces nuestro programa va a poder ser encontrado desde cualquier directorio, del mismo modo que un comando regular.

Puedo encontrar esta lista desde la terminal con:

echo $PATH

Lo que aparece en la pantalla es una serie de directorios incluidos dentro del archivo path, separados cada uno por dos puntos (:).

De este modo:

/home/gus/.local/bin:/usr/local/bin:/usr/sbin:/usr/bin:

Cuando invoco un comando, el sistema observa en cada una de estas (por ahora cuatro) carpetas y si lo encuentra pasa a ejecutarlo.

Esta búsqueda comienza por el primer directorio (de izquierda a derecha) hasta llegar al último. No importa si hay más de un comando con el mismo nombre en más de una carpeta, el sistema siempre ejecuta el primero que encuentra siguiendo ese orden.

Solución 1: mover el programa

La solución más sencilla la encuentro si agrego mi programa en alguno de los directorios que ya existían señalados en el comandoPath.

Si quiero que el comando sea accesible para otras cuentas del sistema puedo usar el directorio:

/usr/local/bin

Y si necesito que el programa sea solamente invocado por la cuenta root, necesito guardar el programa en el directorio:

/usr/local/sbin

Pero en mi caso particular puedo agregar “frase.sh” en el directorio:

/home/gus/.local/bin 

Que en mi caso ya se encuentra dentro del camino de búsqueda de comandos para el sistema. Este directorio no es global, y el nuevo comando va a aplicar solamente a mi cuenta.

Entonces, luego de mover el archivo a esa carpeta, ya puedo invocar mi programa sin importar en que directorio se encuentre abierta la terminal:

gus@apunte:~$ frase.sh
El ejemplo funciona

Pero esto es importante. El camino:

/home/gus/.local/bin 

No siempre existe en ese directorio. Y si no existe, tengo que crearlo.

Pero ¿Cómo puedo hacer para agregar nuevos caminos para que el sistema encuentre programas para ejecutar?

De eso trata la siguiente solución.

Solución 2: Modificar el Command Path

Para editar el command path, tengo que dirigirme primero a mí directorio personal (en mi ejemplo eso es “/Home/gus”).

Allí voy a encontrar un archivo llamado “.profile” que se encuentra oculto en un primer momento.

Para ver ese archivo tengo que hacer click con el botón derecho del mouse dentro de la carpeta y activar “mostrar archivos ocultos” (Show Hidden Files).

Para modificar “.profile” es necesario abrirlo con un editor de texto sin formato. Puedo editarlo también directamente desde la terminal, usando un programa como Nano.

Por ejemplo, en mi caso al abrirlo encuentro que una parte dice:

# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/.local/bin" ] ; then
PATH="$HOME/.local/bin:$PATH"
fi

Esto quiere decir que si el directorio “home/.local/bin” existe, va a ser utilizado para buscar ejecutables.

Perfecto, en ese caso una vez más solamente tengo que aegurarme de crear la carpeta si esta no existe.

Pero ¿Y si quiero agregar un directorio completamente diferente?

Ahora tengo que ir hasta el final del documento.

Voy a actualizarlo agregando el camino al nuevo directorio, con el siguiente formato:

export PATH="$PATH:/camino/al/directorio:$PATH"

En mi caso un posible ejemplo siguiendo nuestro caso original puede ser:

export PATH="$HOME/ejemplo:$PATH"

La idea es poner esa linea de texto al final del documento. Y listo, ya puedo guardarlo.

Ahora para que el cambio tenga efecto es necesario utilizar el comando source para que el System Path vuelva a ser leído/actualizado, haciendo que la nueva modificación tome efecto.

Entonces abro una nueva terminal y escribo:

source ~/.profile

Ahora cuando utilizo el comando

echo $PATH

Voy a poder notar que la modificación tuvo efecto, y la nueva carpeta anexada aparece al final de la lista.

Lo mejor de añadir un nuevo camino al final del documento es que, como esta lista es leída en orden, voy a evitar cometer el error de adelantarme a una dirección o comando ya existente.

Del mismo modo, lo mejor es que la carpeta y los programas no tengan nombres que sean iguales a comandos ya usados en el sistema.

Pero si algo fue mal y quiero ver cómo era el command path en sus valores originales, puedo utilizar el comando:

source /etc/environment

Ademas ese último comando va a restaurar mi terminal actual a los valores originales de command path, al menos hasta que vuelva a cerrarla.

Si quiero eliminar el nuevo directorio agregado, simplemente abro de nuevo el archivo “.profile” y elimino la linea que puse antes.

Y si quiero conocer el camino al directorio de un comando en particular puedo hacerlo con el comando “which” de la siguiente forma:

which nombredelcomando

¿Es necesario guardar el script de bash con la extensión “.sh”?

Por lo que pude notar, en Linux no es necesario agregar la extensión “.sh” en el archivo del programa para que el sistema lo entienda como lo entienda como ejecutable.

Entendido de esa forma, puedo nombrar mi programa como “frase”, sin la extensión, para que escribirlo en la terminal se vuelva todavía más sencillo:

gus@apunte:~$ frase
El ejemplo funciona

Conclusión:

Con esto termino el apunte para entender cómo convertir código de Bash en comandos personalizados.

Esta es la versión expandida y corregida de un antiguo apunte que había escrito. Espero que esta nueva versión sea mejor que la anterior.

Si encontrás algún error en el texto o te parece que puedo mejorarlo, me gustaría conocer tu opinión. Se puede encontrar mi correo electrónico en la sección de contactos.

La seguimos en el próximo apunte.

Leave a Reply