삭제 된 디렉토리에서 CD를 꺼내야하는 이유는 무엇입니까? 같이 남습니다. root@machine:/myproject/code#

내 서버에는 다음과 같은 디렉토리 구조가 있습니다.

/myproject/code

나는 일반적으로 서버에 ssh 연결을하고 해당 디렉토리에 ‘스탠드’합니다.

root@machine:/myproject/code#

새 버전의 코드를 배포하면 코드 디렉토리가 제거되어 다음과 같이 남습니다.

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

그리고 내가 찾은 유일한 해결책은 cd out and back in입니다.

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

이것을 피할 수 있습니까? 다소 이상한 행동입니다. 왜 이런 일이 일어나는지 설명해 주시면 감사하겠습니다.



답변

나에게 “cd ../code”는 noop이다. 왜 그렇지 않은지 듣고 싶습니다.

파일과 디렉토리는 기본적으로 이름이 아닌 파일 시스템 inode 이기 때문에 이것은 파일 시스템 유형에 특정한 구현 세부 사항 일 수 있지만 모든 확장 시스템에 적용되는 것이기 때문에 여기에 충실하겠습니다.

디렉토리 code가 작성 되면 디렉토리 와 연관되며 여기에 있습니다. 이전에 삭제 된 파일과 디렉토리에 대한 기록이 없으므로 시스템이 어떤 inode를 점유하고 무엇을 뒤섞어 다시 동일하게 사용할 수 있는지 확인할 수있는 방법이 없습니다. 이러한 시스템은 빠르게 작동 할 수 없게되며, 어쨌든 다시 돌아온다는 보장은 없습니다. 디렉토리를 만들면 우연히 다른 곳에서 종료 될 수 있기 때문에 바람직하지 않습니다. (현재 사용하지 않는) inode를 가져옵니다.

이 마지막 가능성이 존재하는지 또는 현재 작업 디렉토리에 현재 할당 된 삭제 된 디렉토리의 inode가 추적되어 기간 동안 아무것도 지정되지 않도록 확실하지 않습니다.


답변

항상 cd다음 명령을 실행하기 전에 마지막 명령 동안 있었던 경로를 수행 하지는 않습니다 .

현재 디렉토리를 삭제하고 동일한 이름이 아닌 동일한 이름의 디렉토리를 작성했습니다. 동일한 디렉토리가 아니라 동일한 이름 / 경로를 가진 디렉토리입니다.

노틸러스 및 Windows 탐색기와 같은 파일 브라우저는 디렉토리가 로컬 파일 시스템에서 삭제되면 일반적으로 디렉토리 트리를 “가동”시킵니다. 그러나 이것은 네트워크 파일 시스템의 경우 항상 해당되는 것은 아니며,이 경우 때때로 삭제가 통지되지 않고 다시 나타나서 새 디렉토리에서 종료 될 수 있습니다.

쉘은 cd다음 명령을 실행하기 전에 현재 디렉토리로 들어갈 수 있습니다. 이를 알지 못하거나 그렇게 구성 할 수 있습니다.


답변

대부분의 UNIX 유사 시스템에서 프로세스의 “현재 디렉토리”는 해당 디렉토리를 가리키는 파일 디스크립터로 커널에 저장됩니다. 커널은 실제로 현재 디렉토리의 경로를 저장하지 않습니다 : 해당 정보는 쉘에 의해 추적됩니다.

파일 시스템 오브젝트 (파일 또는 그것에 모든 파일 시스템 링크가 사라 졌어요 때 디렉토리)에만 이익을 위해 파괴, 그리고 그 객체를 가리키는 어떤 파일 설명이 없습니다.

따라서 디렉토리를 현재 작업 디렉토리로 유지하는 프로세스가있는 동안 디렉토리가 제거되면 프로세스 cwd는 디렉토리가 실제로 삭제되지 않도록합니다. 디렉토리를 고정하는 파일 시스템 링크 (부모 디렉토리의 항목 및 모든 내용)는 사라지지만 디렉토리 자체는 일종의 “좀비”로 계속 존재합니다. 한편 이전 디렉토리와 동일한 위치에 완전히 다른 파일 시스템 객체이지만 동일한 경로를 공유하는 새로운 디렉토리를 만들 수 있습니다.

따라서 cd ../code(또는 많은 쉘에서 cd .) 실제로 파일 시스템 계층 구조를 통과 하고 이전 주소 에있는 디렉토리로 이동합니다.

비슷하게 디렉토리를 제거하는 것은 집을 가비지 덤프 (이전 주소와의 관계)로 강제 이동하는 것과 같습니다. 아직 그곳에 살고있는 사람이 있다면 ( cwd집으로 사용) 집을 습격하기 전에 떠나야합니다. 그동안 옛 집 주소지에 새 집을 지을 수있었습니다.


답변

@Anthon은 이유가 무엇인지 밝혀 냈습니다.
해결책 으로 예를 들어 alias를 사용할 수 있습니다 .

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

bash의 별칭은 ~ / .bashrc에 보관됩니다.


답변

현재 작업 디렉토리 확인은 사용자가 찾은 것이 아니라 inode 번호를 기반으로합니다. bash를 사용하고 있으므로 다음과 같이 $ PWD를 사용하여 동일한 이름의 새 디렉토리로 cd 할 수 있습니다.

cd $ PWD

설명하기 위해 더미 배포 명령을 만들었습니다.

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

첫 번째 배포를 작성하고 cd로 코딩 한 다음 내용을 확인 ls -lai하여 inode를 볼 수 있습니다.

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

그리고 디렉토리 내용을 확인하십시오 … 이제 디렉토리에 아무것도 없습니다! 심지어 ‘.’ 그리고 ‘..’! 이것으로부터 cd ..‘..’가 더 이상 존재하지 않으므로 bash가 ‘..’디렉토리 항목을 사용하고 있지 않다는 것을 알 수 있습니다 . $ 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

현재 디렉토리 (.)의 inode가 어떻게 변경 되었습니까?

배포 스크립트가 이전 디렉토리를 다른 이름 (예 : 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'


답변

내가 생각하는 것은 경로가 디렉토리를 식별하는 것입니다.

무언가로가는 길은 물건 자체가 아니라 어떻게 가는지입니다. 침대로가는 경로는 방을 통과 할 수 있지만 일단 침대에 들어간 후 누군가 침대를 집어 들고 외부로 운반하면 더 이상 방에 없습니다.


답변

자체 포함 된 답변은 아니지만 의견을 남기기에는 너무 작습니다.

관련 파일 시스템의 디렉토리가 단순한 경로 이상이라는 생각을 더 잘 이해하려면 다른 프로세스의 현재 작업 디렉토리를 이동하십시오. 한 쉘에서 대화식 Python 세션을 시작하십시오.

$ python
>> import os
>> os.getcwd()
'/home/you/hocus'

그런 다음 다른 쉘로 이동하여 해당 디렉토리를 이동하십시오.

$ cd /home/you
$ mv hocus pocus

원래 것으로 돌아 가기 :

파이썬
>> 수입 OS
>> os.getcwd ()
'/ home / you / hocus'
>> os.getcwd ()
'/ home / you / pocus'