Perché devo estrarre cd da una directory eliminata?


19

Sul mio server ho una struttura di directory simile a questa:

/myproject/code

Normalmente ho una connessione ssh al server e 'stand' in quella directory:

root@machine:/myproject/code#

Quando distribuisco una nuova versione del mio codice, la directory del codice viene rimossa, quindi rimango con:

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

E l'unica soluzione che ho trovato è di eseguire il cd out e il back in:

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

Posso evitarlo? È un comportamento un po 'strano. Se hai una bella spiegazione del perché questo accada, lo apprezzerei.


5
Hai pensato di rimuovere i file nella tua directory di codice e non la directory di codice stessa?
StrongBad

9
Ti sbagli che la directory appena creata runè la stessa della directory precedente. Ha solo lo stesso nome e la stessa directory principale. Paragonalo a quello che distruggi la tua vecchia macchina e acquisti una nuova macchina dello stesso identico colore e modello: non vorresti sederti nell'auto che viene distrutta e speri di finire sulla nuova senza danni, vero?
Anthon,

2
Anthon: Quello che presumo è che il percorso è ciò che identifica la directory. Per me il "cd ../code" è un noop. Sono molto interessato a sapere perché non lo è.
Markus Johansson,

2
@MarkusJohansson cd ../codenon è un noop. ..è una scorciatoia per il genitore del percorso che hai o che avevi. Se la directory corrente viene eliminata, è possibile che esista ancora il percorso principale, e in questo caso è raggiungibile valutando ... In quella directory viene effettuata una ricerca per una directory con nome 'code'.
Anthon,

2
@MarkusJohansson Invece di rimuovere e modificare il codice, consiglio vivamente di utilizzare qualsiasi strumento di controllo della versione disponibile. Aggiornamento molto più facile da condividere (basta premere o tirare) e meno opzioni per eliminare accidentalmente i file sbagliati. E mantieni la versione precedente per impostazione predefinita.
Bernhard,

Risposte:


26

Per me il "cd ../code" è un noop. Sono molto interessato a sapere perché non lo è.

Poiché i file e le directory sono fondamentalmente inode di filesystem , non nomi - questo è forse un dettaglio di implementazione specifico per il tipo di filesystem, ma è vero per tutti i sistemi ext, quindi mi atterrò qui.

Quando viene creata una nuova directory code, viene associata a un nuovo inode ed è lì che si trova. Non vi è alcuna registrazione di file e directory precedentemente eliminati, quindi non esiste alcun modo in cui il sistema possa controllare quale inode ha usato per occupare e forse rimescolare le cose in modo che siano nuovamente le stesse; un sistema del genere diventerebbe rapidamente inattuabile e, in ogni caso, probabilmente non è una garanzia che tornerai di nuovo lì - sarebbe in qualche modo indesiderabile, dal momento che significa che potresti anche finire accidentalmente da qualche altra parte se viene creata una directory che accetta il tuo inode (attualmente non utilizzato).

Non sono sicuro che questa ultima possibilità esista, o se l'inode della directory eliminata attualmente assegnata alla tua attuale directory di lavoro sia tracciata in modo che nulla gli venga assegnato per la durata, ecc.


3
Questa è la vera risposta qui.
karan.dodia,

14

La tua shell non fa ogni volta un cdpercorso nel percorso in cui si trovava durante l'ultimo comando, prima di eseguire il comando successivo.

Hai eliminato la directory corrente e creato una directory con lo stesso nome, che non è la stessa directory, ma solo qualcosa con lo stesso nome / percorso.

I browser di file come Nautilus e Windows Explorer normalmente "salgono" l'albero delle directory se una directory viene eliminata su un file system locale. Tuttavia, ciò non è sempre vero per i file system in rete, in tal caso a volte la cancellazione non viene notata e la ricomparsa potrebbe farti finire nella nuova directory.

Una shell potrebbe cdentrare nella directory corrente prima di eseguire il comando successivo, non ne sono a conoscenza (o può essere configurato per farlo).


Fol illustration - in teoria, potrebbe persino esistere un file system in cui esiste ancora ed è leggibile la vecchia directory cancellata (o piuttosto non collegata), mentre quella nuova è già in uso. Non sarebbe utile in pratica con le directory, ma con i file è abbastanza comune.
Volker Siegel,

