Neden silinen bir dizinden cd almam gerekiyor?


19

Sunucumda böyle bir şey arayan bir dizin yapısı var:

/myproject/code

Normalde sunucuya bir ssh bağlantısı ve bu dizinde 'stand' var:

root@machine:/myproject/code#

Kodumun yeni bir sürümünü dağıttığımda, kod dizini kaldırıldı, bu yüzden kaldım:

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

Ve bulduğum tek çözüm, cd çıkışı ve geri dönüşü:

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

Bundan kaçınabilir miyim? Biraz garip bir davranış. Bunun neden böyle olduğuna dair güzel bir açıklamanız varsa bunu takdir ediyorum.


5
Kod dizininin kendisinde değil, kod dizininizdeki dosyaları kaldırmayı düşündünüz mü?
StrongBad

9
Yeni oluşturulan dizinin runeski dizinle aynı olduğu yanılıyorsunuz . Yalnızca aynı ada ve üst dizine sahiptir. Eski arabanızı parçalayarak ve tam olarak aynı renk ve modelde yeni bir araba satın almakla karşılaştırın: Rendelenmiş arabada oturmak istemezsiniz ve umarız yenisine zarar vermezsiniz, değil mi?
Anthon

2
Anthon: Ben varsayıyorum yolu dizini tanımlayan yolu olmasıdır. Bana göre "cd ../code" bir noop. Neden olmadığını duymakla çok ilgileniyorum.
Markus Johansson

2
@MarkusJohansson cd ../codebir noop değildir. ..sahip olduğunuz veya kullandığınız yolun üst öğesi için bir kısayoldur. Geçerli dizininiz silinirse, üst yol hala var olabilir ve bu durumda değerlendirilerek erişilebilir ... Bu dizinde 'kod' adında bir dizin aranır.
Anthon

2
@MarkusJohansson Kodu kaldırmak ve katranlamak yerine, mevcut herhangi bir sürüm kontrol aracını kullanmanızı şiddetle tavsiye ederim. Güncellemeyi paylaşmak çok daha kolay (sadece it veya çek) ve yanlış dosyaları yanlışlıkla silmek için daha az seçenek. Ve varsayılan olarak eski sürümü tutarsınız.
Bernhard

Yanıtlar:


26

Bana göre "cd ../code" bir noop. Neden olmadığını duymakla çok ilgileniyorum.

Dosya ve dizinler temelde dosya sistemi düğümleri olduğundan , isimler değil - bu belki de dosya sistemi türüne özgü bir uygulama detayıdır, ancak tüm ext sistemleri için geçerlidir, bu yüzden buraya bağlı kalacağım.

Bir zaman yeni dizin codeoluşturulur, yeni bir inode ile ilişkilidir, ve nerede olduğunu budur. Daha önce silinmiş dosya ve dizinlerin kaydedildiği bir kayıt yoktur, bu nedenle sistemin işgal etmek için hangi inode'u kontrol edebileceği ve etraftaki şeyleri karıştırdığı, böylece aynı olması için hiçbir yol yoktur; böyle bir sistem hızla işlenemez hale gelir ve her durumda, muhtemelen tekrar orada olacağınızın garantisi yoktur - bu istenmeyen bir durumdur, çünkü bir dizin oluşturulursa yanlışlıkla başka bir yere de gidebilirsiniz (şu anda kullanılmayan) inode'unuzu alır.

Bu son olasılığın var olup olmadığından veya şu anda çalışma dizininize atanmış olan silinen dizinin inode'unun izlenir, böylece süre boyunca hiçbir şey atanmayacaktır.


3
Buradaki gerçek cevap bu.
karan.dodia

14

Kabuğunuz , bir cdsonraki komutu yürütmeden önce, son komut sırasında bulunduğu yola her zaman bir yapmaz .

Geçerli dizini sildiniz ve aynı ada sahip, aynı dizin olmayan, yalnızca aynı ada / yola sahip bir dizin oluşturdunuz.

Yerel bir dosya sisteminde bir dizin silinirse, Nautilus ve Windows Explorer gibi dosya tarayıcıları normalde dizin ağacını yukarı kaldırır. Ancak bu, ağa bağlı dosya sistemleri için her zaman doğru değildir, bu durumda bazen silme fark edilmez ve yeniden görünme yeni dizinde sonlanmanıza neden olabilir.

Bir kabuk cdsonraki dizini çalıştırmadan önce geçerli dizine olabilir , ben bunu (veya bunu yapmak için yapılandırılabilir) herhangi bir farkında değilim.


Fol illustration - teorik olarak, eski, silinmiş (veya oldukça bağlantısız) dizinin hala var olduğu ve okunabilir olduğu bir dosya sistemi bile mevcut olabilir, ancak yeni de zaten kullanımda. Bu, dizinlerle pratikte yararlı olmaz, ancak dosyalarda oldukça yaygındır.
Volker Siegel

