¿Por qué cd no es un programa?

129

Siempre me he preguntado por qué cdno es un programa, pero nunca logré encontrar la respuesta.

Alguien sabe por qué este es el caso?

AkshaiShah
fuente
1
Recuerdo haber leído (no puedo encontrar dónde) que el cdcomando original de Unix era un programa separado. El caparazón lo manejó especialmente porque no lo hizo fork, solo exec. Y cuando cdterminara, se ejecutaría sh. No sé si esta es una historia real.
camh
¿Cuál sería el punto? Si va a agregar un manejo especial, también podría llamar a chdirsyscall. fuentes: v1 v5 v7 (primera versión con Bourne shell)
Mikel
2
@camh, es una historia real. También lo he leído en un artículo escrito por Dennis M. Ritchie, "La evolución del sistema de tiempo compartido Unix", AT&T Bell Laboratories Technical Journal 63 (6), Parte 2, octubre de 1984.
jlliagre
@Mikel: Estoy de acuerdo en que parece inútil, pero solo estaba transmitiendo una historia sobre cdeso que había leído. Estaba claramente equivocado sobre el aspecto, ahora que @jlliagre ha completado los detalles.
camh

Respuestas:

172

El cdcomando modifica el "directorio de trabajo actual", ¿verdad?

El "directorio de trabajo actual" es una propiedad exclusiva de cada proceso.

Entonces, si cdfuera un programa, funcionaría así:

  1. cd foo
  2. el cdproceso comienza
  3. el cdproceso cambia el directorio para el proceso de cd
  4. el cdproceso sale
  5. su shell todavía tiene el mismo estado, incluido el directorio de trabajo actual, que tenía antes de comenzar.
Daniel Pittman
fuente
8
Sus cinco pasos son correctos pero "si cdfuera un programa funcionaría así" debería ser "cuando cdse utiliza en la implementación de su programa externo, funciona así".
jlliagre
1
Al no ser un programador de sistemas, ni tener un conocimiento profundo de los entresijos de la interacción con el shell, habría esperado que el shell exponga su directorio de trabajo actual y que cd sea un programa que acceda y altere esa propiedad. Entendiendo, después de ver esta respuesta, que eso probablemente sea subóptimo de cómo funciona realmente por muchas razones.
Jason
108

cdAdemás de ser un shell integrado, en realidad también es un programa en sistemas operativos compatibles con POSIX. Ellos deben proporcionar ejecutables independientes para los servicios públicos regulares, como cd. Este es por ejemplo el caso con Solaris , AIX , HP-UX y OS X .

Obviamente, un builtin cdsigue siendo obligatorio ya que su implementación externa no cambia el directorio actual del shell. Sin embargo, este último todavía puede ser útil. Aquí hay un ejemplo que muestra cómo POSIX imagina cómo se cdpodría usar este comando:

find . -type d -exec cd {} \;

En un sistema POSIX, este oneliner informará un mensaje de error para todos los directorios en los que no está permitido cd. Sin embargo, en la mayoría de las distribuciones de Gnu / Linux, falla con ese mensaje de error:

