เหตุใดฉันจึงต้องทำซีดีออกจากไดเรกทอรีที่ถูกลบ


19

บนเซิร์ฟเวอร์ของฉันฉันมีโครงสร้างไดเรกทอรีที่มีลักษณะดังนี้:

/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...

ฉันจะหลีกเลี่ยงสิ่งนี้ได้หรือไม่? มันเป็นพฤติกรรมที่ค่อนข้างแปลก หากคุณมีคำอธิบายที่ดีว่าทำไมสิ่งนี้เกิดขึ้นฉันจะขอบคุณมัน


5
คุณคิดว่าจะลบไฟล์ในไดเรคทอรีโค้ดของคุณไม่ใช่ไดเร็คทอรี่ของตัวเองหรือไม่?
StrongBad

9
คุณเข้าใจผิดว่าไดเรกทอรีที่สร้างขึ้นใหม่runนั้นเหมือนกับไดเรกทอรีเก่า มันมีชื่อและไดเรกทอรีหลักเท่านั้น เปรียบเทียบสิ่งนี้กับคุณเพื่อทำลายรถเก่าของคุณและซื้อรถใหม่ที่มีสีและรุ่นเดียวกัน: คุณไม่ต้องการนั่งในรถที่ถูกทำลายเป็นชิ้นเล็กชิ้นน้อยและหวังว่าคุณจะได้รถใหม่ที่ไม่เป็นอันตรายใช่ไหม
Anthon

2
Anthon: สิ่งที่ฉันถือว่าเป็นเส้นทางคือสิ่งที่ระบุไดเรกทอรี ให้ฉัน "cd ../code" คือ noop ฉันสนใจที่จะฟังมากว่าทำไม
Markus Johansson

2
@MarkusJohansson cd ../codeไม่ได้เป็น noop ..เป็นทางลัดสำหรับพาเรนต์ของพา ธ ที่คุณมีหรือเคยมี ..หากไดเรกทอรีปัจจุบันของคุณจะถูกลบออกเส้นทางแม่อาจยังคงมีอยู่และในกรณีนี้สามารถเข้าถึงได้โดยการประเมิน ในไดเรกทอรีนั้นจะทำการค้นหาไดเรกทอรีที่มีชื่อ 'รหัส'
Anthon

2
@MarkusJohansson แทนที่จะทำการลบและกำหนดรหัสฉันขอแนะนำให้ใช้เครื่องมือควบคุมเวอร์ชันใด ๆ ที่มีอยู่ แชร์การอัปเดตที่ง่ายกว่ามาก (เพียงแค่กดหรือดึง) และตัวเลือกน้อยลงเพื่อลบไฟล์ที่ไม่ถูกต้อง และคุณเก็บรุ่นเก่าไว้เป็นค่าเริ่มต้น
แบร์นฮาร์ด

คำตอบ:


26

ให้ฉัน "cd ../code" คือ noop ฉันสนใจที่จะฟังมากว่าทำไม

เนื่องจากไฟล์และไดเรกทอรีเป็นinode ระบบแฟ้มพื้นฐานไม่ใช่ชื่อ - นี่อาจเป็นรายละเอียดการใช้งานเฉพาะกับประเภทระบบไฟล์ แต่มันเป็นความจริงสำหรับระบบ ext ทั้งหมดดังนั้นฉันจะติดที่นี่

เมื่อสร้างไดเรกทอรีใหม่codeมันจะเชื่อมโยงกับ inode ใหม่และนั่นคือที่ที่มันอยู่ ไม่มีการเก็บบันทึกไฟล์และไดเรกทอรีที่ถูกลบไปก่อนหน้านี้ดังนั้นจึงไม่มีวิธีที่ระบบสามารถตรวจสอบสิ่งที่ inode ใช้เพื่อครอบครองและอาจสับเปลี่ยนสิ่งต่าง ๆ รอบ ๆ เพื่อให้เหมือนเดิมอีกครั้ง ระบบดังกล่าวจะไม่สามารถใช้งานได้อย่างรวดเร็วและในกรณีใด ๆ ก็อาจจะรับประกันได้ว่าคุณจะกลับมาที่นี่อีกครั้ง - ที่จะไม่พึงประสงค์เนื่องจากมันหมายความว่าคุณยังอาจจบลงที่อื่นโดยบังเอิญถ้าสร้างไดเรกทอรี ที่ใช้ inode (ไม่ได้ใช้ในปัจจุบัน) ของคุณ

