prueba
--- con la intención de que HAL lea de él las órdenes que contiene, estamos creando un fichero semejante a aquéllos en que consisten las órdenes que HAL nos proporciona de antemano, es decir, un fichero ejecutable (= una orden) y, particularmente, del mismo tipo que las órdenes escritas en el lenguaje interpretado que venimos denominando la "lengua de HAL".Esta sola idea nos puede llevar a una conclusión casi completamente acertada, a saber, que para pedir a HAL que ejecute nuestro fichero
prueba
bastará con poner su nombre en la línea de órdenes. Vamos a probarlo:
prueba
La respuesta es, desgraciadamente, ¡la misma de siempre!:
bash: prueba: command not found
¿Qué falla en nuestra deducción? Piense el lector unos segundos más y comprenderá que el hecho de que todas las demás órdenes conocidas se encuentren en directorios específicos (
/bin
, /sbin
, etc.) puede tener que ver con el desesperante resultado.Recordemos, de entrada, una de las conclusiones con las que se inició el artículo anterior y que reclama ahora una atención mayor:
... una de las primerísimas cosas que comprueba HAL cuando nos comunicamos con él es si la palabra introducida en la línea de órdenes corresponde o no al nombre de una orden existente en el sistema.
Nuestra palabra
prueba
, esto es, el nombre de fichero prueba
, fue sometido a esta inicial verificación y descartado como orden porque la ruta del directorio que lo contiene no es ninguna de aquéllas en las que HAL entiende que deben estar los ficheros ejecutables, las órdenes. Y HAL, el muy pillín, conoce de antemano esas rutas, antes incluso de que iniciemos una conversación con él. ¿Cómo lo conoce? No es ningún misterio. Del mismo modo que obtiene sus otros conocimientos iniciales, por medio de una variable de entorno.Recordaremos seguramente el tema de las variables de entorno en relación con nuestro esfuerzo por hacer que HAL respondiera en el idioma que deseábamos. Allí quedó determinado su sentido:
... desde el mismo momento que iniciamos nuestra charla con HAL, hay una serie de aspectos relativos a ella que han quedado establecidos de antemano y sin que nosotros hayamos sido conscientes. Los arquitectos de nuestra distribución son los responsables de haberlos definido por nosotros para nuestro propio beneficio, y el de HAL. Estos aspectos se denominan variables de entorno, porque son aspectos modificables del entorno de diálogo en que nos encontramos de entrada.
Pues bien, la variable de entorno donde se especifican las rutas de los ficheros ejecutables es la variable
PATH
(ruta o senda, en inglés). Podemos conocer su valor actual de varias formas. Por ejemplo, mediante la orden printenv
, que, como su nombre indica (abreviatura de print environment) imprime en la salida el entorno actual. Por defecto, printenv
devuelve todas las variables y sus valores actuales. Si se especifican como argumentos variables determinadas, devuelve el valor de esas variables. Consultemos a HAL sobre el valor actual de la variable
PATH
:printenv PATH
La respuesta de mi HAL es ésta:
/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games
Se trata de una lista de todas las rutas de los directorios donde residen órdenes ejecutables y donde cada ruta está separada de la siguiente por el signo '
:
'. Se verá que faltan las rutas donde, según el artículo anterior, residen los ejecutables del sistema:
/sbin
y /usr/sbin
. La razón es que sólo el superusuario puede hacer ejecutar estas órdenes del sistema y puesto que no somos el superusuario ---a menos que nos pongamos el disfraz de Superman y nos convirtamos en él--- nuestro entorno de usuario corriente no contiene tales rutas. El lector debería comprobar que hacer ejecutar la orden anterior (printenv PATH
) con el disfraz de superusuario le dará otra respuesta, donde sí están incluidas las rutas de los ejecutables del sistema y donde no aparecerán, probablemente, otras indignas de la atención de root:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Hay otra forma diferente de conocer el valor de la variable
PATH
, que no requiere el uso de una nueva orden y que nos viene bien para aprender un nuevo elemento de la lengua de HAL.Como sabemos, la orden
echo
repite tal cual los argumentos que recibe. Pero existen excepciones a esa función suya de devolver sin ton ni son lo mismo que le damos. Una de estas excepciones tiene lugar cuando el argumento de echo
es una variable con el prefijo $
. Veamos el porqué. Sabemos lo que es una variable, porque ya nos hemos topado con ellas, de hecho estamos ahora mismo hablando de una en concreto. Las variables ---incluidas las variables de entorno--- no son más que nombres asociados a ciertas informaciones. Por ejemplo, la variable
LANG
es el nombre que recibe en el entorno la información relativa a la lengua del sistema (inglés, español, japonés, etc.). A la información actualmente asociada con ese nombre se la denomina técnicamente el valor actual de esa variable, un valor que podemos cambiar cuando queramos (de ahí lo de variable). En nuestro caso, el valor actual de LANG
es el español, pero podemos cambiarlo al japonés cuando queramos. Pues bien ---y siguiendo con el ejemplo--- $LANG
, con el prefijo del dolar delante del nombre de la variable, es la forma que en lengua de HAL sirve justamente para designar el valor de la variable LANG
. Ahora bien, la orden
echo
, que recibe como argumento cualquier fragmento de texto, puede recibir también perfectamente el tipo de fragmento que sirve para designar el valor de una variable, por ejemplo, el vocablo $LANG
. Cuando echo
se encuentra con un argumento de esta clase, deja por un momento de comportarse de la manera simplona que lo hace ---reproducir tal cual lo que ha recibido--- y nos devuelve el valor de la variable cuyo nombre sucede al signo del dolar. Así:echo $LANG
devuelve:
es_ES.UTF-8
y no simplemente ---como podría predecirse sin la anterior consideración---:
$LANG
En general, podemos saber el valor de cualquier variable y también de la variable que nos interesa en este artículo, la variable
PATH
, mediante la orden echo
:echo $PATH
Que, como era de esperar, nos vuelve a mostrar la salida obtenida con
printenv PATH
:/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games
Si volvemos al comienzo de la digresión, nos resultará evidente por qué nuestra orden
prueba
, cuya ruta completa ---conviene recordarlo--- es /home/[nombre-usuario]/guiones/prueba
no ha sido aceptada por HAL como una orden. Simplemente, el directorio /home/[nombre-usuario]/guiones
no forma parte de la variable PATH
.Es evidente, también, que para obligar a HAL a que acepte nuestra orden
prueba
como tal orden y, en general, todos los guiones que a partir de ahora escribamos para él no queda más remedio que modificar la variable PATH
para que incluya la ruta del directorio /home/[nombre-usuario]/guiones
.Sabemos modificar variables de entorno, lo hicimos hace tiempo con las variables del entorno local [véanse los artículos El supermanual de HAL y HAL y mis ficheros]. Probemos, pues, a pedir a HAL que ejecute nuestra orden
prueba
, pero con el PATH
previamente modificado, tal como hicimos en el primero de los artículos referidos:PATH=/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games:/home/atopos/guiones \
prueba
Antes de pulsar Enter consideremos tres aspectos de esta orden. El primero es obvio: la última ruta incluida en el
PATH
contiene el nombre del usuario después de /home
. Mi nombre de usuario es atopos; el del lector será el que sea. El segundo también es obvio: todas las rutas están separadas por ':
' ---no lo olvide el lector. El tercero es el más interesante: se han de incluir las rutas ya existentes en la variable PATH
antes de cambiarla, de lo contrario, todos las rutas predefinidas de las órdenes habituales serían invisibles para HAL y HAL dejaría de reconocer como órdenes a nuestros viejos amigos echo
, sed
, grep
, awk
y compañía.Esta última consideración puede llevar a algún lector a una deducción inteligente. Si la variable
PATH
ya tiene un valor antes de nuestro cambio ---un valor que, como hemos visto, se designa con $PATH
--- y este valor debe ser preservado, ¿por qué no añadir directamente la ruta de nuestro directorio guiones
a ese valor previo? Dicho más claramente, ¿por qué no poner en lugar de la larga expresión anterior esta otra?PATH=$PATH:/home/atopos/guiones
Si el lector ha llegado a tal conclusión por sí mismo, ¡enhorabuena! Demuestra una inteligencia despierta y creativa y una comprensión plena de lo dicho en este artículo. Efectivamente, ésa es la forma habitual de modificar variables cuyo valor anterior debe mantenerse. Por tanto, nuestra forma de pedir a HAL que ejecute
prueba
debe ser la siguiente:PATH=$PATH:/home/atopos/guiones prueba
Y, ahora sí ---por fin--- la respuesta de HAL cambia, pero de una forma totalmente inesperada:
bash: /home/atopos/guiones/prueba: Permiso denegado
Increíble, pero cierto. Incluso estando en nuestro
home
particular, HAL nos dice que no tenemos permisos. ¡Esto sí que es un galimatías!Pero no, lector, HAL no ha dejado de funcionar cuerdamente. La razón de su comportamiento es muy significativa y será tratada en el próximo artículo.
Antes de ello, conviene comentar tres cosas más en relación con el asunto de este artículo.
La primera es que se podría editar nuestro fichero
.bashrc
para que el cambio de la variable PATH
fuera permanente, de modo semejante a como se hizo en HAL y mis ficheros con las variables del entorno local. La segunda es que podríamos incluir nuestros propios guiones en los directorios que el sistema tiene reservados para los binarios ejecutables. Algo muy poco recomendable, porque, aunque ello evita tocar la variable
PATH
, acaba mezclando órdenes del sistema con órdenes de usuario y las consecuencias de esta mezcolanza pueden ser bastante penosas, aparte de poco estéticas.La tercera y última es que existe otra forma sencilla para conseguir que HAL entienda mis guiones como ficheros ejecutables sin necesidad de redefinir la variable
PATH
ni de añadir nada ajeno a los directorios del sistema. A saber, dar como orden la ruta completa del fichero que contiene la orden. En el caso de nuestro fichero prueba
sería:/home/atopos/guiones/prueba
Como esta opción es un tanto molesta, por larga, existe un atajo o, más exactamente, una abreviatura: hacer preceder la orden del caso con los signos punto y barra: '
./
'. Es decir, que sin hacer ninguna modificación en la variable PATH
y dando por sobrentendido que estamos dentro del directorio guiones
podríamos escribir:./prueba
Tanto la versión que incluye la ruta completa como esta abreviada (donde el punto es la abreviatura del directorio actual de trabajo) obtendríamos el mismo resultado inesperado de la orden anterior en que la variable
PATH
fue modificada.De hecho, y en próximos artículos, utilizaremos este último recurso (
./mi-orden
) con el fin de diferenciar nuestras órdenes de las que proporciona el sistema.Resumen
- Cuando escribimos una orden en la línea de órdenes, HAL comprueba si el fichero que corresponde a esa orden existe en el sistema. Lo hace consultando los directorios definidos en la variable de entorno
PATH
. - La orden
printenv
(print environment) devuelve el valor actual de las variables de entorno que se le especifican como argumentos. Por defecto, esto es, sin argumentos, devuelve todas las variables del entorno y sus valores actuales. - Una variable es un nombre para un determinado fragmento de información.
- El valor de una variable se designa mediante el nombre de esa variable precedido por el prefijo '
$
'. Por ejemplo,$PATH
designa el valor de la variablePATH
. - Cuando el argumento de
echo
es la designación de un valor de variable,echo
devuelve el valor de esa variable. Por ejemplo,echo $PATH
devuelve el valor de la variablePATH
. - La combinación de signos '
./
' como prefijo de un nombre de fichero, hace que ese nombre sea interpretado como el nombre de una orden existente en el directorio de trabajo actual. (El punto está ahí como abreviatura de la ruta completa de dicho directorio).
No hay comentarios:
Publicar un comentario