削除したディレクトリからcdする必要があるのはなぜですか?


19

私のサーバーには、次のようなディレクトリ構造があります。

/myproject/code

通常、サーバーへのssh接続があり、そのディレクトリに「スタンド」します。

root@machine:/myproject/code#

コードの新しいバージョンをデプロイすると、コードディレクトリが削除されるため、次のようにします。

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

そして、私が見つけた唯一の解決策は、CDを出し入れすることです:

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

これを回避できますか?それはやや奇妙な動作です。なぜこれが起こるのか、良い説明があれば感謝します。


5
コードディレクトリ自体ではなく、コードディレクトリ内のファイルを削除することを考えましたか?
StrongBad 14

9
新しく作成されたディレクトリrunが古いディレクトリと同じであると間違えています。同じ名前と親ディレクトリのみを持ちます。これをあなたの古い車を細断し、まったく同じ色とモデルの新しい車を購入するのと比較してください。
アントン

2
Anthon:パスはディレクトリを識別するものだと思います。私にとって、「cd ../code」は何もありません。なぜそうではないのか、とても興味があります。
マルクスヨハンソン14

2
@MarkusJohansson cd ../codeは何もしません。..あなたが持っている、または以前持っていたパスの親へのショートカットです。現在のディレクトリが削除された場合、親パスがまだ存在している可能性があり、この場合、評価することにより到達可能..です。そのディレクトリで、「code」という名前のディレクトリが検索されます。
アントン14

2
@MarkusJohanssonコードを削除してtararする代わりに、利用可能なバージョン管理ツールを使用することを強くお勧めします。更新の共有(プッシュまたはプル)がはるかに簡単になり、誤ったファイルを誤って削除するオプションが少なくなります。そして、デフォルトで古いバージョンを保持します。
ベルンハルト

回答:


26

私にとって、「cd ../code」は何もありません。なぜそうではないのか、とても興味があります。

ファイルとディレクトリは基本的に名前ではなくファイルシステムのiノードであるため、これはおそらくファイルシステムの種類に固有の実装の詳細ですが、すべてのextシステムに当てはまるので、ここに固執します。

ときに新しいディレクトリがcode作成され、それが新しいiノードに関連付けられ、それがどこにあるというのです。以前に削除されたファイルやディレクトリの記録は保持されていないため、システムが使用するinodeを確認して、同じものになるようにシャッフルする方法はありません。そのようなシステムはすぐに機能しなくなり、いずれにせよ、あなたが再びそこに戻ってくるという保証はおそらくないでしょう-ディレクトリが作成された場合、誤って別の場所になってしまう可能性があるため、それは一種の望ましくないでしょうそれは(現在未使用の)iノードを取ります。

この最後の可能性が存在するかどうか、または現在の作業ディレクトリに現在割り当てられている削除されたディレクトリのiノードが追跡され、その間何も割り当てられないかどうかはわかりません。


3
これが本当の答えです。
karan.dodia 14

14

シェルcd、次のコマンドを実行する前に、最後のコマンド中にあったパスに毎回実行するわけではありません

現在のディレクトリを削除し、同じ名前のディレクトリを作成しましたが、これは同じディレクトリではなく、同じ名前/パスを持つものです。

NautilusやWindows Explorerなどのファイルブラウザは、通常、ローカルファイルシステムでディレクトリが削除されると、ディレクトリツリーを「上に移動」します。ただし、これはネットワークファイルシステムには必ずしも当てはまりません。その場合、削除が認識されず、再表示により新しいディレクトリに移動することがあります。

cd次のコマンドを実行する前にシェルが現在のディレクトリに移動する可能性がありますが、これを実行する(または実行するように構成できる)ことはわかりません。


図解-理論的には、古い、削除された(またはリンクされていない)ディレクトリがまだ存在し、読み取り可能なファイルシステムが存在し、新しいディレクトリもすでに使用されている場合があります。これは、ディレクトリでは実際には役立ちませんが、ファイルではかなり一般的です。
フォルカーシーゲル14

4

ほとんどのUNIXライクシステムでは、プロセスの「現在のディレクトリ」は、そのディレクトリを指すファイル記述子としてカーネルに保存されます。カーネルは実際には現在のディレクトリのパスを保存しません。その情報はシェルによって追跡されます。

ファイルシステムオブジェクト(ファイルまたはそれへのすべてのファイルシステムリンクがなくなっているときのディレクトリ)が良いだけのために破壊され、そしてそのオブジェクトを指して何のファイルディスクリプタはありません。

そのため、現在の作業ディレクトリとしてそれを保持しているプロセスがまだある間にディレクトリが削除された場合、そのプロセスcwdはディレクトリが本当に削除されないようにします。ディレクトリを固定するファイルシステムリンク(親ディレクトリのエントリ、およびそのすべてのコンテンツ)はなくなりますが、ディレクトリ自体は一種の「ゾンビ」として存在し続けます。一方、古いディレクトリと同じ場所にまったく新しいディレクトリを作成できます。これは完全に異なるファイルシステムオブジェクトですが、同じパスを共有します。

したがって、cd ../code(または多くのシェルでcd .)実行すると、実際にはファイルシステム階層を走査し、古いアドレスにある新しいディレクトリに移動します。

類推すると、ディレクトリを削除することは、強制的に家をゴミ捨て場に移動するようなものです(前のアドレスとの関係を壊します)。まだ誰かがそこに住んでいる場合cwd、家を破壊する前に彼らは去らなければなりません。それまでの間、新しい家を古い住所に建てることができました。


0

@アンソンは理由を明らかにしました、なぜそれが起こるのか
あなたが使用する解決策としてとして、例としてaliasを

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

bashのエイリアスは〜/ .bashrcにあります


0

確認現在の作業ディレクトリは、iノード番号に基づいており、そこに到達するために検索したものではありません。bashを使用しているため、次のように$ PWDを使用して、同じ名前の新しいディレクトリにcdできます。

cd $ PWD

説明のために、ダミーのdeployコマンドを作成しました。

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

最初のデプロイメントを作成し、cdでコーディングしてから内容をチェックしls -laiて、iノードを確認できるようにしました。

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

次に、2回目のデプロイを実行します

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 ..はこの状況で処理しないので、最初に絶対パスに移動する必要があります。

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

現在のディレクトリ(。)のiノードがどのように変更されたかに注意してください。

あなたのデプロイスクリプトが例えば他のいくつかの名前、古いディレクトリを移動した場合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'

0

私が想定しているのは、パスがディレクトリを識別するものであるということです。

何かへの道は、それ自体ではなく、あなたがそこに到達する方法です。あなたのベッドへの道はあなたの部屋を通るかもしれませんが、あなたがベッドに入ったら、誰かがそれを拾って外に持ち出すと、あなたはもうあなたの部屋にいません。


0

自己完結型の答えではありませんが、追加のポイントがありますが、コメントするマージンが小さすぎて収まりきれません。

関連するファイルシステム内のディレクトリが単なるパスではないという考えをよりよく理解するには、別のプロセスの現在の作業ディレクトリを移動してみてください。1つのシェルで、インタラクティブなPythonセッションを開始します。

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

次に、別のシェルに移動して、そのディレクトリを移動します。

$ cd /home/you
$ mv hocus pocus

元の状態に戻る:

$ python
>>輸入OS
>> os.getcwd()
「/ home / you / hocus」
>> os.getcwd()
'/ home / you / pocus'
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.