4

UNIX benzeri sistemlerin çoğunda, bir işlemin "geçerli dizini" çekirdekte o dizine işaret eden bir dosya tanımlayıcı olarak depolanır. Çekirdek aslında geçerli dizinin yolunu saklamaz: bu bilgiler kabuğunuz tarafından izlenir.

Bir dosya sistemi nesnesi (dosya veya dizin) yalnızca ona tüm dosya sistemi bağlantıları kaybolduğunda ve bu nesneyi işaret eden dosya tanımlayıcıları olmadığında yok olur.

Dolayısıyla, bir dizin hala geçerli çalışma dizini olarak tutan bir işlem varken kaldırılırsa, işlem cwddizinin gerçekten silinmesini önler. Dizini tutturan dosya sistemi bağlantıları (üst dizindeki girişi ve tüm içeriği) kaybolacak, ancak dizinin kendisi bir çeşit "zombi" olarak var olmaya devam edecek. Bu arada, tamamen farklı bir dosya sistemi nesnesi olan ancak aynı yolu paylaşan, eskisiyle aynı yerde yeni bir dizin oluşturabilirsiniz.

Böylece, yaptığınızda cd ../code(veya birçok kabukta cd .), aslında dosya sistemi hiyerarşisini geçiyor ve eski adreste bulunan yeni dizine gidiyorsunuz .

Benzeri bir şekilde, bir dizini kaldırmak, bir evi çöplükte zorla taşımak gibi bir şey olacaktır (bir önceki adrese bağları koparmak). Hâlâ orada yaşayan birileri olsaydı (onu kendileri gibi kullanıyorlarsa cwd), evin yerle bir edilmesinden önce ayrılmak zorunda kalacaklardı. Bu arada, eski adreste yepyeni bir ev inşa edilebilir.


0

@Anthon nedenlerini açıkladı, neden oluyor
Çözüm olarak takma ad kullanabilirsiniz , örneğin:

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

bash için diğer adlar ~ / .bashrc içinde tutulur


0

Onaylama Geçerli çalışma dizini, oraya ulaşmak için aradığınız şeyi değil, inode numarasına dayalıdır. Bash kullandığınız için, aynı addaki yeni dizine cd olarak $ PWD kullanabilirsiniz:

cd $ PWD

Göstermek için, sahte bir komut verdim:

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

İlk konuşlandırmayı oluşturdu, cd'd kodladı ve ardından ls -laiinode'ları görebilmeniz için içeriği kontrol etti:

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

Şimdi 2. konuşlandırmayı çalıştırın

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

Ve dizin içeriğini kontrol edin ... şimdi dizinde hiçbir şey yok! hatta '.' ve '..'! Bundan sonra, '..' cd ..artık olmadığından beri çalıştırdığınızda bash '..' dizin girişini kullanmadığını görebilirsiniz - Ben onun $ PWD işlemenin bir parçası olduğunu varsayıyorum. Bazı diğer / eski kabuklar cd ..bu durumda işlemez , önce mutlak bir yola cd yapmalısınız.

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

Cd ile $PWDtekrar deneyin:

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

Geçerli dizinin (.) İnode'unun nasıl değiştiğine dikkat edin?

Konuşlandırma komut dosyanız eski dizini başka bir ada taşıdıysa, örneğin mv code code.$$yukarıdaki dağıtım komut dosyasında, o ./runzaman işe yarayacaktır, ancak kullanılana kadar yeni kodu değil, eski kodu cd $PWDçalıştırırsınız .

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 kullanarak dağıtma aynı sorun var (Geçerli sürüm için geçerli adından bir symlink var), bu yüzden üretim / hazırlama alanlarına cd için takma adları kullanın ve RAIL_ENV uygun şekilde ayarlayın:

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

Ne varsayıyorum yolu dizini tanımlayan olmasıdır.

Bir şeyin yolu, oraya nasıl ulaştığınızdır, şeyin kendisi değil. Yatağınıza giden yol odanızdan olabilir, ancak bir kez yatakta olduğunuzda, birisi onu alır ve dışarıda taşırsa, artık odanızda olmazsınız.


0

Kendi kendine yeten bir cevap değil, ama yorum marjının içeremeyecek kadar küçük olduğu ek bir noktam var.

İlgili dosya sistemlerindeki bir dizinin bir yoldan daha fazlası olduğu fikrini daha iyi hissetmek için, başka bir işlemin geçerli çalışma dizinini taşımayı deneyin: bir kabukta etkileşimli bir Python oturumu başlatın:

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

Ardından başka bir kabuğa gidin ve şu dizini taşıyın:

$ cd /home/you
$ mv hocus pocus

Orijinaline geri dön:

$ python
>> işletim sistemi
>> os.getcwd ()
'/ Home / sen / hokus'
>> os.getcwd ()
'/ Home / sen / pokus'
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.