curl ที่ทำงานได้บนระบบปฏิบัติการ 100 แบบ
(daniel.haxx.se)- curl จำกัดการเปลี่ยนแปลงเพื่อให้ยังคง build และทดสอบได้แม้ในสภาพแวดล้อมเก่า ๆ และใน pull request ล่าสุดก็ยังกำหนดเงื่อนไขว่าต้องไม่ทำลายความเข้ากันได้กับ
time_tแบบ 32 บิต และแพลตฟอร์ม legacy - แก่นสำคัญไม่ได้อยู่ที่การรักษารายชื่อแพลตฟอร์มไว้ให้มาก แต่คือการรักษาคำมั่นเรื่อง เสถียรภาพของ ABI/API เพื่อให้ผู้ใช้ยังใช้งานได้ต่อแม้อัปเกรดแล้ว
- สิ่งที่สำคัญกว่าจำนวนผู้ใช้ของระบบปฏิบัติการหนึ่ง ๆ คือมีคนที่ดูแลและแก้ไขจริงหรือไม่ และถ้ายังมีผู้ดูแลอยู่ แพลตฟอร์มที่มีผู้ใช้น้อย ก็ยังอาจได้รับการสนับสนุนต่อไป
- curl และ libcurl แพร่หลายด้วยหลักการแบบ portability-first ที่ทำให้ยังอยู่ในสภาพ “build ได้และรันได้” ครอบคลุมทั้งระบบปฏิบัติการ สถาปัตยกรรม CPU และการตั้งค่าที่แปลกเฉพาะ
- สาเหตุหลักที่คำสั่ง curl เก่า ๆ ล้มเหลว มักใกล้เคียงกับการเปลี่ยนแปลงของสภาพแวดล้อมอินเทอร์เน็ต เช่น โฮสต์หรือ URL หายไป และการเปลี่ยนผ่านจาก HTTP ไปสู่ HTTPS มากกว่าจะเป็นเพราะการเปลี่ยนแปลงของ curl เอง
เกณฑ์การเปลี่ยนแปลงที่ไม่ทำลายแพลตฟอร์ม legacy
- ใน pull request ของ curl เมื่อไม่นานมานี้ การเปลี่ยนแปลงจะถูกรวมเข้า git code repository ได้ก็ต่อเมื่อไม่ทำให้การ build หรือการทดสอบบนแพลตฟอร์ม legacy พัง
- การเปลี่ยนแปลงนั้นเกี่ยวข้องกับส่วนของ
time_tและ curl รองรับชนิดtime_tแบบ 32 บิต อยู่แล้ว จึงต้องรักษาพฤติกรรมนี้ไว้ time_tแบบ 32 บิตมีข้อจำกัดในการใช้งานอยู่แล้ว และยิ่งเข้าใกล้ปี 2038 ก็อาจยิ่งมีข้อจำกัดมากขึ้น แต่แพลตฟอร์ม legacy จำนวนมากก็ยังคงอยู่กับเวอร์ชัน 32 บิต- ข้อกำหนดลักษณะนี้ทำให้งานของผู้ร่วมพัฒนายากขึ้น แต่ใน curl มองว่านี่เป็นส่วนหนึ่งของการทำให้การเปลี่ยนแปลงสมบูรณ์พร้อมใช้งาน
ความเข้ากันได้คือคำมั่นที่ใหญ่กว่าจำนวนแพลตฟอร์ม
- โครงการ curl พยายามอย่างต่อเนื่องเพื่อรักษา เสถียรภาพและความเข้ากันได้ของ ABI และ API
- แอปพลิเคชันที่ใช้ libcurl ตั้งแต่ช่วงกลางทศวรรษ 2000 สามารถอัปเกรดเป็น libcurl รุ่นล่าสุดได้โดยไม่ต้องคอมไพล์แอปใหม่ และยังทำงานได้ในลักษณะเดิม
- สคริปต์ curl ที่เขียนไว้ช่วงต้นทศวรรษ 2000 ก็ยังควรคาดหวังได้ว่าจะทำงานบน curl รุ่นล่าสุดได้แทบจะเหมือนเดิม
- ความเข้ากันได้นี้ไม่ใช่แค่ข้อความประชาสัมพันธ์ แต่เป็นหลักการแกนกลางที่ curl และ libcurl ยึดถือ
- ผู้ใช้สามารถพึ่งพา curl ได้
- แม้จะมีรีลีสที่มีบั๊กอยู่บ้าง ก็ยังพยายามออกอัปเดตที่ทำให้ผู้ใช้ย้ายไปเวอร์ชันใหม่ได้โดยไม่ต้องเจอกับความเจ็บปวดแบบการอัปเกรดซอฟต์แวร์ทั่วไป
- ท่าทีที่ว่าไม่ควรทำของที่ใช้งานได้ดีอยู่แล้วให้พังโดยไม่จำเป็น เป็นส่วนหนึ่งของเกณฑ์การบำรุงรักษา
สิ่งที่ชี้ขาดการรองรับคือผู้ดูแล
- จำนวนผู้ใช้ของแพลตฟอร์มใดแพลตฟอร์มหนึ่ง ไม่ใช่แรงจูงใจหลักที่ทำให้ curl ตัดสินใจสนับสนุนแพลตฟอร์มนั้นต่อไป
- เกณฑ์ที่สำคัญกว่าคือใครเป็นคนรับงาน และมีการบำรุงรักษาที่จำเป็นเกิดขึ้นจริงหรือไม่
- หากมีผู้ร่วมพัฒนาที่คอยตรวจสอบให้ curl ยังทำงานได้บนแพลตฟอร์มใดแพลตฟอร์มหนึ่ง curl ก็ยังอาจรันต่อไปได้แม้บนแพลตฟอร์มที่ขึ้นชื่อว่ามีผู้ใช้น้อย
- ช่วงเวลาที่แพลตฟอร์มหนึ่งแทบจะหายไปจาก curl จริง ๆ คือเมื่อโค้ดที่จำเป็นสำหรับแพลตฟอร์มนั้นไม่ได้รับการดูแลอีกต่อไป
- โค้ดที่ไม่มีคนดูแลอาจยังคงอยู่ในสภาพใช้งานได้เป็นเวลาหลายปี
- และอาจต้องใช้เวลานานกว่าจะรู้ว่า curl ไม่ทำงานบนแพลตฟอร์มหนึ่ง ๆ แล้ว
- ในทางกลับกัน แม้เป็นแพลตฟอร์มที่มีผู้ใช้มาก หากขาดผู้ดูแลที่มีทั้งความตั้งใจและความรู้ในการจัดการปัญหาเฉพาะของแพลตฟอร์มนั้น การดูแลก็ทำได้ยาก
เหตุผลที่แพร่หลายไปในสภาพแวดล้อมที่หลากหลาย
- curl และ libcurl ให้ความสำคัญอย่างมากกับการทำให้ build ได้และรันได้ ในสภาพแวดล้อมให้มากที่สุดเท่าที่เป็นไปได้
- ท่าทีที่พยายามรักษาให้ทำงานได้แม้ในคอนฟิกที่แปลกหรือไม่ธรรมดา เป็นหนึ่งในเหตุผลที่ทำให้แพร่หลายไปยังระบบปฏิบัติการและสถาปัตยกรรม CPU จำนวนมาก
- ผู้ใช้และบริษัทจำนวนมากยังคงใช้งานแพลตฟอร์มเก่า เฉพาะทาง หรือ legacy อยู่ต่อไป
- สำหรับคนกลุ่มนี้ การคงความสามารถด้านการรับส่งข้อมูลของ curl ไว้มักดีกว่าในแง่ความปลอดภัย เมื่อเทียบกับการทำระบบทดแทนขึ้นเอง
- หากไม่มีความจำเป็นต้องทำให้ฟีเจอร์พัง ก็ย่อมดีกว่าที่จะปล่อยให้ผู้ใช้เดิมยังพึ่งพา curl ได้ต่อไป
การถอดการรองรับเกิดขึ้นช้าและทำอย่างเปิดเผย
- curl เองก็มีการถอดการรองรับบางอย่างออกเป็นครั้งคราว
- เป้าหมายหลักของการถอดออกมักเป็นการรองรับ third-party library ที่การใช้งานลดลงจนกำลังหายไป แต่ก็อาจเกิดในด้านอื่นได้เช่นกัน
- การยุติการรองรับจะดำเนินไปอย่างช้า รอบคอบ และสื่อสารอย่างเปิดเผย
- ผู้ใช้ที่อยากรู้ควรได้รับทราบการเปลี่ยนแปลงล่วงหน้า
- ผู้ใช้ควรมีเวลาสำหรับเตรียมตัว หรือคัดค้านได้หากเห็นว่าข้อเสนอนั้นไม่เหมาะสม
- หากผู้ใช้ไม่สามารถสังเกตเห็นการเปลี่ยนแปลงของพฤติกรรมได้ ก็จะไม่ถือว่าเป็นการเปลี่ยนแปลง
- curl ถูกสร้างขึ้นมาเพื่อผู้ใช้ และถ้าผู้ใช้ยังต้องการพฤติกรรมแบบใดต่อไป พฤติกรรมนั้นก็ควรคงอยู่
เหตุผลจริงที่คำสั่งเก่าล้มเหลว
- โปรโตคอลอินเทอร์เน็ตและเวอร์ชันต่าง ๆ มีทั้งเกิดขึ้นและหายไปตามกาลเวลา
- คำสั่ง curl command line จำนวนมากที่เขียนไว้ในปี 2002 อาจไม่ทำงานเหมือนเดิมในปัจจุบัน
- สาเหตุที่ล้มเหลวอาจไม่ใช่ตัว curl เอง แต่เป็นเพราะ ชื่อโฮสต์และ URL ที่ใช้ในตอนนั้นไม่ทำงานแล้ว
- หนึ่งในเหตุผลใหญ่ที่คำสั่ง curl จากปี 2002 ไม่ทำงานเหมือนเดิมในวันนี้ คือการเปลี่ยนผ่านจาก HTTP ไปเป็น HTTPS
- ต่อให้ในปี 2002 จะมีเว็บไซต์ที่ใช้ TLS หรือ SSL อยู่บ้าง แต่ในเวลานั้นก็ยังไม่ใช่เรื่องปกติ และเวอร์ชันของโปรโตคอล TLS ที่ใช้ตอนนั้นอาจถูกมองว่าไม่ปลอดภัยในปัจจุบัน
- TLS library รุ่นใหม่และ curl อาจปฏิเสธการเชื่อมต่อกับการตั้งค่า TLS เก่า ๆ ที่ไม่เคยอัปเดต
- ต่อให้เก็บไฟล์ executable ของ curl จากปี 2002 ไว้แล้วลองนำมารันวันนี้ มันก็อาจเชื่อมต่อกับเว็บไซต์ HTTPS ยุคใหม่ไม่ได้
- และนั่นไม่ได้เกิดจากการเปลี่ยนแปลงของ curl แต่เกิดจากการเปลี่ยนแปลงใน ชั้นโปรโตคอลการรับส่งข้อมูล
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
เป็นความสำเร็จที่น่าทึ่งมาก Curl เป็นเครื่องมือที่เหมือนพรจริง ๆ
น่าสนใจที่ Daniel เน้นเรื่อง 32-bit time_t ว่าเป็นจุดสำคัญของความเข้ากันได้ ถ้าเป้าหมายคือทำให้มันยังทำงานได้ต่อไปบนหลายระบบปฏิบัติการ ก็สมเหตุสมผลมาก เพียงแต่ตอนนี้ปี 2038 ก็เหลืออีกแค่ 14 ปี และมันใกล้กว่าช่วงที่ curl ออกมาครั้งแรกมาก เลยสงสัยว่าเมื่อไรการพยายามรองรับเวลาแบบ 32 บิตจะถูกมองว่าไม่คุ้มอีกต่อไป เดาว่าน่าจะราว ๆ 3 เดือนหลัง วัน Y2K38 ผ่านไป หรืออาจนานกว่านั้นก็ได้
มีอย่างหนึ่งที่นักพัฒนาเรียนรู้เมื่อทำงานใกล้ชิดกับทีมปฏิบัติการมากขึ้น คือ ยิ่งมีคนพึ่งพามาก ภาระยิ่งมาก โครงสร้างพื้นฐานและระบบศูนย์กลาง เมื่อมีสิ่งต่าง ๆ มาพึ่งพามากพอ ก็จะสูญเสียความคล่องตัว และแม้แต่การเปลี่ยนแปลงเล็กน้อยก็ยากมาก
ถ้าเป็นบริการของตัวเองที่มีทั้งแบ็กเอนด์และฟรอนต์เอนด์ แล้วอยากรื้อ API ระหว่างสองส่วนนี้ใหม่ทั้งหมด จะมีใครสนล่ะ ก็แค่ทำไป
แต่ถ้าคุณอยากลบ edge case แปลก ๆ ในเทมเพลตพื้นฐานเพียงเพราะมัน “ดูไม่สวย” คุณต้องไปดูบริการเก่า 20 ตัว บริการกึ่งสมัยใหม่อีก 20 ตัวที่ไม่มีใครอยากแตะ และบริการอีก 50 ตัวที่ใช้งานสิ่งนั้นอยู่ แค่งานที่ต้องทำเพื่อให้รู้ว่าการเปลี่ยนนั้นใหญ่แค่ไหนก็ระดับนั้นแล้ว นี่ยังไม่รวมถึงการลงมือเปลี่ยนจริง หรือการย้อนรอยความลับพิสดารต่าง ๆ เลย
จะบอกว่าเป็นงานหรูหราก็คงไม่ใช่ แต่การเปลี่ยนทุกอย่างข้างใต้โดยที่ไม่มีใครสังเกตเห็น พร้อมกับ ค้ำจุนตัวเอกที่ส่องประกายต่อไป เป็นสิ่งที่ทำให้โรดดี้หรือผู้ดูแลระบบภูมิใจได้
ในรายการนั้นมีของที่ ไม่มีรีลีสมานานเกิน 25 ปี อยู่ไม่น้อย ตอนนี้ยังสร้างบิลด์ปัจจุบันสำหรับ SCO, Xenix, OS/2, NextStep กันอยู่จริงหรือ?
ผมเคยลองใช้ของพวกนี้ และรู้ว่ามี curl อยู่บนนั้น แต่จากประสบการณ์ curl บนระบบเหล่านั้นมักเป็นเวอร์ชันที่เก่าอย่างน้อย 15 ปีเสมอ
ถ้าบอกว่าไม่อยากทำลาย support matrix ใด ๆ แต่หลายรายการใน matrix นั้นผ่านไปนานเกิน 10 ปีมากแล้วนับจากบิลด์ล่าสุด แล้วจะรู้ได้อย่างไรว่าจริง ๆ มันยังไม่พัง?
ไม่แน่ใจว่าจะยังบิลด์สำหรับ Xenix ได้ด้วยซ้ำ GCC ที่ใหม่ที่สุดที่พอใช้เป็น target ได้คือ 2.7 และนั่นก็โบราณมากอยู่แล้ว ยิ่งถ้าคิดถึงโค้ดเครือข่ายยิ่งใช่ น่าจะประมาณว่า “เคยทำงานได้บนระบบเหล่านั้นในช่วงเวลาหนึ่ง” มากกว่า
สำหรับคำพูดที่ว่า “มีผู้ใช้และบริษัทจำนวนมากที่ยังยึดติดกับแพลตฟอร์มเก่า เฉพาะทาง และเลกาซี และเราไม่มีอะไรจะทำได้” คนส่วนใหญ่ รวมถึงนักพัฒนา proprietary closed source ด้วย ต่างก็สร้างซอฟต์แวร์ที่ต้นสัญญาอนุญาตมีข้อความประมาณว่า “โปรแกรมนี้แจกจ่ายด้วยความหวังว่าจะเป็นประโยชน์ แต่ไม่มีการรับประกันใด ๆ รวมถึงไม่มีการรับประกันโดยนัยเรื่องความสามารถเชิงพาณิชย์หรือความเหมาะสมต่อวัตถุประสงค์เฉพาะ”
แบบนั้นต้นทุนต่ำ
ในทางกลับกัน บางคนรวมถึงผมเองพัฒนาซอฟต์แวร์ที่ รับประกันความเหมาะสมต่อวัตถุประสงค์ และมีการรับประกันแบบชัดเจนและเด็ดขาด
แบบนั้นแพงมากและช้ามาก
ถ้าความเสียหายจากสิ่งที่พังอาจทำให้คนตาย สิ่งแวดล้อมเสียหาย หรือเกิดความเสียหายระดับหลายล้านดอลลาร์ การใช้แพลตฟอร์มเก่าเฉพาะทางที่นักพัฒนาซึ่งช้าและรอบคอบมากตรวจสอบอย่างละเอียดมาแล้ว 30-40 ปีต่อไปก็สมเหตุสมผล
อย่างน้อยผมก็บอกตัวเองแบบนั้นเวลาไปดู Ada บน INTEGRITY ที่รันบน PowerPC
ถ้าคนตายหนึ่งคนอาจนำไปสู่ความเสียหายหลายล้านดอลลาร์ ก็ควรหลีกเลี่ยงซอฟต์แวร์หรือแพลตฟอร์มที่มีฐานนักพัฒนาเล็กพอ ๆ กับ “จำนวนนักเล่นกลชาวฝรั่งเศสที่เป็นโรค Wilson”
เหตุผลหนึ่งที่มันได้รับความนิยม น่าจะเป็นเพราะ สัญญาอนุญาตแบบผ่อนปรน ตอนแรกผมเดาว่าเป็น MIT license แต่ดูเหมือนจะต่างออกไปนิดหน่อย [1] มีใครอธิบายแบบง่าย ๆ ได้ไหมว่าจุดต่างหลักจาก MIT คืออะไร? ในหน้าลิขสิทธิ์ไม่มีคำอธิบายละเอียด
[1] https://curl.se/docs/copyright.html
“ยกเว้นตามที่มีอยู่ในประกาศนี้ ห้ามใช้ชื่อของผู้ถือลิขสิทธิ์ในการโฆษณาหรือส่งเสริมการขาย การใช้งาน หรือการดำเนินการอื่นใดเกี่ยวกับซอฟต์แวร์นี้ โดยไม่ได้รับอนุญาตเป็นลายลักษณ์อักษรล่วงหน้าจากผู้ถือลิขสิทธิ์”
[1] https://spdx.org/licenses/curl.html
ผมนึกว่าแค่เวอร์ชัน Linux อย่างเดียวก็น่าจะเกือบ 100 แล้ว แต่นี่นับ Linux ทุกเวอร์ชันรวมเป็นระบบปฏิบัติการเดียวแล้วยังได้ 100 ก็น่าทึ่ง
จากประสบการณ์ส่วนตัว ถ้าเขียนโค้ดโดยคำนึงถึง ระบบเลกาซี หลาย ๆ แบบ โค้ดมักจะดีขึ้นโดยรวม
คุณจะทำตามแนวปฏิบัติในการเขียนโค้ดที่รู้จักกันดีได้ดีขึ้น เช่น การตั้งชื่อ ชนิดข้อมูล และการแยกเป็นโมดูล รวมถึงปฏิบัติตามมาตรฐานได้ดีขึ้นด้วย ยกเว้นในส่วนที่ระบุชัดเจนไว้ abstraction จะแข็งแรงขึ้น บั๊กโดยเฉพาะบนแพลตฟอร์มสมัยใหม่จะลดลง และระบบบิลด์ก็ทนทานขึ้น ทำให้เข้ากันได้กับแพลตฟอร์มในอนาคตโดยอัตโนมัติ หรืออย่างน้อยก็ทำให้รองรับได้ง่ายมาก
อย่างไรก็ตาม ถ้ามุ่งเป้าไปที่ระบบเลกาซีแค่ไม่กี่ตัว ข้อสังเกตนี้อาจไม่จริง เพราะอาจประคองไปได้ด้วยการปะผุและแฮ็กแปลก ๆ หลายอย่างรวมกัน
การแยก FreeDOS, DR-DOS, MS-DOS เป็นระบบปฏิบัติการคนละตัวดูแปลก เพราะพวกมันคล้ายกันมาก และต่างจาก Unix หลายสายพันธุ์ตรงที่แทบจะ เข้ากันได้ในระดับ ABI
ทั้งอย่างนั้นผู้คนก็ยังอยากเขียนมันใหม่ด้วย Rust อยู่ดี Rust รองรับสถาปัตยกรรมและระบบปฏิบัติการทั้งหมดนั้นได้จริงหรือ?
เรื่องอ่านที่เกี่ยวข้อง: บทความเกี่ยวกับการกำเนิดของ curl และประวัติของมัน (1)
(1) https://daniel.haxx.se/blog/2023/03/20/twenty-five-years-of-...