POSIX รับประกันเส้นทางไปยังยูทิลิตี้มาตรฐานหรือไม่?


22

จาก C วิธีที่ง่ายที่สุดในการใช้ยูทิลิตี้มาตรฐาน (เช่น ps) และอื่น ๆ คืออะไร?

POSIX รับประกันว่ามาตรฐานpsนั้นอยู่ใน/bin/psหรือฉันควรรีเซ็ตตัวแปรสภาพแวดล้อม PATH เป็นสิ่งที่ฉันได้รับconfstr(_CS_PATH, pathbuf, n);จากนั้นเรียกใช้ยูทิลิตีผ่าน PATH-search หรือไม่


ฉันมีที่ด้านหลังของหัวของฉันที่ POSIX พูดสำหรับคำสั่งจำนวนหนึ่งในหมู่พวกเขาed (1) (ซึ่งเป็นสิ่งสำคัญสำหรับmksh ) ว่าถ้าพวกเขามีอยู่พวกเขาก็ต้องสามารถเข้าถึงได้ภายใต้/binเช่น/bin/edจะต้องใช้งานได้ ถ้าติดตั้ง ed แล้ว ฉันไม่สามารถหาได้ในตอนนี้ แต่ฉันรู้ว่า LSB ขึ้นอยู่กับมันและฉันประสบความสำเร็จในการป้องกันการรายงานข้อบกพร่องโดยใช้เหตุผลนั้นอย่างน้อยก็ต้องเป็นจริงในบางจุด (หรือเป็นสิ่งอื่นที่ไม่ใช่ POSuX และฉันจำเดือนที่เหลือ แต่ส่วนที่เหลือเป็นเรื่องจริง)
mirabilos

คำตอบ:


33

ไม่ไม่ส่วนใหญ่สำหรับเหตุผลที่ไม่ต้องการให้ระบบปฏิบัติตามค่าเริ่มต้นหรือปฏิบัติตามมาตรฐาน POSIX เท่านั้น (ยกเว้นมาตรฐานอื่นใด)

ยกตัวอย่างเช่น Solaris (ได้รับการรับรองระบบตามมาตรฐาน) เลือกกันได้ย้อนหลังค่าสาธารณูปโภคใน/binซึ่งอธิบายว่าทำไมประพฤติเหล่านั้นในรูปแบบที่เป็นความลับและให้สาธารณูปโภค POSIX สอดคล้องในสถานที่แยกต่างหาก ( /usr/xpg4/bin, /usr/xpg6/bin... สำหรับรุ่นที่แตกต่างกันของ XPG (ตอนรวม เป็น POSIX) มาตรฐานซึ่งเป็นส่วนหนึ่งขององค์ประกอบเสริมใน Solaris)

แม้จะไม่รับประกันว่าจะอยู่ในsh /binบน Solaris /bin/shเคยเป็น Bourne shell (ดังนั้นจึงไม่เข้ากันได้กับ POSIX) จนถึง Solaris 10 ในขณะที่ตอนนี้คือ ksh93 ใน Solaris 11 (ยังไม่เข้ากันได้กับ POSIX อย่างสมบูรณ์ แต่ในทางปฏิบัติมากกว่า/usr/xpg4/bin/sh)

จาก C คุณสามารถใช้exec*p()และสมมติว่าคุณอยู่ในสภาพแวดล้อม POSIX (โดยเฉพาะเกี่ยวกับPATHตัวแปรสภาพแวดล้อม)

คุณสามารถตั้งค่าPATHตัวแปรสภาพแวดล้อมได้

#define _POSIX_C_SOURCE=200809L /* before any #include */
...
confstr(_CS_PATH, buf, sizeof(buf)); /* maybe append the original
                                      * PATH if need be */
setenv("PATH", buf, 1);
exec*p("ps"...);

หรือคุณสามารถกำหนดเวลาสร้างเส้นทางของยูทิลิตี้ POSIX ที่คุณต้องการเรียกใช้ (โดยคำนึงถึงว่าในบางระบบเช่น GNU คุณต้องมีขั้นตอนเพิ่มเติมเช่นการตั้งค่าPOSIXLY_CORRECTตัวแปรเพื่อให้แน่ใจว่าสอดคล้อง)

คุณสามารถลองสิ่งต่างๆเช่น:

execlp("sh", "sh", "-c", "PATH=`getconf PATH`${PATH+:$PATH};export PATH;"
                         "unset IFS;shift \"$1\";"
                         "exec ${1+\"$@\"}", "2", "1", "ps", "-A"...);

ในความหวังว่ามีที่shอยู่ใน$PATHว่ามันเป็นบอร์นเหมือนว่ายังมีgetconfและว่ามันเป็นหนึ่งในรุ่นของ POSIX คุณสนใจกำลังที่


แล้วคุณจะทำยังไงกับ #!?
โจชัว

13
@ โจชัว: คุณอธิษฐานที่/usr/bin/envมีอยู่และส่วนใหญ่เป็นไปตาม POSIX
เควิน

3
@Kevin หรือคุณคุ้นเคยกับนิสัยใจคอของ palaeo-unix และปรับ #! บรรทัดที่จะใช้เส้นทางที่ถูกต้อง
cas

