Чому cd не є програмою?

Я завжди замислювався, чому cd не є програмою, але не вдалося знайти відповідь.

Хто-небудь знає, чому це так?

115
Я пам'ятаю, що прочитав (не можу знайти, де), що початкова команда unix cd була окремою програмою. Оболонка обробляла його спеціально тим, що вона не fork , а просто exec . І коли cd було зроблено, було б exec sh . Я не знаю, чи це справжня історія.
додано Автор John Sibly, джерело
@Mikel: Я погоджуюся, що це здається безглуздим, але я просто передавав історію про cd , яку я прочитав. Я явно помилявся в аспекті цього, тепер, коли @jlliagre заповнив подробиці.
додано Автор John Sibly, джерело
@camh, це справжня історія. Я теж прочитав це в статті, написаній Деннісом М. Річі, «Еволюція Unix-системи розподілу часу», AT&T Bell Laboratories Technical Journal 63 (6), Part 2, Oct. 1984.
додано Автор Eric Scrivner, джерело
Який буде сенс? Якщо буде додано спеціальну обробку, він може просто викликати syscall chdir . джерел: v1 v5 v7 (перша версія з Bourne) оболонка)
додано Автор Mikel, джерело

7 Відповіді

Команда cd змінює "поточний робочий каталог", чи не так?

"поточний робочий каталог" - це властивість, унікальна для кожного процесу.

Отже, якщо програма cd була програмою, вона працювала б так:

  1. cd foo
  2. the cd process starts
  3. the cd process changes the directory for the cd process
  4. the cd process exits
  5. your shell still has the same state, including current working directory, that it did before you started.
162
додано
Ваші п'ять кроків є правильними, але "якщо cd була програмою, яка працювала б так, як" повинна бути ", коли cd використовується у його зовнішній реалізації програми, вона працює так ".
додано Автор Eric Scrivner, джерело
Не будучи системним програмістом, і не маючи глибоких знань про інтерактивні взаємодії з оболонкою, я б очікував, що оболонка відкриє поточний робочий каталог, а cd - програма, яка звертається і змінює цю властивість. Розуміння, після перегляду цієї відповіді, що це, ймовірно, не оптимально, як це дійсно працює з багатьох причин.
додано Автор p01nd3xt3r, джерело

cd in addition to being a shell builtin, is actually also a program on POSIX compliant OSes. They must provide independent executables for regular utilities, like cd. This is for example the case with Solaris, AIX, HP-UX and OS X.

Очевидно, що вбудований cd як і раніше є обов'язковим, оскільки його зовнішня реалізація не змінює поточний каталог оболонки. Однак останнє може бути корисним. Ось приклад, що показує, як POSIX уявляє, як можна використовувати цю команду cd :

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

У системі POSIX цей oneliner повідомить про помилку для всіх каталогів, у яких ви не маєте права cd . На більшості дистрибутивів Gnu/Linux воно виходить з цього повідомлення про помилку, хоча:

