El estándar de shell POSIX dice en este sitio
http://pubs.opengroup.org/onlinepubs/9699919799/
sobre cómo usan los shells PATHpara buscar ejecutables:
"Se buscará en la lista de principio a fin, aplicando el nombre de archivo a cada prefijo, hasta que se encuentre un archivo ejecutable con el nombre especificado y los permisos de ejecución apropiados".
Bueno, no es así como parece funcionar en la implementación POSIX real:
man which dice:
"devuelve los nombres de ruta de los archivos (o enlaces) que se ejecutarían en el entorno actual, si sus argumentos se hubieran dado como comandos en un shell estrictamente compatible con POSIX. Lo hace buscando en la RUTA archivos ejecutables que coincidan con los nombres de argumentos. No sigue enlaces simbólicos ".
OK, veamos esta situación:
$ pwd
/home/mark
$ echo $PATH
/home/mark/bin:...
$ ls -l bin/foobar
lrwxrwxrwx 1 mark mark 18 Dec 12 22:51 bin/foobar -> /home/mark/foobar1
$ touch foobar1
$ which foobar
$ chmod a+x foobar1
$ which foobar
/home/mark/bin/foobar
OK, aquí hay un enlace simbólico PATHcon el nombre correcto, y se informa lsque es ejecutable.
which no lo mira en absoluto, pero solo le interesa lo que señala.
Eso a pesar del hecho de que ambos man whichdicen explícitamente que no sigue enlaces simbólicos (y de hecho vemos que no lo hace, porque which foobarno se imprime foobar1), y también que la documentación del shell POSIX citada anteriormente, nunca menciona los siguientes enlaces simbólicos en el PATHalgoritmo.
Entonces, ¿están whichmal los shells existentes o no entiendo la documentación?
PARA ACLARAR:
Sé y puedo explicar el comportamiento existente. Mi pregunta no es "¿cómo funciona esto?". Eso lo sé.
Mi pregunta es sobre la documentación: ¿dónde está mi error al seguir la documentación que cité? ¿O está mal la documentación?
MOTIVACIÓN: ¿Por qué me importa?
Bueno, soy un implementador. Los diferentes implementadores tienen diferentes requisitos. Para mí, el requisito es que la palabra del estándar POSIX actual DEBE seguirse EXACTAMENTE (o, más precisamente, lo mejor que puede ser, porque el estándar en sí es algo defectuoso). Como si fuera la palabra de Dios.
Ahora, la redacción estándar es bastante clara: no se mencionan los enlaces simbólicos, donde en muchos otros lugares, se menciona dónde debe hacerse. Entonces, en este caso, no lo hagas.
Sin embargo, siempre verifico cómo dashy cómo me bashcomporto, solo para asegurarme. Ahora, por supuesto, también hay un pequeño problema aquí, dashaunque se factura como POSIX, tiene muchos pequeños errores conformes con POSIX. bash, Todavía no he encontrado ningún error con POSIX, pero ... bash no es realmente POSIX, es mucho más que eso.
Entonces ahí lo tienes. Por eso me importa.
fuente

