ทำไมฉันถึงแก้ไขไฟล์แบบอ่านอย่างเดียว?


42

คำถามสั้น ๆ :

ทำไมเราสามารถจัดการไฟล์อ่านอย่างเดียวใน Vim โดยใช้:+ w+ q+ !ได้โดยไม่ต้องเป็นผู้ดูแลระบบ?

คำถามยาว:

ฉันมีไฟล์ข้อความ (myFile.txt) ซึ่งอ่านได้อย่างเดียวสำหรับทุกคน:

navid@navid-ThinkPad-T530:~/ubuntuTest$ ls -l myFile.txt 
-r--r--r-- 1 navid navid 26 Aug 22 21:21 myFile.txt

ฉันสามารถเปิดด้วย Vim ได้โดยไม่ต้องมีสิทธิ์ระดับผู้ดูแล:

navid@navid-ThinkPad-T530:~/ubuntuTest$ vi myFile.txt 

ฉันแก้ไขมันและกด: Esc+ :+ w+ q+ Enterและฉันเห็นข้อความแสดงข้อผิดพลาดนี้:

E45: 'readonly' option is set (add ! to override)

จนถึงตอนนี้ทุกอย่างเข้าท่า แต่เมื่อฉันกด: Esc+ :+ w+ q+ !+ Enter, กลุ่มจะบันทึกการเปลี่ยนแปลง

ฉันใช้ Ubuntu 16.04 และ VIM 7.4


1
@Zanna คุณเป็นเจ้าของไดเรกทอรีที่ไฟล์นั้นมีอยู่หรือไม่
Rob

ใช่นี่จะเป็นปัญหาที่ยิ่งใหญ่เป็นอย่างอื่น :)
Rob

11
การแก้ไขไฟล์และการแทนที่ไฟล์เป็นสองสิ่งที่แตกต่างกันด้วยข้อกำหนดการอนุญาตที่ต่างกัน
David Schwartz

1
คุณอาจต้องการที่จะมีลักษณะที่นี้ โดยทั่วไปจะตอบคำถามของคุณและเป็น @DavidSchwartz ชี้ให้เห็นอย่างถูกต้อง:Modifying a file and replacing a file are two different things
Panagiotis Tabakis

@PanagiotisTabakis ดีมาก ๆ ที่พบว่ามันยอดเยี่ยมมาก .. chmod เพื่อทำให้ไฟล์อ่าน - เขียนและย้อนกลับมาอีกครั้งถ้าคุณเป็นเจ้าของ .. รักมัน :)
Rob

คำตอบ:


58

ดังที่ @Rob ได้กล่าวถึงไปแล้วคุณสามารถทำได้เฉพาะเมื่อคุณมีสิทธิ์เขียนเพื่อเข้าถึงไดเรกทอรีที่มีไฟล์ ยกตัวอย่างเช่นการพยายามทำสิ่งเดียวกันกับไฟล์นั้น/etcจะล้มเหลว

สำหรับวิธีการ vimทำสิ่งนี้มันจะลบไฟล์และสร้างมันขึ้นมาใหม่ เพื่อทดสอบสิ่งนี้ฉันสร้างไฟล์ที่รูทเป็นเจ้าของ:

echo foo | sudo tee fff

จากนั้นดำเนินการแก้ไขไฟล์ด้วยvimวิธีที่คุณอธิบาย แต่แนบกระบวนการstraceเพื่อดูว่าเกิดอะไรขึ้น:

strace vim fff 2> strace.out

ฉันตรวจสอบแล้วstrace.outพบ:

unlink("fff")                           = 0
open("fff", O_WRONLY|O_CREAT|O_TRUNC, 0644) = 4
write(4, "foasdasdao\n", 11)            = 11

ดังนั้นไฟล์ถูกลบครั้งแรก ( unlink("fff")) จากนั้นไฟล์ใหม่ที่มีชื่อเดียวกันถูกสร้างขึ้น ( open("fff", O_WRONLY|O_CREAT|O_TRUNC, 0644)) และการแก้ไขที่ฉันทำถูกเขียนลงไป ( write(4, "foasdasdao\n", 11)) หากคุณลองทำที่บ้านคุณจะเห็นว่าหลังจากที่คุณแก้ไขvimไฟล์ตอนนี้ไฟล์จะเป็นของคุณไม่ใช่รูท