ฉันไม่แน่ใจว่ามีความเป็นไปได้สุดท้ายนี้อยู่หรือไม่ถ้า inode ของไดเรกทอรีที่ถูกลบซึ่งมอบหมายให้ไดเรกทอรีการทำงานปัจจุบันของคุณถูกติดตามเพื่อไม่ให้มีการมอบหมายสิ่งใดในช่วงเวลานั้นเป็นต้น


3
นี่คือคำตอบที่แท้จริงที่นี่
karan.dodia

14

เชลล์ของคุณไม่ได้ทำทุกครั้งcdที่พา ธ ที่อยู่ในระหว่างคำสั่งสุดท้ายก่อนดำเนินการคำสั่งถัดไป

คุณลบไดเรกทอรีปัจจุบันและสร้างไดเรกทอรีด้วยชื่อเดียวกันซึ่งไม่ใช่ไดเรกทอรีเดียวกันเพียงบางสิ่งที่มีชื่อ / พา ธ เดียวกัน

เบราว์เซอร์ไฟล์อย่าง Nautilus และ Windows Explorer โดยปกติจะ "ทำ" ไดเรกทอรีต้นไม้ถ้าไดเรกทอรีถูกลบในระบบไฟล์ในเครื่อง อย่างไรก็ตามสิ่งนี้อาจไม่เป็นจริงเสมอไปสำหรับระบบไฟล์เครือข่ายในกรณีนั้นบางครั้งการลบจะไม่ได้รับการสังเกตและการปรากฏขึ้นอีกครั้งอาจทำให้คุณสิ้นสุดในไดเรกทอรีใหม่

เชลล์สามารถcdเข้าไปในไดเรกทอรีปัจจุบันก่อนที่จะดำเนินการคำสั่งถัดไปฉันไม่ทราบว่าสิ่งใดที่ทำ (หรือสามารถกำหนดค่าให้ทำ)


ในทางทฤษฎีแล้วอาจมีระบบไฟล์อยู่ซึ่งไดเรกทอรีเก่าที่ถูกลบ (หรือยกเลิกการเชื่อมโยง) ยังคงมีอยู่และสามารถอ่านได้ในขณะที่ระบบใหม่มีการใช้งานแล้ว ที่จะไม่เป็นประโยชน์ในทางปฏิบัติกับไดเรกทอรี แต่ด้วยไฟล์มันเป็นเรื่องธรรมดา
Volker Siegel

4

บนระบบที่เหมือน UNIX ส่วนใหญ่ "ไดเรกทอรีปัจจุบัน" สำหรับกระบวนการจะถูกเก็บไว้ในเคอร์เนลเป็นตัวบ่งชี้ไฟล์ที่ชี้ไปยังไดเรกทอรีนั้น เคอร์เนลไม่ได้เก็บเส้นทางของไดเรกทอรีปัจจุบันจริง ๆ : ข้อมูลนั้นถูกติดตามโดยเชลล์ของคุณ

วัตถุระบบไฟล์ (ไฟล์หรือไดเรกทอรี) จะถูกทำลายก็ต่อเมื่อดีแล้วเมื่อระบบไฟล์ทั้งหมดลิงก์ไปที่มันหายไปและไม่มีไฟล์ตัวบ่งชี้ที่ชี้ไปยังวัตถุนั้น

