Зачем мне удалять CD из удаленной директории?

На моем сервере у меня есть структура каталогов, которая выглядит примерно так:

/myproject/code 

Обычно у меня есть ssh-соединение с сервером и «stand» в этом каталоге:

 root@machine:/myproject/code# 

Когда я развертываю новую версию своего кода, каталог кода удаляется, поэтому мне остается:

 root@machine:/myproject/code# ./run -bash: ./run: No such file or directory 

И единственным решением, которое я нашел, является выход из системы и обратно:

 root@machine:/myproject/code# cd ../code root@machine:/myproject/code# ./run Running... 

Могу ли я избежать этого? Это несколько странное поведение. Если у вас есть хорошее объяснение, почему это происходит, я был бы признателен.

6 Solutions collect form web for “Зачем мне удалять CD из удаленной директории?”

Для меня «cd ../code» – это noop. Мне очень интересно узнать, почему это не так.

Поскольку файлы и каталоги в основном являются файловыми inodes , а не именами – это, возможно, деталь реализации, характерная для типа файловой системы, но она верна для всех систем ext, поэтому я буду придерживаться ее здесь.

Когда создается новый code каталога, он связан с новым inode, и именно там. Нет записи о ранее удаленных файлах и каталогах, поэтому нет средств, с помощью которых система могла бы проверить, какой inode она использовала, чтобы занять и, возможно, перетасовать вещи вокруг, так что это будет снова и снова; такая система быстро станет неработоспособной, и в любом случае это, вероятно, не гарантирует, что вы вернетесь туда снова – это будет своего рода нежелательным, так как это означает, что вы также можете случайно оказаться где-то в другом месте, если каталог создан который принимает ваш (в настоящее время неиспользуемый) inode.

Я не уверен, существует ли эта последняя возможность или если inode удаленной директории, назначенной в текущий рабочий каталог, отслеживается так, что на нее не будет назначено какое-либо время и т. Д.

Ваша оболочка не каждый раз делает cd к пути, в котором она находилась во время последней команды, перед выполнением следующей команды.

Вы удалили текущий каталог и создали каталог с тем же именем, которое не является тем же самым каталогом, просто с тем же именем / путем.

Файловые браузеры, такие как Nautilus и Windows Explorer, обычно «поднимаются» по дереву каталогов, если каталог удаляется в локальной файловой системе. Однако это не всегда верно для сетевых файловых систем, в этом случае иногда удаление не замечается, и повторное появление может привести к тому, что вы попадете в новый каталог.

Оболочка могла бы cd в текущий каталог перед выполнением следующей команды, я не знаю, что делать (или может быть настроено для этого).

В большинстве UNIX-подобных систем «текущий каталог» для процесса хранится в ядре в виде файлового дескриптора, указывающего на этот каталог. Ядро фактически не сохраняет путь к текущему каталогу: эта информация отслеживается вашей оболочкой.

Объект файловой системы (файл или каталог) уничтожается только тогда, когда все ссылки на файловую систему исчезли, и нет дескрипторов файлов, указывающих на этот объект.

Таким образом, если каталог удаляется, а процесс cwd оставаться его текущим рабочим каталогом, то cwd процесса будет полностью cwd каталог. Ссылки файловой системы, которые привязывают каталог (его запись в родительском каталоге и все его содержимое), исчезнут, но сама директория будет продолжать существовать как своего рода «зомби». Между тем, вы можете создать совершенно новый каталог в том же месте, что и старый, который является совершенно другим объектом файловой системы, но который имеет один и тот же путь.

Таким образом, когда вы делаете cd ../code (или, во многих оболочках, cd . ), Вы фактически обходите иерархию файловой системы и переходите в новый каталог, который находится на прежнем адресе.

По аналогии, удаление каталога будет походить на принудительное перемещение дома в мусорный дамп (разрыв связей с предыдущим адресом). Если бы кто-то жил там (используя его как свою cwd ), они должны были уйти, прежде чем дом может быть снесен. Между тем, по старому адресу можно было построить совершенно новый дом.

@Anthon очистил причины, почему это происходит
В качестве решения вы можете использовать псевдоним , например:

 alias 1234='PROJECT=`pwd`; cd $PROJECT ; ./run' 