ดังนั้นการพูดอย่างเคร่งครัดvimไม่ได้แก้ไขไฟล์ที่คุณไม่มีสิทธิ์เข้าถึงเพื่อเขียน เป็นการลบไฟล์จากไดเรกทอรีที่คุณมีสิทธิ์การเขียนและจากนั้นสร้างไฟล์ใหม่ซึ่งคุณมีสิทธิ์เข้าถึงการเขียนอีกครั้ง



8
@CCJ เป็นการดำเนินการเขียนในไดเรกทอรีแต่ไม่ใช่ไฟล์ไม่ใช่ การดำเนินการเขียนบนไฟล์เป็นสิ่งที่เปลี่ยนแปลงเนื้อหาของไฟล์ ด้วยโทเค็นเดียวกันการสร้าง / ลบไฟล์เป็นการดำเนินการเขียนในไดเรกทอรีเนื่องจากคุณเปลี่ยนเนื้อหา
terdon

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

5
@PeterCordes อืมตกลง คุณอาจต้องการส่งคำร้องเรียนของคุณไปยังนักพัฒนาที่เป็นกลุ่ม ฉันไม่ได้ใช้สิ่งนี้เลยฉันอยู่ในค่าย emacs
terdon

3
@CCJ การลบไฟล์เป็นการดำเนินการเขียนไปยังไดเร็กทอรีที่มีไฟล์ไม่ใช่ตัวไฟล์เอง มันใช้งานง่ายอย่างสมบูรณ์แบบหากคุณเป็นผู้ดูแลของไดเรกทอรี (เช่นมีการเข้าถึงการเขียน) คุณควรจะสามารถควบคุมสิ่งที่อยู่ในนั้นและเจ้าของไฟล์แต่ละไฟล์ไม่ควรได้รับอนุญาตให้แทนที่คุณ
fkraiem

16

ตราบใดที่คุณเป็นเจ้าของไดเรกทอรีแม่คุณสามารถลบหรือแทนที่ไฟล์ไม่ว่าจะได้รับอนุญาตเนื่องจากคุณสามารถเปลี่ยนเนื้อหาของไดเรกทอรี :)

ลองกับคำสั่งอื่น ๆ เช่น rm มันจะแจ้งให้คุณ แต่คุณยังสามารถทำได้ ทำให้ไดเรกทอรีไม่สามารถเขียนได้และควรหยุดทำ

ส่วนที่เพิ่มเข้าไป:

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


7
ดูเหมือนว่า VIM จะเลือกจากหลายกลยุทธ์รวมถึงเขียนใหม่ในสถานที่หรือยกเลิกการเชื่อมโยง + เขียนไฟล์ใหม่
Peter Cordes

3
@PeterCordes ใช่มันจะพยายามอย่างหนักในการทำสิ่งที่คุณบอกให้ :) มีฝีมือมาก :)
Rob

16

การใช้w!คุณลบไฟล์ต้นฉบับ ( ซึ่งคุณได้รับอนุญาตให้ทำ ) และเขียนเวอร์ชันของคุณแทน

เมื่อคุณมีสิทธิ์การเขียนไปยังไดเรกทอรีคุณสามารถ: สร้างย้ายหรือลบไฟล์ภายในไดเรกทอรีนั้น

$ mkdir foo
$ echo hi > foo/file
$ chmod 777 foo
$ chmod 700 foo/file
$ ls -l foo/file 
-rwx------ 1 ravexina ravexina 7 Aug 31 03:19 foo/file

ตอนนี้ให้ฉันเปลี่ยนผู้ใช้ของฉันและเปลี่ยนไฟล์

$ sudo -u user2 -s
$ vi foo/a # save using w! (I wrote into the file bye)
$ ls -l foo/a
-rwx------ 1 user2 user2 7 Aug 31 03:20 foo/file

ตอนนี้ดูสิ่งที่อยู่ในนั้น:

$ cat foo/file
bye

10

ดู:help write-readonly:

                                                        write-readonly
