Primero que nada les quería agradecer por darle bola al primer post . Espero que la continuación no defraude. Y ante cualquier interrogante que les surja, no duden en
acercársela a Mauri
o bien hacer man bash. Ahí van a encontrar listadas las variables de entorno, los caracteres especiales, y las estructuras lógicas para hacer iteraciones, que serán utilizadas en el siguiente post. Café, Julia Holter, empecemos.
Las variables son componentes esenciales de cualquier lenguaje de programación, cuya finalidad es almacenar datos de diversos tipos. En general, en lenguajes ligados al scripting no requieren declarar el tipo asociado a una variable previo a su utilización, y las asignaciones pueden realizarse directamente.
En Bash, el valor de toda variable es un string o cadena, sin importar si asignamos variables utilizando comillas o no ( ejemplos ). Además, existen variables específicas utilizadas por el entorno del shell y el entorno operativo para almacenar valores especiales; las llamaremos variables de entorno.
Los nombres de las variables son definidos mediante los constructores usuales. Cuando una aplicación se encuentra en ejecución, se definirá un conjunto particular de variables llamadas variables de entorno. Para ver todas las variables de entorno asociadas a un terminal, corremos el comando env. Para cualquier proceso, las variables de entorno pueden ser listadas mediante
donde PID es el ID del proceso (PID es siempre un valor entero).
Por ejemplo, supongamos que una aplicación llamada geany está corriendo. Podemos obtener su ID de proceso con el comando pgrep
Luego, podemos obtener las variables de entorno asociadas al proceso ejecutando el siguiente comando:
El comando devuelve una lista de variables de entorno y sus valores. Cada variable es representada bajo la forma del par nombre=value y separada por el caracter nulo o NULL \0. Si sustituimos el caracter \0 por \n, cambiamos el formato de la salida o output para que nos devuelva sólo un par variable=value por línea. La sustitución se realiza utilizando el comando tr:
¿Qué sucede si sustituimos '\0' por '\t'?
A continuación, vamos a hablar sobre cómo asignar y manipular variables en general y variables de entorno en particular.
Una variable es asignada de la siguiente manera:
var es el nombre de una variable, y value es el valor que se le asigna a la variable var. Si value no contiene caracteres de espaciado (como el espacio), no requiere entrecomillado; caso contrario, necesita estar acotado por comillas simples o dobles.
Es importante notar que var = value y var=value son operaciones distintas. Es un error usual escribir var =value en lugar de var=value. La última es una operación de asignación, mientras que la anterior involucra un operador de comparación, en particular la igualdad.
Podemos imprimir en pantalla el contenido de una variable utilizando el prefijo $ seguido con el nombre de la variable:
O también:
La salida será:
Podemos utilizar variables de valor dentro de printf o echo entre comillas dobles:
La salida será:
Las variables de entorno son variables cuya definición ha sido heredada de procesos "padre". Un ejemplo de variable de entorno es HTTP_PROXY. Esta variable define qué servidor se deberá utilizar para establecer una conexión a internet. En general, se establece de la siguiente manera:
El comando export se utiliza para modificar la variable env. De ahora en más, cualquier aplicación ejecutada desde el shell actual, recibirá esta variable. Podemos exportar variables personalizadas de acuerdo a lo que necesitemos y queramos hacer en una aplicación o shell script que es ejecutada. Existen muchas variables de entorno estándar disponibles por defecto para el shell.
Por ejemplo, PATH. El contenido típico de una variable PATH será:
Cuando introducimos un comando para su ejecución, el shell automáticamente busco el ejecutable en la lista de directorios de la variable de entorno PATH (las rutas de directorios o paths son delimitadas por el caracter ":" ). Usualmente $PATH estará definida en /etc/enviroment o /etc/profile o ~/.bashrc. Cuando necesitamos añadir un nuevo path al entorno PATH, utilizamos:
O alternativamente, podemos usar:
Y verificamos:
Hemos añadido /home/usuario/bin a PATH.
Algunas de las variables de entorno más conocidas son HOME, PWD, USER, UID, SHELL, etc.
Aclaraciones. Cuando usemos el entrecomillado simple, la variable de valor ($var) no expanderá el contenido (value) de la variable (var), sino la variable de valor en sí misma:
Mientras que echo "$var" devolverá el valor de la variable var siempre que la misma esté definida, o nada en caso de que no lo esté.
Qué más podemos hacer...
Calcular la longitud de una cadena
La operación asigna la longitud de la cadena asignada a la variable var, a la variable length. En otras palabras, el valor de var es una cadena, el valor de length es la longitud de tal cadena.
Para directamente imprimir en pantalla la longitud de una cadena:
Identificar el shell actual
Para identificar el shell en uso, podemos utilizar la variable SHELL:
O también:
Verificar permisos de super usuario
UID es una variable de entorno importante que puede ser utilizada para verificar si un script ha sido lanzado como usuario root o como usuario regular. Por ejemplo, podemos agregar a nuestro script:
Luego, devolverá:
Modificar el texto del prompt de Bash
Cuando abrimos un terminal o corremos un shell, vemos una cadena de la forma usuario@host:/home/$. Distintas distribuciones GNU/Linux tendrán prompts levemente diferentes, y diferentes colores. Podemos personalizar localmente el texto del prompt utilizando la variable de entorno PS1. En el primer post modificamos su valor por defecto recurriendo a un editor de texto; aquí, "localmente" refiere a no más allá las variables de entorno del shell en uso.
Podemos listar la línea utilizada para establecer la variable PS1 mediante
Para establecer un prompt personalizado, introducimos el siguiente comando:
Obviamente podemos utilizar texto en color utilizando secuencias especiales de escape, como mostramos al final de primer post.
Existen además ciertos caracteres especiales que expanden hacia parámetros del sistema. Por ejemplo, \u muestra el nombre de usuario, \h el nombre de host, y \w muestra el directorio actual.
Las variables de entorno son utilizadas en general para almacenar una lista de paths donde se deben buscar ejecutables, librerías, y otros. Ejemplos son $PATH , $LD_LIBRARY_PATH que típicamente se verán como:
En esencia esto significa que cuando el shell deba ejecutar binarios, primero mirará dentro de /usr/bin, y luego en /bin.
Una tarea común a la hora de compilar un programa desde el código fuente e instalar sobre un path personalizado, es añadir la ruta del directorio bin a la variable de entorno PATH.
Supongamos que instalamos miprograma en /opt/miprograma, que además tiene binarios en un directorio llamado bin y librerías en lib[/lib].
Cómo lo hacemos
Una manera es:
PATH y LD_LIBRARY_PATH deberían ahora verse similar a:
Sin embargo, podemos hacer esto más fácilmente al agregar la siguiente función a .bashrc
Luego, utilizaremos la función prepend de la siguiente manera:
Cómo funciona
Definimos una función prepend(), que primero verifica si el directorio especificado para la función por el segundo parámetro $2 existe. En tanto exista, la expresión eva1 hace que a la variable cuyo nombre está en el primer parámetro $1 se le asigne la cadena dada por el segundo parámetro, seguida por un : (caracter separador de paths), y luego el valor original de la variable.
Notemos que, en caso de que la variable esté vacía, habrá un : al final. Para evitar esto, modificamos la función de la siguiente manera:
Definida de esta manera, introducimos un parámetro de expansión del shell
que expande a expresión si el parámetro ha sido ingresado y es no nulo.
Con este cambio, nos aseguramos de agregar : y luego el valor previo de la variable si y sólo si dicho valor existe.
Los descriptores de archivos son enteros asociados a la entrada (input) y salida (output) de archivos. Son los que siguen el rastro de los archivos abiertos. Los descriptores más conocidos son stdin, stdout, y stderr. Jugando con ellos podemos redirigir la salida de un archivo de un descriptor a otro filtrando su contenido. Haciendo esto mucha gente se compró la casa y el auto. Nos vemos en el próximo post.
Jugando con variables y variables de entorno
Las variables son componentes esenciales de cualquier lenguaje de programación, cuya finalidad es almacenar datos de diversos tipos. En general, en lenguajes ligados al scripting no requieren declarar el tipo asociado a una variable previo a su utilización, y las asignaciones pueden realizarse directamente.
En Bash, el valor de toda variable es un string o cadena, sin importar si asignamos variables utilizando comillas o no ( ejemplos ). Además, existen variables específicas utilizadas por el entorno del shell y el entorno operativo para almacenar valores especiales; las llamaremos variables de entorno.
Los nombres de las variables son definidos mediante los constructores usuales. Cuando una aplicación se encuentra en ejecución, se definirá un conjunto particular de variables llamadas variables de entorno. Para ver todas las variables de entorno asociadas a un terminal, corremos el comando env. Para cualquier proceso, las variables de entorno pueden ser listadas mediante
$ cat /proc/$PID/environ
donde PID es el ID del proceso (PID es siempre un valor entero).
Por ejemplo, supongamos que una aplicación llamada geany está corriendo. Podemos obtener su ID de proceso con el comando pgrep
$ pgrep geany
4615
Luego, podemos obtener las variables de entorno asociadas al proceso ejecutando el siguiente comando:
$ cat /proc/4615/environ
El comando devuelve una lista de variables de entorno y sus valores. Cada variable es representada bajo la forma del par nombre=value y separada por el caracter nulo o NULL \0. Si sustituimos el caracter \0 por \n, cambiamos el formato de la salida o output para que nos devuelva sólo un par variable=value por línea. La sustitución se realiza utilizando el comando tr:
$ cat /proc/4615/environ | tr '\0' '\n'
¿Qué sucede si sustituimos '\0' por '\t'?
A continuación, vamos a hablar sobre cómo asignar y manipular variables en general y variables de entorno en particular.
Una variable es asignada de la siguiente manera:
var=value
var es el nombre de una variable, y value es el valor que se le asigna a la variable var. Si value no contiene caracteres de espaciado (como el espacio), no requiere entrecomillado; caso contrario, necesita estar acotado por comillas simples o dobles.
Es importante notar que var = value y var=value son operaciones distintas. Es un error usual escribir var =value en lugar de var=value. La última es una operación de asignación, mientras que la anterior involucra un operador de comparación, en particular la igualdad.
Podemos imprimir en pantalla el contenido de una variable utilizando el prefijo $ seguido con el nombre de la variable:
$ var="value" #Asignamos value a la variable var
$ echo $var
O también:
$ echo ${var}
La salida será:
value
Podemos utilizar variables de valor dentro de printf o echo entre comillas dobles:
La salida será:
Las variables de entorno son variables cuya definición ha sido heredada de procesos "padre". Un ejemplo de variable de entorno es HTTP_PROXY. Esta variable define qué servidor se deberá utilizar para establecer una conexión a internet. En general, se establece de la siguiente manera:
$ HTTP_PROXY=152.179.42.178:3128
$ export HTTP_PROXY
El comando export se utiliza para modificar la variable env. De ahora en más, cualquier aplicación ejecutada desde el shell actual, recibirá esta variable. Podemos exportar variables personalizadas de acuerdo a lo que necesitemos y queramos hacer en una aplicación o shell script que es ejecutada. Existen muchas variables de entorno estándar disponibles por defecto para el shell.
Por ejemplo, PATH. El contenido típico de una variable PATH será:
$ echo $PATH
/home/slynux/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
Cuando introducimos un comando para su ejecución, el shell automáticamente busco el ejecutable en la lista de directorios de la variable de entorno PATH (las rutas de directorios o paths son delimitadas por el caracter ":" ). Usualmente $PATH estará definida en /etc/enviroment o /etc/profile o ~/.bashrc. Cuando necesitamos añadir un nuevo path al entorno PATH, utilizamos:
$ export PATH="$PATH:/home/usuario/bin"
O alternativamente, podemos usar:
$ PATH="$PATH:/home/usuario/bin"
$ export PATH
Y verificamos:
$ echo $PATH
/home/slynux/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/home/usuario/bin
Hemos añadido /home/usuario/bin a PATH.
Algunas de las variables de entorno más conocidas son HOME, PWD, USER, UID, SHELL, etc.
Aclaraciones. Cuando usemos el entrecomillado simple, la variable de valor ($var) no expanderá el contenido (value) de la variable (var), sino la variable de valor en sí misma:
$ echo '$var'
$var
Mientras que echo "$var" devolverá el valor de la variable var siempre que la misma esté definida, o nada en caso de que no lo esté.
Qué más podemos hacer...
Calcular la longitud de una cadena
length=${#var}
La operación asigna la longitud de la cadena asignada a la variable var, a la variable length. En otras palabras, el valor de var es una cadena, el valor de length es la longitud de tal cadena.
Para directamente imprimir en pantalla la longitud de una cadena:
$ var="GNU/Linux en T!"
$ echo ${#var}
15
Identificar el shell actual
Para identificar el shell en uso, podemos utilizar la variable SHELL:
$ echo $SHELL
O también:
$ echo $0
Verificar permisos de super usuario
UID es una variable de entorno importante que puede ser utilizada para verificar si un script ha sido lanzado como usuario root o como usuario regular. Por ejemplo, podemos agregar a nuestro script:
Luego, devolverá:
Modificar el texto del prompt de Bash
Cuando abrimos un terminal o corremos un shell, vemos una cadena de la forma usuario@host:/home/$. Distintas distribuciones GNU/Linux tendrán prompts levemente diferentes, y diferentes colores. Podemos personalizar localmente el texto del prompt utilizando la variable de entorno PS1. En el primer post modificamos su valor por defecto recurriendo a un editor de texto; aquí, "localmente" refiere a no más allá las variables de entorno del shell en uso.
$ cat ~/.bashrc | grep PS1
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w$ '
Existen además ciertos caracteres especiales que expanden hacia parámetros del sistema. Por ejemplo, \u muestra el nombre de usuario, \h el nombre de host, y \w muestra el directorio actual.
Función prepend para variables de entorno
Las variables de entorno son utilizadas en general para almacenar una lista de paths donde se deben buscar ejecutables, librerías, y otros. Ejemplos son $PATH , $LD_LIBRARY_PATH que típicamente se verán como:
PATH=/usr/bin;/bin
LD_LIBRARY_PATH=/usr/lib;/lib
En esencia esto significa que cuando el shell deba ejecutar binarios, primero mirará dentro de /usr/bin, y luego en /bin.
Una tarea común a la hora de compilar un programa desde el código fuente e instalar sobre un path personalizado, es añadir la ruta del directorio bin a la variable de entorno PATH.
Supongamos que instalamos miprograma en /opt/miprograma, que además tiene binarios en un directorio llamado bin y librerías en lib[/lib].
Cómo lo hacemos
Una manera es:
$ export PATH=/opt/miprograma/bin:$PATH
$ export LD_LIBRARY_PATH=/opt/miprograma/lib;$LD_LIBRARY_PATH
PATH y LD_LIBRARY_PATH deberían ahora verse similar a:
PATH=/opt/miprograma/bin:/usr/bin:/bin
LD_LIBRARY_PATH=/opt/miprograma/lib:/usr/lib;/lib
Sin embargo, podemos hacer esto más fácilmente al agregar la siguiente función a .bashrc
prepend() { [ -d "$2" ] && eval $1="$2':'$$1" && export $1; }
Luego, utilizaremos la función prepend de la siguiente manera:
$prepend PATH /opt/miprograma/bin
$prepend LD_LIBRARY_PATH /opt/miprograma/lib
Cómo funciona
Definimos una función prepend(), que primero verifica si el directorio especificado para la función por el segundo parámetro $2 existe. En tanto exista, la expresión eva1 hace que a la variable cuyo nombre está en el primer parámetro $1 se le asigne la cadena dada por el segundo parámetro, seguida por un : (caracter separador de paths), y luego el valor original de la variable.
Notemos que, en caso de que la variable esté vacía, habrá un : al final. Para evitar esto, modificamos la función de la siguiente manera:
prepend() { [ -d "$2" ] && eval $1="$2${$1:+':'$$1}" && export $1 ; }
Definida de esta manera, introducimos un parámetro de expansión del shell
${parámetro:+expresión}
que expande a expresión si el parámetro ha sido ingresado y es no nulo.
Con este cambio, nos aseguramos de agregar : y luego el valor previo de la variable si y sólo si dicho valor existe.
Jugando con descriptores de archivo y redirección
Los descriptores de archivos son enteros asociados a la entrada (input) y salida (output) de archivos. Son los que siguen el rastro de los archivos abiertos. Los descriptores más conocidos son stdin, stdout, y stderr. Jugando con ellos podemos redirigir la salida de un archivo de un descriptor a otro filtrando su contenido. Haciendo esto mucha gente se compró la casa y el auto. Nos vemos en el próximo post.