ฉันได้ลองเรียกคำสั่ง chmod ในลำดับที่ไม่ถูกต้อง chmod file.txt -r
สิ่งนี้ทำงานได้ด้วยเหตุผลบางอย่าง chmod file.txt +r
ในทางกลับกันปฏิเสธที่จะทำงาน ทำไมนี้ ด้วยเหตุผลอะไรคำสั่งหนึ่งทำงานและอื่น ๆ ไม่ได้?
ฉันได้ลองเรียกคำสั่ง chmod ในลำดับที่ไม่ถูกต้อง chmod file.txt -r
สิ่งนี้ทำงานได้ด้วยเหตุผลบางอย่าง chmod file.txt +r
ในทางกลับกันปฏิเสธที่จะทำงาน ทำไมนี้ ด้วยเหตุผลอะไรคำสั่งหนึ่งทำงานและอื่น ๆ ไม่ได้?
คำตอบ:
นี่เป็นสิ่งที่แปลกประหลาดของวิธีที่ GNU chmod จัดการกับอินพุตและไม่สามารถพกพาไปยังการใช้งาน chmod ที่ใช้ POSIX ได้ทั้งหมด
โปรดทราบว่าไวยากรณ์ของPOSIXchmod
coomand-line ต้องการโหมดที่จะมาก่อนเช่นเดียวกับGNUchmod
(ตัวเลือกควรมาก่อนโหมดด้วย) สิ่งอื่นใดก็คือการเล่นโวหารที่ไม่มีเอกสาร
ทีนี้ลองดูว่าทำไมมันถึงเกิดขึ้นในการติดตั้งแบบนี้
มันบอกเป็นนัยในคู่มือ :
แม้ว่าโดยทั่วไปแล้ว '
chmod a-w file
' จะดีกว่าและchmod -w file
(ถ้าไม่มี--
) จะบ่นว่ามันทำงานแตกต่างจากสิ่งที่chmod a-w file
จะทำหรือไม่
สั้น ๆ , ตัวเลือกแยกวิเคราะห์โดยจะมีคำนำหน้าด้วยgetopt
-
เช่นเดียวกับในls -a
, a
เป็นตัวเลือก แบบยาวls --all
มีall
เป็นตัวเลือก rm -rf
(เทียบเท่าrm -r -f
) มีทั้งตัวเลือกr
และf
ทุกสิ่งทุกอย่างเป็นอาร์กิวเมนต์ที่ไม่ใช่ตัวเลือกที่เรียกว่าในทางเทคนิคตัวถูกดำเนินการ ฉันชอบที่จะเรียกข้อโต้แย้งตำแหน่งเหล่านี้ตามความหมายของพวกเขาถูกกำหนดโดยตำแหน่งญาติ ในchmod
อาร์กิวเมนต์ตำแหน่งแรกคือโหมดและอาร์กิวเมนต์ตำแหน่งที่สองคือชื่อไฟล์
-
อย่างดีที่สุดโหมดไม่ควรนำไปด้วย ถ้าเป็นเช่นนั้นคุณควรใช้--
ในการบังคับให้แจงเป็นตัวถูกดำเนินการแทนตัวเลือก (เช่นใช้chmod a-w file
หรือchmod -- -w file
แทนที่จะchmod -w file
เป็นเช่นนี้POSIX แนะนำด้วย
หากคุณดูซอร์สโค้ดคุณจะสังเกตเห็นว่ามันใช้getoptเพื่อแยกวิเคราะห์ตัวเลือกบรรทัดคำสั่ง ที่นี่มีการจัดการพิเศษสำหรับโหมด 'ไม่ถูกต้อง' เช่น-w
:
case 'r':
case 'w':
case 'x':
case 'X':
case 's':
case 't':
case 'u':
case 'g':
case 'o':
case 'a':
case ',':
case '+':
case '=':
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
/* Support nonportable uses like "chmod -w", but diagnose
surprises due to umask confusion. Even though "--", "--r",
etc., are valid modes, there is no "case '-'" here since
getopt_long reserves leading "--" for long options. */
ยกตัวอย่างของคุณ:
chmod a-r file.txt
จะเป็นการเรียกที่แข็งแกร่งที่สุดchmod +r file.txt
ใช้งานได้เนื่องจากอาร์กิวเมนต์แรกถูกตีความตำแหน่งเป็นโหมดchmod -r file.txt
ยังใช้งานได้เพราะ-r
ถูกตีความว่าเป็นr
ตัวเลือกสั้น ๆและใส่กล่องพิเศษchmod -- -r file.txt
ถูกต้องและทำงานได้เนื่องจาก-r
ถูกตีความตำแหน่งเป็นโหมด ความแตกต่างนี้จากกรณีที่โดยไม่ต้อง--
เพราะไม่ได้ตีความว่าเป็นตัวเลือก--
-r
chmod file.txt -r
ยังใช้งานได้เพราะ-r
ถูกตีความว่าเป็นr
ตัวเลือกสั้น ๆและใส่กล่องพิเศษ ตัวเลือกไม่ขึ้นอยู่กับตำแหน่ง เทคนิคนี้เป็นการดูหมิ่นที่ไม่มีเอกสารทางเทคนิคchmod file.txt +r
ไม่ทำงานเนื่องจาก+r
ตัวถูกดำเนินการไม่ใช่ตัวเลือก ตัวถูกดำเนินการแรก ( file.txt
) ถูกตีความว่าเป็นโหมด ... และล้มเหลวในการแยกวิเคราะห์getopt
คำสั่งไม่ห้องสมุดประจำในส่วนที่ 3 ประการที่สองนั่นคือการอ้างอิงถึงoptstring
คือรายการของตัวเลือกที่ยอมรับ (ในchmod
แหล่งที่มาoptstring
ถูกตั้งค่าเป็น"Rcfvr::w::x::X::s::t::u::g::o::a::,::+::=::"
) ส่วน "โหมดการสแกน" ที่เชื่อมโยงนั้นไม่มีส่วนเกี่ยวข้องกับอาเรย์อาร์กิวเมนต์ argv
ที่มี args ที่ส่งผ่านเข้าไปในโปรแกรม
a+rwx
และทำอะไรเช่นchmod * +r
นั้นและa+rwx
ไฟล์จะเกิดขึ้นก่อนในการขยายแบบกลม