When the 'cpoptions' option contains 'W', Vim will refuse to overwrite a
readonly file.  When 'W' is not present, ":w!" will overwrite a readonly file,
if the system allows it (the directory must be writable).

เนื่องจากคุณมีสิทธิ์ในการเขียนในไดเรกทอรี (หมายถึงคุณสามารถสร้างลบหรือเปลี่ยนชื่อไฟล์ได้) ระบบจึงอนุญาต


ค่าเริ่มต้นของcpoptionsไม่มีW:

                                                'cpoptions' 'cpo' cpo
'cpoptions' 'cpo'       string  (Vim default: "aABceFs",
                                 Vi default:  all flags)
                        global

2

นี่เป็นคำเตือนของ VIM สำหรับคุณที่อาจค่อนข้างสำคัญเมื่อพิจารณาว่าสิทธิ์ทำงานใน UNIX อย่างไร ความไม่ชัดเจนที่เห็นได้ชัดนี้เป็นเพราะระบบไฟล์ UNIX มีสิทธิ์สำหรับไฟล์ที่เก็บไว้ใน i-node ของไฟล์ โครงสร้างไดเร็กทอรีนั้นแยกจากกันและเชื่อมโยง i-nodes เหล่านี้เท่านั้น ไดเรกทอรียังมีสิทธิ์ของพวกเขาที่บอกว่าคุณสามารถลิงค์ / ยกเลิกการเชื่อมโยงไฟล์เข้าไปหรืออ่านมันหรือเข้าไปในไดเรกทอรีย่อย การออกแบบนี้ช่วยให้ไฟล์เดียวกันสามารถปรากฏในหลาย ๆ ตำแหน่งในโครงสร้างไดเรกทอรี (ผ่านฮาร์ดลิงก์) โดยการพูดว่า "add! to override" VIM พยายามเตือนคุณว่าไฟล์ต้นฉบับจะถูกยกเลิกการเชื่อมโยง (ดังนั้นไฟล์จะยังคงอยู่ในที่อื่น ๆ ที่ไม่ได้ถูกแตะต้อง) และไฟล์ใหม่จะถูกสร้างขึ้นและเชื่อมโยงไปยังตำแหน่งเดิมในโครงสร้างไดเรกทอรี ในกรณีที่จำนวนลิงค์ของไฟล์ต้นฉบับลดลงเป็นศูนย์ไฟล์ต้นฉบับจะถูกปล่อยให้เป็นอิสระ แต่ถ้าไม่ใช่คุณจะทำการโคลนไฟล์อย่างมีประสิทธิภาพ การเปิดไฟล์จะนับเป็นลิงค์ด้วยดังนั้นหากบางโปรแกรมเปิดไฟล์และคุณยอมรับ "add! to override" โปรแกรมจะไม่เห็นการเปลี่ยนแปลงที่เกิดขึ้นกับไฟล์ของคุณด้วย VIM ไฟล์จะได้รับการยกเลิกการเชื่อมโยงจากไดเรกทอรีโดย VIM และหลังจากปิดไฟล์โดยโปรแกรมอื่นไฟล์นั้นจะได้รับการปล่อยให้เป็นอิสระยกเว้นว่ามีการเชื่อมโยงที่อื่น

โปรดทราบว่าใน Windows การอนุญาตสำหรับไฟล์จะถูกเก็บไว้ในไดเรกทอรีดังนั้นจากมุมมองของกระบวนทัศน์การอนุญาตของ Windows พฤติกรรม vim นี้อาจดูแปลก สำหรับการเขียนไปยังไฟล์ Windows มีเหตุผลอาจตรวจสอบการอนุญาตบางอย่างของไดเรกทอรีแม้แต่การอนุญาตแบบ super-directory ดังที่ได้กล่าวไว้ข้างต้นใน UNIX สิทธิ์ของไดเรกทอรีนั้นไม่เกี่ยวข้องกับการจัดการกับไฟล์เท่าที่คุณสามารถแสดงรายการและเปิดไฟล์ได้ (เช่นมี x สำหรับ super-directory ทั้งหมด) ไฟล์ที่เปิดใน UNIX อาจไม่มีชื่อไฟล์อีกต่อไปหากไฟล์นั้นถูกยกเลิกการเชื่อมโยงจากไดเรกทอรีทั้งหมดหลังจากเปิด