3
@ Kevin: เลขที่/usr/bin/envเป็นแม้แต่น้อยแบบพกพา (ในทางปฏิบัติ) /bin/shสับกว่า ต่อ POSIX วิธีแบบพกพาที่จะเขียนสคริปต์เปลือกคือไม่มี#!ที่ทั้งหมด หากไฟล์สามารถดำเนินการได้ แต่ENOEXEC(ไม่ใช่ไบนารีที่ถูกต้อง) execvpให้เรียกใช้งานผ่านเชลล์มาตรฐาน :-) #!/bin/shแน่นอนในการปฏิบัตินี้เป็นความคิดที่ไม่ดีและคุณควรใช้เพียง
..

2
@GeoffNixon ส่วนที่คุณอ้างถึงเป็นอีกทางเลือกหนึ่งเมื่อไม่ต้องการใช้ไม่ได้หรือไม่ต้องการใช้ _POSIX_C_SOURCE เป็นการตั้งค่าของ$PATHเชลล์จากแทน C
Stéphane Chazelas

3

อันที่จริงผมส่วนใหญ่จะตอบว่าใช่ POSIX รับประกัน:

  1. ว่ามีเป็นเส้นทางสัมบูรณ์ไปเป็นรุ่นมาตรฐานของยูทิลิตี้ที่ระบุไว้ในแต่ละครั้ง
  2. และคุณจะต้องสามารถค้นหาเส้นทางสัมบูรณ์นี้และสามารถใช้งานยูทิลิตีนี้ได้

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

อันที่จริงเพียงวิธีมาตรฐานที่กำหนดจะทำเช่นนี้ในมาตรฐานคือ (ใน C) ผ่านunistd.h's _CS_PATH หรือในเปลือกผ่านการรวมกันของcommandและgetconfสาธารณูปโภคเช่นPATH="$(command -p getconf PATH)" command -v psมักจะต้องกลับเส้นทางแน่นอนไม่ซ้ำกันของPOSIX สอดคล้องมาพร้อมกับระบบเฉพาะ นั่นคือในขณะที่มันถูกกำหนดให้มีการนำไปปฏิบัติซึ่งพา ธถูกรวมไว้ในตัวแปร PATH เริ่มต้นของระบบการใช้ประโยชน์เหล่านี้จะต้องพร้อมใช้งานไม่ซ้ำกันและสอดคล้องกับหนึ่งในพา ธ ที่ระบุในนั้นps

ดู: < unistd.h > คำสั่ง


แต่สำหรับ sh มีปัญหาไก่และไข่ ซึ่งPATH=$(command -p getconf PATH)จะใช้งานได้จากเปลือก POSIX ในสภาพแวดล้อม POSIX POSIX ไม่ได้ระบุว่าคุณจะเข้าสู่สภาพแวดล้อมนั้นได้อย่างไรว่ามันถูกบันทึกไว้ ยกตัวอย่างเช่นบน Solaris คุณมี/usr/xpg4/bin/getconfและ/usr/xpg6/bin/getconfที่จะกลับมาเป็นค่าที่แตกต่างกันสำหรับ_CS_PATHทั้งสองรุ่นที่แตกต่างของมาตรฐานและค่า/usr/xpg4/binมิได้อยู่ในค่าเริ่มต้นของ/usr/xpg6/bin $PATHมี/usr/bin/getconfIIRC ตัวใดที่ให้มาตรฐาน XPG4 แก่คุณ
Stéphane Chazelas

เป็นเรื่องจริงสำหรับรุ่น Solaris 11+ (รับรอง UNIX 03+) หรือไม่? ฉันมักจะอ่าน `` `แอปพลิเคชั่น ... ควรพิจารณาจากการสอบถาม PATH ที่ส่งคืนโดย getconf PATH เพื่อให้แน่ใจว่าชื่อพา ธ ที่ส่งคืนนั้นเป็นชื่อพา ธ สัมบูรณ์และไม่ใช่เชลล์ในตัว ตัวอย่างเช่นเพื่อกำหนดตำแหน่งของยูทิลิตี sh มาตรฐาน: command -v sh ในการใช้งานบางอย่างนี้อาจส่งคืน: / usr / xpg4 / bin / sh `` `หมายความว่านี่จะต้องเป็นรายการที่สอดคล้องกับ POSIX shจากเชลล์เริ่มต้นใด ๆ .
Geoff Nixon

1
ไม่มีสิ่งใดใน POSIX ที่บอกว่าควรมีgetconfคำสั่งในการเริ่มต้น$PATHของระบบที่กำหนด ตัวอย่างเช่นการรับสภาพแวดล้อม POSIX อาจเกี่ยวข้องกับการเริ่มต้นเลเยอร์การจำลองโดยที่คุณจะไม่เรียกใช้คำสั่งเหมือน Unix ใด ๆ (คิดว่า Windows เป็นต้น) เมื่อคุณอยู่ในสภาพแวดล้อมที่เข้ากันgetconf PATH ได้คุณ$PATHจะได้รับโปรแกรมอรรถประโยชน์ที่เข้ากันได้ แต่ถ้าคุณอยู่ในสภาพแวดล้อม POSIX นั่นอาจเป็นกรณีที่เกิดขึ้นแล้ว โปรดทราบว่าอาจจะกลับมาgetconf ps psมีpsbuiltin ที่ได้รับอนุญาต
Stéphane Chazelas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.