ดังนั้นหากไดเรกทอรีถูกลบออกในขณะที่ยังคงมีกระบวนการที่ถือเป็นไดเรกทอรีการทำงานปัจจุบันของกระบวนการcwdจะทำให้ไดเรกทอรีถูกลบอย่างแท้จริง ลิงก์ระบบไฟล์ที่เชื่อมโยงกับไดเรกทอรี (รายการในไดเรกทอรีหลักและเนื้อหาทั้งหมด) จะหายไป แต่ไดเรกทอรีจะยังคงอยู่ในรูปแบบของ "zombie" ในขณะเดียวกันคุณสามารถสร้างไดเรกทอรีใหม่ในตำแหน่งเดียวกันกับไดเรกทอรีเก่าซึ่งเป็นวัตถุระบบไฟล์ที่แตกต่างกันโดยสิ้นเชิง แต่ใช้เส้นทางเดียวกัน

ดังนั้นเมื่อคุณทำcd ../code(หรือบนเชลล์จำนวนมากcd .) คุณกำลังข้ามลำดับชั้นของระบบไฟล์และไปที่ไดเรกทอรีใหม่ที่อยู่ในที่อยู่เดิม

โดยการเปรียบเทียบการลบไดเรกทอรีจะเหมือนกับการย้ายบ้านไปที่กองขยะอย่างรุนแรง (ทำลายความสัมพันธ์กับที่อยู่ก่อนหน้า) หากยังมีคนอาศัยอยู่ที่นั่น (ใช้เป็นของพวกเขาcwd) พวกเขาจะต้องออกไปก่อนที่บ้านจะถูกทำลาย ในระหว่างนี้บ้านใหม่สามารถสร้างที่อยู่เดิมได้


0

@Anthon เคลียร์เหตุผลทำไมมันเกิดขึ้น
ในฐานะที่เป็นวิธีการแก้ปัญหาคุณอาจใช้นามแฝงเช่น:

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

นามแฝงสำหรับ bash นั้นเป็น keept ใน ~ / .bashrc


0

การยืนยันไดเรกทอรีการทำงานปัจจุบันอ้างอิงหมายเลขไอโหนดไม่ใช่สิ่งที่คุณค้นหาเพื่อไปที่นั่น เนื่องจากคุณใช้ bash คุณสามารถใช้ $ PWD ดังต่อไปนี้เพื่อ cd ไปยังไดเรกทอรีใหม่ที่มีชื่อเดียวกัน:

cd $ PWD

เพื่อแสดงให้เห็นว่าฉันได้ทำคำสั่งปรับใช้ dummy:

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

สร้างการปรับใช้ครั้งแรกแล้วให้เขียนโค้ดจากนั้นตรวจสอบเนื้อหาด้วย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

ตอนนี้เรียกใช้การปรับใช้ที่ 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 ..ตั้งแต่ '.. ' ไม่มีอยู่อีกต่อไป - ฉันเข้าใจว่าส่วนหนึ่งของการจัดการ $ PWD เชลล์อื่น / เก่ากว่าบางตัวไม่จัดการcd ..ในสถานการณ์นี้คุณต้อง cd ไปยังพา ธ สัมบูรณ์ก่อน

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

ซีดีถึง$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 มีปัญหาเดียวกัน (มี symlink จากชื่อปัจจุบันถึงรีลีสปัจจุบัน) ดังนั้นฉันใช้ aliases to 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

ไม่ใช่คำตอบที่มีในตัวเอง แต่ฉันมีประเด็นเพิ่มเติมที่ขอบการแสดงความคิดเห็นนั้นเล็กเกินกว่าจะบรรจุได้

เพื่อให้ได้ความรู้สึกที่ดีขึ้นสำหรับแนวคิดที่ว่าไดเรกทอรีในระบบไฟล์ที่เกี่ยวข้องเป็นมากกว่าแค่เส้นทางให้ลองย้ายไดเรกทอรีการทำงานปัจจุบันของกระบวนการอื่น: ในเชลล์หนึ่งให้เริ่มเซสชัน Python แบบโต้ตอบ:

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

จากนั้นไปที่เชลล์อื่นและย้ายไดเร็กทอรีนั้น:

$ cd /home/you
$ mv hocus pocus

กลับไปที่ต้นฉบับ:

$ python
>> ระบบปฏิบัติการนำเข้า
>> os.getcwd ()
'/ home / คุณ / Hocus'
>> os.getcwd ()
'/ home / คุณ / Pocus'
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.