ตัวอย่างเช่นคุณมีไฟล์ / home / user1 / foo และเป็นไฟล์เดียวกับ (เช่น hardlinked to) / home / user2 / foo และไฟล์ไม่สามารถเขียนได้โดยใครและปัจจุบันเปิดโดยโปรแกรม P (เปิดอ่านเขียนโดย โปรแกรมเริ่มต้นด้วยรูท) หาก user1 เปิดด้วย vim และเขียนทับเขาจะทำสำเนาของตัวเองและไม่เห็นไฟล์ต้นฉบับอีกต่อไป หากภายหลัง user2 เปิดลิงก์ของเขาด้วยกลุ่มและเขียนลงไปมันจะถูกยกเลิกการเชื่อมโยงอีกครั้งและเขาจะสร้างสำเนาใหม่ โปรแกรม P จะยังคงเห็นไฟล์ต้นฉบับและสามารถอ่านหรือเขียนได้อย่างอิสระ ทันทีที่โปรแกรมปิดไฟล์ไฟล์จะหายไป (รับอิสระจากระบบไฟล์)


2

ทั้งกระบวนการแก้ไขเป็นกลุ่มของคุณและไฟล์ของคุณมี

 getpwnam("navid")->pw_uid

การเป็นเจ้าของเพื่อให้คุณสามารถใช้จ่าย

 :!chmod +w %

และคุณอาจเดาได้ว่ากาลครั้งหนึ่งมันจะง่ายกว่าเดิม

 :!rm %

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

ลองเขียนทับพี่สาวของคุณ

 /home/whoopi/.profile

เป็นเพียง navid และเดิมพันเป็นกลุ่มของคุณให้คุณปฏิเสธที่คุณต้องการ


ขอบคุณ @Zanna สำหรับการแก้ไขโค้ดถึงแม้ว่าฉันจะเสียค่าใช้จ่ายเล็กน้อยในเรื่องชื่อเสียง แต่ก็สมควรได้รับ
Roman Czyborra

1

นี่ไม่ใช่คำตอบที่แน่นอน แต่ถ้าคุณต้องการตั้งค่าไฟล์เพื่อให้ไม่มีใครสามารถเปลี่ยนหรือลบไฟล์ได้คุณสามารถทำให้มันไม่เปลี่ยนรูปได้

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

วิธีทำให้ไฟล์ไม่เปลี่ยนรูป (คุณต้องการsudo):

sudo chattr +i myFile.txt

คุณสามารถเห็นสิ่งนี้ได้ด้วยlsattr(ตัวอักษรiในผลลัพธ์):

$ lsattr myFile.txt
----i--------e-- myFile.txt

หากต้องการทำให้ไฟล์เป็นปกติอีกครั้ง:

sudo chattr -i myFile.txt

ในการชี้แจง: เมื่อไฟล์ไม่เปลี่ยนรูปไฟล์จะไม่สามารถลบเปลี่ยนชื่อแก้ไขหรือแม้กระทั่งเชื่อมโยงอย่างหนัก

มันควรค่าแก่การอ่านman chattrเพราะไฟล์สามารถมีคุณสมบัติที่มีประโยชน์มากมาย

คุณอาจพบว่า "การลบแบบ จำกัด " มีประโยชน์ หากวางไว้ในโฟลเดอร์ (ไม่ใช่ไฟล์) หมายความว่าผู้ใดก็ตามที่สร้างไฟล์ภายในโฟลเดอร์จะได้รับอนุญาตให้แก้ไขหรือลบไฟล์นั้น แต่ไม่มีใครอยู่ (ยกเว้นรูท) โฟลเดอร์/tmpมีการตั้งค่าสถานะนี้ คุณสามารถดูสิ่งนี้ได้ด้วยการtตั้งค่าสถานะบน/tmp:

$ ls -l --directory /tmp
drwxrwxrwt 10 root root 4096 Sep  6 09:00 /tmp

หากต้องการตั้งค่าหรือลบการตั้งค่าสถานะการลบที่ จำกัด ในโฟลเดอร์:

chmod +t myFolder      # Add the restricted deletion flag.
chmod -t myFolder      # Remove the restricted deletion flag.
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.