find: `cd': No such file or directory

Y aquí está la respuesta a su pregunta, " ¿Por qué cd no es un programa? " Por uno de los coautores originales de Unix. En una implementación muy temprana de Unix, cd(escrito chdiren ese momento) era un programa externo. Simplemente dejó de funcionar inesperadamente después de que forkse implementó por primera vez.

Citando a Dennis Ritchie :

En medio de nuestro júbilo, se descubrió que el comando chdir (cambiar el directorio actual) había dejado de funcionar. Hubo mucha lectura de código e introspección ansiosa sobre cómo la adición de fork podría haber roto la llamada del chdir. Finalmente la verdad amaneció: en el viejo sistema chdir era un comando ordinario; ajustó el directorio actual del proceso (único) conectado al terminal. Bajo el nuevo sistema, el comando chdir cambió correctamente el directorio actual del proceso creado para ejecutarlo, ¡pero este proceso terminó rápidamente y no tuvo ningún efecto en su shell principal! Era necesario hacer de chdir un comando especial, ejecutado internamente dentro del shell. Resulta que varias funciones similares a comandos tienen la misma propiedad, por ejemplo, inicio de sesión.

Fuente: Dennis M. Ritchie, " La evolución del sistema de tiempo compartido Unix ", AT&T Bell Laboratories Technical Journal 63 (6), Parte 2, octubre de 1984, págs. 1577–93

La página de manual de chdir de Unix Versión 1 (marzo de 1971) dice:

Debido a que se crea un nuevo proceso para ejecutar cada comando, chdir sería ineficaz si se escribiera como un comando normal. Por lo tanto, es reconocido y ejecutado por Shell.

jlliagre
fuente
10
... entonces, aparentemente, POSIX exige que haya un cdejecutable independiente , pero que no haga nada (excepto posiblemente emitir mensajes de error si se llama con los argumentos incorrectos). Extraño.
Ilmari Karonen
44
Bueno, si es verdad, eso no sería lo más estúpido en POSIX.
Kaz
55
La página POSIX cd también dice "Dado que cd afecta el entorno actual de ejecución del shell, siempre se proporciona como un shell incorporado regularmente".
Mikel
66
@Kaz, no son cosas completamente diferentes. Hacen lo mismo pero solo el incorporado afecta al caparazón actual.
jlliagre
13
@Kaz: Por favor no me llames tonto mientras solo estoy informando un hecho. Puede estar de acuerdo o en desacuerdo con POSIX, pero no dispare al mensajero.
jlliagre
47

De la introducción de Bash ( ¿Qué es un shell? ):

Los shells también proporcionan un pequeño conjunto de comandos integrados (incorporados) que implementan funcionalidades imposibles o inconvenientes de obtener a través de utilidades separadas. Por ejemplo, cd, break, continue, y exec) no puede ser implementado fuera de la carcasa, ya que manipular directamente el depósito propiamente dicho. El history, getopts, kill, o pwdlas órdenes internas, entre otros, podrían ser implementadas en utilidades separadas, sino que son más convenientes de utilizar comandos como incorporadas. Todas las conchas incorporadas se describen en secciones posteriores.

cjc
fuente
29

Para April Fool's este año, escribí una versión independiente decd .

Nadie entendió el chiste. Suspiro.

Cualquiera que no esté seguro de que cddebe integrarse en el shell debe descargarlo, compilarlo y probarlo.

Lea también su página de manual. :)

Warren Young
fuente
Código realmente útil! :-)
dschulz
66
Es bueno que veas a alguien trabajando para hacer que Gnu / Linux sea más compatible con POSIX. Su aplicación no es sólo una buena broma, pero en realidad algo que falta en las distribuciones de Linux ...
jlliagre
8
Creo que volveré a intentarlo el próximo año, citando el problema POSIX. ;)
Warren Young
6 años después: Bueno, ¿y tú?
Peter A. Schneider
@ PeterA.Schneider: Pensé que estaba claro que estaba bromeando, así que para ser claros, no, en realidad no voy a gastar un montón de esfuerzo tratando de incluir esto en sistemas operativos y proyectos similares a sistemas operativos como Cygwin que actualmente la falta /bin/cd. Si desea tomar mi código y hacer que sea su propia búsqueda personal, puede hacerlo.
Warren Young
4

El cdcomando en shell no puede ser un proceso separado porque en Unix no hay ningún mecanismo para cambiar el directorio de trabajo actual de un proceso diferente (ni siquiera el proceso padre).

Si cdse tratara de un proceso diferente, entonces tendría que cambiar el directorio de trabajo actual de su padre (shell) que no es posible en Unix. En cambio, cdes un comando especial incorporado. El shell llama a funciones chdir()y fchdir() cambia su propio directorio de trabajo actual.

Nota: el núcleo almacena el número de inodo del directorio de trabajo actual para cada proceso. El proceso hijo lo hereda cwdde su padre.

saurav1405
fuente
0

cd es un comando de shell incorporado. Tan fácil como es. El cd del hombre lo dice todo. El comando cd cambia el directorio de trabajo para todos los intérpretes y (en un entorno de subprocesos) todos los subprocesos.


fuente
Porque el shell es el entorno que se ocupa de sus directorios de trabajo actuales ($ PDW ...) o cdable_vars. Esta construcción es, en última instancia, la forma en que todos los comandos visibles para el usuario deberían cambiar el directorio de trabajo actual. Puede probarlo de esa manera: compile el bash sin cd.c e intente escribir su propio script cd, que trata de cuidar todo el entorno cdable_vars. Esta pregunta también está más relacionada con un desarrollador. Apuesto a que podrían responderte esta pregunta con más detalle.
2
Hay una muy buena razón técnica que cdestá incorporada. Le sugiero que lea las respuestas mejor calificadas y considere cómo se puede mejorar su respuesta.
Thorbjørn Ravn Andersen
¡La respuesta mejor calificada fue la peor que he leído! Pero eh? ¡Quién soy!
3
Pero responde a la pregunta de por qué .
Thorbjørn Ravn Andersen
-1

Creo que una cosa que falta en la respuesta de la gente es que el directorio actual es una variable de entorno que cada programa puede cambiar. Si usa el comando 'exportar' para ver su lista actual de variables de entorno, tendrá:

declare -x PWD="/home/erfan"

en sus resultados Por lo tanto, mediante el comando 'cd' solo queremos modificar esta variable interna. Creo que si lo intentamos, podemos cambiar la variable PWD de cualquier pty en shell, por supuesto. Me gusta:

cder    #change current PTY $PWD variable

Pero creo que no hay necesidad en casos normales. En otras palabras, tomamos ayuda de bash (o cualquier shell) para modificar su variable interna definida.

Erfankam
fuente
3
Si bien es cierto que los shells Bourne exponen el directorio de trabajo actual (CWD) como $ PWD, esa no es la ubicación de almacenamiento principal; la ubicación real está en la estructura por proceso del núcleo. Por lo tanto, es incorrecto decir que el CWD "es una variable de entorno". Si funcionó de la manera que usted sugiere, este C dos-liner imprimirá el ..camino, no el camino desde el que lo inició: #include <stdlib.h> int main(void) { chdir(".."); puts(getenv("PWD")); }(C shells exponen el CWD como% cwd en cambio, por cierto.)
Warren Young
agreguemos algunas otras líneas a su aplicación. #include <stdlib.h> int main (void) {chdir (".."); pone (getenv ("PWD")); setenv (P "PWD", "/", 1); pone (getenv ("PWD")); } ¿Qué tendremos como resultados?
Erfankam
3
Eso solo sobrescribirá el valor de una variable, sin efectos secundarios en el CWD. Esta es una mejor prueba para demostrar que: #include <unistd.h> int main(void) { char ac[99]; setenv("PWD", "/", 1); puts(getcwd(ac, sizeof(ac))); }No mostrará el directorio desde el que inició el programa /.
Warren Young
Creo que cada proceso tiene un directorio de trabajo y una variable de ruta también. Por lo tanto, por chdir simplemente cambia este atributo de proceso. Shell también tiene este atributo y con cd modificamos este atributo.
Erfankam
44
No, te digo que eso $PWDsolo tiene sentido para el shell Bourne. Es solo una forma de que el shell comunique algo que sabe a los scripts de shell para que no tengan que llamar pwdpara encontrarlo. Cualquier programa independiente que dependa del valor de $PWDno será confiable.
Warren Young