No es un problema de Linux, sino del
shell que estás usando.
Tienes razón que es algo relacionado con la variable
$PATH. Cuando tu mandas ejecutar algo, el
shell busca el comando en el lugar del sistema de ficheros que se le indique. Por ejemplo:
/home/kiloko/bin/scripts/hola.sh
Si no le indicamos una ruta, el
shell tendrá que buscarlo. Primero, mira a ver si es un comando interno suyo. Si no lo es, entonces se trata de un comando que debe estar en algún lugar del sistema de ficheros.
Para saber en qué directorio se puede encontrar ese comando, el
shell usa la variable
$PATH.
Si, por ejemplo, la variable
$PATH contiene
/bin:/usr/bin:/usr/local/bin entonces el
shell mirará en cada uno de esos directorios intentando encontrarlo.
Si no lo encuentra, entonces informa de un posible error.
En tu primer caso,
hola.sh sí que se encuentra en alguno de los caminos indicados por
$PATH. En el segundo caso, como no lo encuentra, le estás indicando un camino (relativo) al lugar donde está (en este caso, el mismo directorio de trabajo).
Cuando uno tiene que hacer programas, puede ser muy aburrido tener que escribir el './' siempre delante de cada comando. Hay dos soluciones, pero pasan por la misma tarea: modificar la variable
$PATH en el momento del arranque.
La modificación se puede realizar en alguno de los ficheros que el shell lee en el momento del arranque. En los Linux más modernos, se realiza en el fichero global /etc/profile. Ejemplo: en mi OpenSuse 10.3, un extracto de ese fichero es:
Using bash Syntax Highlighting
#
# Make path more comfortable
#
if test -z "$PROFILEREAD" ;
then
PATH=
/usr
/local
/bin:
/usr
/bin:
/bin
if test "$HOME" !=
"/" ;
then
for dir in $HOME/bin
/$CPU $HOME/bin ;
do
test -d $dir && PATH=
$dir:
$PATH
done
fi
if test "$UID" = 0 ;
then
test -d /opt
/kde3
/sbin
&& PATH=
/opt
/kde3
/sbin:
$PATH
PATH=
/sbin:
/usr
/sbin:
/usr
/local
/sbin:
$PATH
fi
for dir in /usr
/X11
/bin \
/usr
/bin
/X11 \
/usr
/X11R6
/bin \
/var
/lib
/dosemu \
/usr
/games \
/opt
/bin \
/opt
/kde3
/bin \
/opt
/kde2
/bin \
/opt
/kde
/bin \
/usr
/openwin
/bin \
/opt
/cross
/bin
do
test -d $dir && PATH=
$PATH:
$dir
done
unset dir
export PATH
fiColoreado en 0.003 segundos, usando
GeSHi 1.0.8.4
Notar las siguientes cosas:
* Se usa una variable global llamada
$PROFILEREAD para saber si este fichero ya lo hemos ejecutado o no (resulta que durante diez años, los shell ejecutaban varias veces este mismo fichero, por... una historia... que es mejor olvidar...)
* Vale, si es la primera vez que lo ejecutamos, inicializa la variable a un valor estándar.
* Si la variable
$HOME está puesta (lo que suele querer decir que este fichero está siendo ejecutado por un shell arrancado a su vez por un proceso login por parte de un usuario -real-), entonces hace un bucle mirando a ver si ese usuario tiene un par directorios llamados
bin/$CPU y
bin/. Si los tiene, los agrega a
$PATH.
* El resto de las líneas van añadiendo directorios más o menos estándares, en caso de que existan en el sistema.
* Finalmente, exporta la variable, para que sea conocida en los procesos que se ejecutarán más tarde.
Aquí has visto que, con que el usuario ya tenga un subdirectorio llamado
bin/, el
$PATH cambia para agregarle, así que la consecuencia es que solo tendríamos que meter nuestros programas dentro de ese directorio y ya está. Y esta es la solución más aconsejable.
Pero claro... muchas veces estamos haciendo programas que NO están NI estarán guardados en el
bin/ del usuario, así que muchas veces tenemos que ejecutar comandos que están en el mismo directorio donde les estamos creando. Y escribir './' es muy aburrido.
Bien, pues hay que modificar
$PATH para que agregue el directorio actual -en donde estemos en ese momento- a la lista de "caminos a ejecutables".
(Lo siguiente es un rollo. Saltar los dos próximos párrafos)
Esto se suele hacer ya en alguno de los ficheros propios del usuario, por temas de seguridad que luego comentaré. Si se usa el Bash Shell, se suele hacer en alguno de los ficheros que se ejecutan en el arranque de login del usuario. Podría ser
~/.profile o
~/.bashrc. Según el manual, el primero se ejecuta en el momento del login del usuario, mientras que el segundo se ejecuta cuando se ejecuta un shell interactivo (sí, hay ocasiones que un usuario puede entrar en un sistema y no hacer una sesión interactiva).
En mi OpenSuse 10.3,
~/.profile, básicamente lo único que hace es comprobar que
/etc/profile se haya ejecutado. Sino es así, lo ejecutamos de todas formas:
Using bash Syntax Highlighting
test -z "$PROFILEREAD" && .
/etc
/profile
Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
mientras que
~/.bashrc contiene un texto que indica que este fichero será ejecutado desde el
/etc/profile, por lo que todo que pongamos en
~/.bashrc será ejecutado tanto en sesiones interactivas, como en sesiones normales o incluso si solo se hace login.
Bueno, pues entonces editamos
~/.bashrc y agregamos una línea como esta:
Using bash Syntax Highlighting
export PATH=
"$PATH:."Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
que quiere decir que a la variable
$PATH le añadimos el directorio actual ('.'), sea el que sea en ese momento y siempre que ejecutemos un comando.
Con este cambio, ya no tenemos que escribir './' para ejecutar los comandos del propio directorio.
Todo esto está bien... pero tiene un lado perverso. Si nuestra máquina está segura (y nadie va a entrar a tocar las narices), podemos seguir así. El problema es el siguiente: si en lugar de definir la variable
$PATH como antes, si no así:
Using bash Syntax Highlighting
export PATH=
".:$PATH"Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
(es decir: damos preferencia de búsqueda a los comandos que están en nuestro directorio ANTES que en ningún otro), entonces, si un día, alguien -hacker o no- consigue entrar en el sistema, podría colocar un ejecutable -un malware-, con un nombre muy conocido, en alguno de los directorios de algún usuario o del propio root -según los permisos que consiga escalar-. Ejemplo: instala un troyano, con el nombre 'ls' y lo deja en tu carpeta raíz.
Como ejecutar 'ls' es algo muy normal, lo vas a hacer y, como el
$PATH fue modificado para tener en cuenta el propio directorio en donde estemos, lo que hará el
shell será ejecutar el troyano.
Lo mejor, entonces, es definir
$PATH como se ha indicado antes, con el '.' al final, porque entonces el
shell ejecutará el 'ls' del sistema antes que el de tu directorio.
De todas formas, mientras que esto es una modificación muy normal para un usuario, no es nada aconsejable para los root. Y en el caso de usarlo un usuario, que no se le ocurra crear programas que tengan el mismo nombre que los comandos básicos del sistema. El lío puede ser tremendo (con la ulterior posible pérdida de información).
Son 0.20€.