4

Sulla maggior parte dei sistemi simili a UNIX, la "directory corrente" per un processo è memorizzata nel kernel come descrittore di file che punta a quella directory. Il kernel in realtà non memorizza il percorso della directory corrente: tali informazioni sono tracciate dalla shell.

Un oggetto filesystem (file o directory) viene distrutto per sempre solo quando tutti i collegamenti al filesystem sono spariti e non ci sono descrittori di file che puntano a quell'oggetto.

Pertanto, se una directory viene rimossa mentre è ancora presente un processo che la tiene come directory di lavoro corrente, il processo cwdeviterà che la directory venga effettivamente eliminata. I collegamenti del filesystem che ancorano la directory (la sua voce nella directory principale e tutto il suo contenuto) scompariranno, ma la directory stessa continuerà a esistere come una sorta di "zombie". Nel frattempo, puoi creare una nuova directory nella stessa posizione di quella precedente, che è un oggetto filesystem completamente diverso ma che condivide lo stesso percorso.

Pertanto, quando lo fai cd ../code(o, su molte shell cd .), stai effettivamente attraversando la gerarchia del filesystem e vai nella nuova directory che risiede al vecchio indirizzo.

Per analogia, rimuovere una directory sarebbe come spostare forzatamente una casa nella discarica (rompendo i legami con l'indirizzo precedente). Se c'era ancora qualcuno che viveva lì (usandolo come loro cwd), avrebbero dovuto andarsene prima che la casa potesse essere rasa al suolo. Nel frattempo, una vecchia casa potrebbe essere costruita al vecchio indirizzo.


0

@Anthon ha chiarito le ragioni, perché succede
Come soluzione puoi usare l' alias , come esempio:

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

gli alias per bash sono mantenuti in ~ / .bashrc


0

Conferma della directory di lavoro corrente È basata sul numero di inode, non su quello che hai cercato per arrivarci. Dato che stai usando bash, puoi usare $ PWD come segue per cd nella nuova directory con lo stesso nome:

cd $ PWD

Per illustrare, ho eseguito un comando deploy fittizio:

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

Ha creato la prima distribuzione, cd per codificare e quindi controllato i contenuti in ls -laimodo da poter vedere gli 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

Ora esegui la seconda distribuzione

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

E controlla il contenuto della directory ... ora non c'è nulla nella directory! nemmeno '.' e '..'! Da questo puoi vedere che bash non sta usando la voce della directory '..' quando esegui cd ..da '..' non esiste più - presumo che faccia parte della sua gestione $ PWD. Alcune altre / vecchie shell non gestiscono cd ..in questa situazione, devi prima effettuare il cd su un percorso assoluto.

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

Cd per $PWDriprovare:

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

Notare come è cambiato l'inode per la directory corrente (.)?

Se lo script di distribuzione spostasse la vecchia directory su un altro nome, ad esempio, mv code code.$$nello script di distribuzione sopra, ./runfunzionerebbe, ma fino a quando non utilizzi cd $PWDsi eseguirà il vecchio codice, non il nuovo.

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

La distribuzione tramite capistrano ha lo stesso problema (hanno un collegamento simbolico dal nome corrente alla versione corrente), quindi uso gli alias per cd nelle aree di produzione / messa in scena e per impostare RAIL_ENV in modo appropriato:

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

Quello che presumo è che il percorso è ciò che identifica la directory.

Il percorso verso qualcosa è come arrivarci, non la cosa stessa. Il percorso per il tuo letto può essere attraverso la tua stanza, ma una volta che sei a letto, se qualcuno lo raccoglie e lo porta fuori, non sei più nella tua stanza.


0

Non è una risposta autonoma, ma ho un punto in più, che il margine di commento era troppo piccolo per contenere.

Per avere un'idea migliore dell'idea che una directory nei relativi file system non sia solo un percorso, prova a spostare la directory di lavoro corrente di un altro processo: in una shell, avvia una sessione interattiva di Python:

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

Quindi, vai su un'altra shell e sposta quella directory:

$ cd /home/you
$ mv hocus pocus

Torna a quello originale:

$ python
>> import os
>> os.getcwd ()
'/ Home / vi / Hocus'
>> os.getcwd ()
'Home / vi / pocus /'
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.