псевдонимы для bash keept в ~ / .bashrc

Подтверждение Текущий рабочий каталог IS основан на номере inode, а не на том, что вы искали, чтобы добраться туда. Поскольку вы используете bash, вы можете использовать $ PWD следующим образом: cd для нового каталога с тем же именем:

cd $ PWD

Чтобы проиллюстрировать это, я применил команду «dummy deploy»:

 set -x cd ~/tmp rm -rf code mkdir code echo echo hello from $* > code/run chmod +x code/run 

Создал первое развертывание, cd'd для кода, а затем проверил содержимое с помощью ls -lai чтобы вы могли видеть inodes:

 ianh@abe:~/tmp$ ./,deploy first ++ cd /home/ianh/tmp ++ rm -rf code ++ mkdir code ++ echo echo hello from first ++ chmod +x code/run ianh@abe:~/tmp$ cd code ianh@abe:~/tmp/code$ ls -lai total 12 22945913 drwxr-xr-x 2 ianh ianh 4096 Apr 9 23:12 . 22937618 drwxrwxr-x 14 ianh ianh 4096 Apr 9 23:12 .. 22939455 -rwxr-xr-x 1 ianh ianh 22 Apr 9 23:12 run 

Теперь запустите второе развертывание

 ianh@abe:~/tmp/code$ ../,deploy 2nd ++ cd /home/ianh/tmp ++ rm -rf code ++ mkdir code ++ echo echo hello from 2nd ++ chmod +x code/run 

И проверьте содержимое каталога … теперь в каталоге нет ничего! даже не '.' а также '..'! Из этого вы можете видеть, что bash не использует запись каталога «..» при запуске cd .. так как «..» больше не существует – я предполагаю его часть обработки $ PWD. Некоторые другие / старые оболочки не обрабатывают cd .. в этой ситуации вам нужно сначала cd перейти к абсолютному пути.

 ianh@abe:~/tmp/code$ ls -lai total 0 

Cd до $PWD и повторите попытку:

 ianh@abe:~/tmp/code$ cd $PWD ianh@abe:~/tmp/code$ ls -lai total 12 22945914 drwxr-xr-x 2 ianh ianh 4096 Apr 9 23:12 . 22937618 drwxrwxr-x 14 ianh ianh 4096 Apr 9 23:12 .. 22939455 -rwxr-xr-x 1 ianh ianh 20 Apr 9 23:12 run ianh@abe:~/tmp/code$ ./run hello from 2nd 

Обратите внимание, как изменился индекс для текущего каталога (.)?

Если ваш сценарий развертывания переместил старый каталог на другое имя, например mv code code.$$ в вышеприведенном сценарии развертывания, то ./run будет работать, но пока вы не будете использовать cd $PWD вы будете запускать старый код, а не новый.

 ianh@abe:~/tmp/code$ ./run hello from 2nd ianh@abe:~/tmp/code$ ../,deploy 3rd ++ cd /home/ianh/tmp ++ '[' -d code ']' ++ mv code code.9629 ++ mkdir code ++ echo echo hello from 3rd ++ chmod +x code/run ianh@abe:~/tmp/code$ ./run hello from 2nd ianh@abe:~/tmp/code$ cd $PWD ianh@abe:~/tmp/code$ ./run hello from 3rd 

Развертывание с использованием capistrano имеет ту же проблему (у них есть символическая ссылка от имени, текущего до текущей версии), поэтому я использую псевдонимы для cd для производственных / промежуточных областей, а также для установки RAIL_ENV соответственно:

 alias cdp='export RAILS_ENV=production; echo RAILS_ENV=$RAILS_ENV ; cd /var/www/www.example.com/current' alias cds='export RAILS_ENV=staging; echo RAILS_ENV=$RAILS_ENV ; cd /var/www/staging.example.com/current' 

Я предполагаю, что путь – это то, что идентифицирует каталог.

Путь к чему-то – это то, как вы туда попадаете, а не сама вещь. Путь к вашей кровати может быть через вашу комнату, но как только вы окажетесь в постели, если кто-то возьмет ее и выведет на улицу, вы больше не находитесь в своей комнате.

Linux и Unix - лучшая ОС в мире.