$PATHlata contiene enlaces simbólicos. Tratarwhich sh.$PATHno tiene enlaces simbólicos.lstat(2)), por lo general, no se indica su seguimiento. Por ejemplo, la descripción deopen(2)solo menciona enlaces simbólicos cuando se habla del comportamiento deO_CREAT | O_EXCL. No es necesario indicar que se abrirá el archivo de destino.Respuestas:
Los permisos del enlace simbólico en sí son irrelevantes. Ni siquiera podría cambiarlos si lo intentara.
Lo que importa son los permisos del archivo subyacente.
Está bien que los directorios en su RUTA incluyan enlaces simbólicos a ejecutables. De hecho, es probable que muchos ejecutables en su RUTA sean enlaces simbólicos. Por ejemplo, en sistemas debian / ubuntu-like:
Documentación
De
man chmod:Ejemplo
El shell tiene una prueba,
-xpara determinar si un archivo es ejecutable. Probemos eso:Entonces, tal como lo encontró con
which, el shell no considera un ejecutable softlink a menos que el archivo subyacente sea ejecutable.Como funciona
En un sistema Debian,
whiches un script de shell. La sección relevante del código es:Como puede ver, utiliza la
-xprueba para determinar si un archivo es ejecutable.POSIX especifica la
-xprueba de la siguiente manera:Entonces, POSIX verifica a qué se resuelve el nombre de ruta . En otras palabras, acepta enlaces simbólicos.
Función de ejecución POSIX
La función de ejecución POSIX sigue enlaces simbólicos. La especificación POSIX continúa para especificar las condiciones de error que puede informar si los enlaces simbólicos son circulares o demasiado profundos, como:
fuente
whiches un script de shell. Por lo tanto, es probable que solo esté usando la-xprueba que mostré. Según POSIX,-xprueba si un archivo "se resuelve" en un ejecutable. Si estás viendo algo diferente, ¿dónde estás mirando?whichfunciona, o si es-xo algo más. Me interesa saber dónde no sigo correctamente la documentación que cité.execsigue enlaces simbólicos. Eso parece dejar bastante claro que los archivos con enlaces simbólicos pueden ser ejecutables en POSIX.man whichque dice "No canonicaliza los nombres de ruta". Eso no significa que no siga los enlaces. Eso solo significa, como observó, que no "canoniza" los nombres.En este caso, los enlaces simbólicos se siguen de forma transparente, sin canonizar la ruta final. En otras palabras,
whichno le importa si/home/mark/bines un enlace simbólico o no. Lo que le importa es si el archivo/home/mark/bin/foobarexiste o no. No necesita aplanar manualmente los enlaces simbólicos a lo largo de la ruta; el sistema operativo puede hacerlo bien solo.Y, de hecho, cuando se
whichle pregunta acerca de la información del archivo/home/mark/bin/foobar, el sistema operativo nota que/home/mark/bines un enlace simbólico, lo sigue y lo encuentra con éxitofoobaren el directorio de destino.Este es el comportamiento predeterminado a menos que el programa use
open(…, O_NOFOLLOW)ofstatat(…, AT_SYMLINK_NOFOLLOW)para acceder al archivo.[comentarios fusionados en]
Si bien se dice que las utilidades de shell lo hacen sobre una base caso por caso, no es lo mismo con llamadas al sistema del kernel: todas las llamadas de archivos relacionados hacen seguir enlaces simbólicos por defecto, a menos que se da la opción "nofollow". (Incluso lstat sigue enlaces simbólicos en todos los componentes de la ruta excepto el último).
Cuando la especificación no menciona explícitamente qué hacer con los enlaces simbólicos, implica que se utilizará el comportamiento predeterminado. Es decir, un shell que sigue el algoritmo de ruta no resuelve los enlaces simbólicos manualmente ni excluye explícitamente que el sistema operativo haga lo mismo. (Simplemente concatena cada componente $ PATH con el nombre ejecutable).
Cuando la página del manual which (1) dice que no sigue enlaces simbólicos, puede significar varias cosas, pero la versión de GNU coreutils lo dice de esta manera:
El alcance es mucho más limitado: solo significa
whichque no intentará canonizar manualmente todas las rutas para eliminar los duplicados, pero no implica que la herramienta optará por el enlace simbólico que sigue el sistema operativo en general. Por ejemplo, si/bines un enlace simbólico a/usr/bin, la ejecuciónwhich -a shdevolverá ambos/bin/shy/usr/bin/sh.fuente
whichpágina del manual de GNU lo expresa de manera diferente: "Lo que considerará que dos directorios equivalentes son diferentes cuando uno de ellos contiene una ruta con un enlace simbólico".execve("/home/mark/bin/foobar", …), dará como resultado que se sigan todos los enlaces simbólicos.execveargumento, en realidad, en mi implementación, es loexecl()mismo. Por favor, si incluye esto en su respuesta, lo aceptaré.El shell se ajusta a su documentación en el sentido de que sigue las reglas para la resolución del nombre de ruta.
whichse ajusta a su documentación. Los dos hacen cosas ligeramente diferentes.La salida de
whiches el nombre y la ruta del archivo del enlace, no la ruta a la que apunta el enlace simbólico. Esto se explica en la página del manual.Cuando se ejecuta un comando, el enlace se "sigue" según la Sección 4.13 Resolución de nombre de ruta en el mismo . La cláusula relevante para ejecutar un archivo es:
fuente