find: `cd': No such file or directory

Ось відповідь на ваше запитання: " Чому cd не є програмою? " одним з оригінальних співавторів Unix. На початку реалізації Unix, cd (написаний chdir у той час) був зовнішньою програмою. Він несподівано припинив роботу після першої реалізації fork .

Цитуючи Денніс Рітчі :

У період нашої радості було виявлено, що команда chdir (change current directory) перестала працювати. Існував багато читання коду і тривожний самоаналіз про те, як додавання вилки могло б порушити дзвінок chdir. Нарешті вийшла правда: у старій системі chdir була звичайною командою; він скоригував поточний каталог (унікального) процесу, приєднаного до терміналу. Під новою системою команда chdir правильно змінила поточний каталог процесу, створеного для його виконання, але цей процес негайно завершився і не мав ніякого впливу на його батьківську оболонку! Потрібно було зробити chdir спеціальною командою, що виконується всередині оболонки. Виявляється, що декілька функцій, подібних до команд, мають одне і те ж властивість, наприклад, login.

Source: Dennis M. Ritchie, “The Evolution of the Unix Time-sharing System”, AT&T Bell Laboratories Technical Journal 63(6), Part 2, Oct. 1984, pp.1577–93

Версія Unix 1 (березень 1971) chdir сторінка вручну говорить:

Оскільки створено новий процес для виконання кожної команди, chdir був би неефективним, якщо б він був написаний як нормальний команду. Тому він визнається та виконується Оболонка.

97
додано
Це з OSX 10.7.2 cat/usr/bin/cd #!/bin/sh # $ FreeBSD: src/usr.bin/alias/generic.sh, v 1.2 2005/10/24 22:32:19 cperciva Exp $ # Цей файл знаходиться у вільному доступі. вбудований echo $ {0 ## * /} | tr [: upper:] [: lower:] `$ {1 +" $ @ "}` так що єдиним, що він робить, є аліас, щоб виконати вбудовану команду
додано Автор Nick Watts, джерело
@Kaz: якщо простежити виконання обох варіантів, то в обох випадках з'явиться виклик системного виклику chdir. Це те, що я маю на увазі з "Вони роблять те ж саме".
додано Автор Eric Scrivner, джерело
@Warren Young Дякуємо
додано Автор Eric Scrivner, джерело
Звичайно, я знаю, що командний ефект на викликає оболонку відрізняється, але це просто семантика. Скажімо, моє визначення "робити те ж саме" - це "внести $ 100 на банківський рахунок", тоді чиїм рахунком це не має значення.
додано Автор Eric Scrivner, джерело
@Kaz: Будь ласка, не називайте мене дурним, поки я просто повідомляю про факт. Ви можете погодитися або не погодитися з POSIX, але не стріляти посланника.
додано Автор Eric Scrivner, джерело
@Kaz, вони не зовсім різні речі. Вони роблять те ж саме, але тільки вбудований один впливає на поточну оболонку.
додано Автор Eric Scrivner, джерело
@Nils Усі реалізації оболонки Unix забезпечують вбудований компакт-диск. Не виконати це було б досить складно (потрібно було б, щоб оболонка надала можливість для зовнішнього процесу передавати цю інформацію) і досить ризикованою.
додано Автор Eric Scrivner, джерело
Всі оболонки в основному реалізують компакт-диск так само, наприклад, за допомогою виклику chdir: pubs.opengroup .org/onlinepubs/9699919799/functions/chdir.htm & zwnj; l
додано Автор Eric Scrivner, джерело
@Jarrod Robertson Кожен постачальник Unix може вільно реалізовувати ці команди так, як йому подобається. Оскільки вбудований cd і зовнішній cd повинні вести себе так само, викликає вбудовану реалізацію з скрипта дійсно і мудро.
додано Автор Eric Scrivner, джерело
@Kaz: див. Попередній коментар.
додано Автор Eric Scrivner, джерело
@Ilmari Karonen: Неправильно заявляти, що команда cd нічого не робить. Це перевіряє, чи можна змінити ваш каталог на наданий аргумент, і повертає відповідний статус.
додано Автор Eric Scrivner, джерело
@Totor Ви повинні прочитати повний абзац: "усі стандартні утиліти, включаючи регулярні вбудовані в таблиці, але не спеціальні вбудовані модулі, описані в спеціальних вбудованих утилітах, повинні бути реалізовані таким чином, щоб вони може бути доступний через Exec-сімейство функцій, як визначено в обсязі System Interfaces POSIX.1-2008, і можуть бути викликані безпосередньо тими стандартними утилітами, які його потребують "
додано Автор Eric Scrivner, джерело
@jlliagre: Вилучено мій коментар і -1. Ви праві, POSIX, здається, говорить, що зовнішній cd повинен існувати. Bizarre.
додано Автор Warren Young, джерело
Компакт-сторінка POSIX також говорить: "Оскільки cd впливає на поточне виконання оболонки середовище, він завжди передбачений як оболонка звичайної вбудованої. ".
додано Автор Mikel, джерело
Це цікаво. Наведене посилання означає, що cd - це "звичайна вбудована утиліта", яка "повинна бути реалізована таким чином, щоб їх можна було отримати через сімейство exec функцій [...] і можуть бути викликані безпосередньо тими стандартними утилітами, які потребують цього ( env , find , nice , nohup , < код> час , xargs ) ". Проте специфікація для cd сама говорить, що "якщо вона викликається в підгрупі або окремому середовищі виконання утиліти, [...] вона не впливає на робочий каталог середовища, що викликає."
додано Автор Scott McMillin, джерело
... отже, мабуть, POSIX зобов'язує, що має бути незалежний cd виконуваний файл, але він нічого не робитиме (за винятком, можливо, випускає повідомлення про помилку, якщо буде викликано неправильні аргументи). Дивно.
додано Автор Scott McMillin, джерело
Цікаво. але чи є оболонка, яка не реалізує cd як вбудовану команду і фактично викликає цю зовнішню команду?
додано Автор Ero Sɘnnin, джерело
Тому зовнішній cd має сенс, якщо ви хочете перевірити, якщо ви в змозі успішно виконати вбудований cd . Великий - це саме те, що мені зараз потрібно для мого сценарію ...
додано Автор Ero Sɘnnin, джерело
@Totor так Linux не Posix. Нічого нового тут.
додано Автор Ero Sɘnnin, джерело
@jlliagre Хороші речі. Дякуємо, що вказали це.
додано Автор George M, джерело
Так що дозвольте мені отримати це прямо ... якщо я повинен був зробити свою оболонку для Unix, я повинен був б обробляти конкретний випадок CD? Чому вона навіть існує в першу чергу, якщо кожна програма Shell реалізує інший диск?
додано Автор Catija, джерело
Кричущим жахом є те, що я можу зробити/usr/bin/cd, який змінює робочий каталог оболонки, але підказка не оновлюватиметься, коли ви її запустите.
додано Автор Aaron K., джерело
@jlliagre Mea culpa, ви маєте рацію. Моя система Debian не поважає цей POSIX-ness, боюся ...
додано Автор Totor, джерело
@jlliagre @Nils @IlmariKaronen Вони cd ! Сторінка, на яку ви посилаєтеся, говорить: "Утиліти, названі у звичайних вбудованих утилітах [ cd є однією з них", часто надаються у вбудованій формі ". Сторінка cd говорить: "Оскільки cd впливає на поточне середовище виконання оболонки, воно завжди надається як звичайна вбудована оболонка". Чому ви говорите, що вони повинні існувати як зовнішня програма?
додано Автор Totor, джерело
@jlliagre Видалено мій перший коментар і +1 для покращеної версії вашої відповіді.
додано Автор M.A. Golding, джерело
@jlliagre Я не використовував слово "виконуваний", і я нічого не розумію взагалі. Я просто хотів сказати, що на моїй ОС X програма, яка змінює робочий каталог оболонки, є самою оболонкою.
додано Автор M.A. Golding, джерело
@Rudolf Яке визначення "програми" ви використовуєте тут? ІМХО скрипт це програма, це просто, ну, scripty :) але це все ж таки ряд команд, які інтерпретуються комп'ютером для виконання завдання, і які можуть бути збережені і запущені повторно.
додано Автор user18928, джерело
Ну, якщо це правда, це не було б найдипломніше в POSIX.
додано Автор Nathan V, джерело
@jiliagre "Вони роблять те ж саме, але тільки вбудований один впливає на поточну оболонку" означає, що вони не роблять те ж саме. Я не розумію, як можна навіть написати речення цієї форми, а потім натиснути Enter. :)
додано Автор Nathan V, джерело
Операція виконує тільки те ж саме, якщо вона є тією ж операцією, що працює в тому ж середовищі/області на тій же самій точці. chdir має прихований неявний аргумент: ідентифікатор викликає процесу, на чиїй поточній змінної робочого каталогу він працює. Це означає, що chdir в процесі A і chdir в процесі B не є тією ж операцією (навіть якщо вони викликаються з однаковим абсолютним шляхом). Подумайте про транзакцію бази даних. Чи є депозит у розмірі 100 доларів на мій банківський рахунок така ж операція, як депозит у розмірі 100 доларів на ваш банківський рахунок? Якщо так, то не заперечуйте, якщо банк змішує їх.
додано Автор Nathan V, джерело
Таким чином, для всіх цілей і цілей, /usr/bin/cd і cd - цілком різні речі.
додано Автор Nathan V, джерело

Від введення Bash ( Що таке оболонка? ):

Оболонки також надають невеликий набір вбудованих команд (вбудованих)   реалізація функціональності неможлива або незручна для отримання через   окремі комунальні послуги. Наприклад, cd , break , continue і    exec ) не може бути реалізовано за межами оболонки, оскільки вони   безпосередньо маніпулювати самою оболонкою. історія , getopts ,   Вбудовані kill або pwd , зокрема, можуть бути реалізовані в   окремі утиліти, але вони зручніше використовувати як вбудовані   команд. Всі вбудовані оболонки описані в подальшому   розділів.

45
додано

У квітні цього року я написав окрему версію коду cd .

Ніхто не отримав жарт. Зітхання.

Будь-хто, хто не впевнений, що cd повинен бути вбудований в оболонку, повинен його завантажити, побудувати і спробувати.

Ознайомтеся з його людиною. :)

28
додано
Добре, що ви бачите, як хтось працює над створенням Gnu/Linux більш сумісним з POSIX. Ваша реалізація не тільки хороша жарт, але насправді щось відсутнє в дистрибутивах Linux ...
додано Автор Eric Scrivner, джерело
Я думаю, що збираюся повторити наступного року, посилаючись на проблему POSIX. ;)
додано Автор Warren Young, джерело
Дуже корисний код! :-)
додано Автор Akash Dubey, джерело

Команда cd в оболонці не може бути окремим процесом, оскільки в Unix немає механізму зміни поточного робочого каталогу іншого процесу (навіть не батьківського процесу).

Якщо cd був іншим процесом, то він міг би змінити поточний робочий каталог батьківського (оболонки), який неможливий в Unix. Натомість cd - спеціальна вбудована команда. Оболонка викликає такі функції, як chdir() і fchdir() , які змінюють власний поточний робочий каталог.

Примітка: ядро ​​зберігає номер inode поточного робочого каталогу для кожного процесу. Дочірній процес успадковує його cwd від свого батька.

4
додано

Мені здається, що в людині відсутня відповідь на те, що поточний каталог - це змінна середовища, яку кожна програма може змінити. Якщо ви використовуєте команду "export", щоб побачити список поточних змінних середовища, ви матимете:

declare -x PWD="/home/erfan"

у результатах. Таким чином, командою "cd" ми просто хочемо змінити цю внутрішню змінну. Я думаю, якщо ми спробуємо, ми можемо змінювати PWD-змінну будь-якого pty в оболонці, звичайно. Люблю:

cder    #change current PTY $PWD variable

Але я думаю, що немає потреби в звичайних випадках. Іншим словом, ми використовуємо допомогу від bash (або будь-якої оболонки) для зміни визначеної внутрішньої змінної.

1
додано
Хоча це правда, що оболонки Борна виставляють поточний робочий каталог (CWD) як $ PWD, тобто не є основним місцем зберігання; фактичне розташування знаходиться в структурі ядра. Тому неправильно сказати, що CWD "є змінною середовища". Якщо він працював так, як ви запропонували, цей двома лайнерами С буде виводити шлях .. , а не шлях, з якого його було запущено, з: code> int main (void) {chdir (".."); ставить (getenv ("PWD")); } (C оболонки виставляють CWD як% cwd замість цього).
додано Автор Warren Young, джерело
Це просто замінить значення змінної, без побічних ефектів на CWD. Це кращий тест, щоб показати, що: #include int main (void) {char ac [99]; setenv ("PWD", "/", 1); puts (getcwd (ac, sizeof (ac))); } Він покаже папку, з якої ви запустили програму, а не /.
додано Автор Warren Young, джерело
Ні, я кажу вам, що $ PWD має значення тільки для оболонки Bourne. Це лише спосіб для оболонки повідомляти щось, що він знає, до скриптів оболонки, щоб вони не повинні викликати pwd , щоб знайти її. Будь-яка окрема програма в залежності від значення $ PWD буде ненадійною.
додано Автор Warren Young, джерело
Я думаю, що кожен процес має змінну робочого каталогу і шляху. Таким чином ви chdir просто змінюєте цей атрибут процесу. Оболонка також має цей атрибут, а компакт-диск змінює цей атрибут.
додано Автор Octavarium, джерело
дозволяє додати інші додатки до вашого додатка. #include int main (void) {chdir (".."); ставить (getenv ("PWD")); setenv (P "PWD", "/", 1); ставить (getenv ("PWD")); } Що ми матимемо як результати?
додано Автор Octavarium, джерело

cd - це вбудована команда оболонки. Так само просто. Людина CD говорить все це. команда cd змінює робочий каталог для всіх перекладачів і (у потоковому середовищі) всі потоки.

0
додано
Існує дуже хороша технічна причина, що cd вбудовано. Я б радив вам прочитати відповіді з найвищим рейтингом і розглянути, як можна поліпшити вашу відповідь.
додано Автор Swaroop C H, джерело
Але він відповідає на питання чому .
додано Автор Swaroop C H, джерело
Тому що оболонка - це середовище, яке піклується про ваші поточні робочі директиви ($ PDW ...) або cdable_vars. Цей вбудований в кінцевому підсумку спосіб, яким всі видимі користувачем команди повинні змінити поточний робочий каталог. Ви можете перевірити його таким чином: скомпілюйте bash без cd.c і спробуйте написати власний cd-скрипт, який намагається подбати про всі середовища cdable_vars. Це питання також більше стосується розробників. Б'юся об заклад, що вони могли б відповісти на це питання більш детально.
додано Автор Alan Sparks, джерело
Найвища відповідь була найгіршою, яку я коли-небудь читав! Але так? Хто я!
додано Автор Alan Sparks, джерело