งาน รายการ และสัญญา

ไม่ใช่ทุกอย่างในบริษัทใหญ่ที่เกี่ยวข้องกับการเขียนโค้ด บางครั้ง คุณต้องทำสิ่งเมตาจำนวนมากเพื่อจัดการโครงการ นี่เป็นสองเรื่องราวของการทำอย่างนั้น

คุณเคยเห็นสิ่งที่เกิดขึ้นเมื่อทีมมีรายการ “สิ่งที่ต้องทำ” ยาวๆ และไม่รู้ว่าจะเริ่มต้นจากตรงไหน? คุณเคยนั่งตรงนั้นและเป็นสักขีพยานในการสนทนาแบบวงกลมของคนที่พยายามจะให้ความสำคัญกับรายการเหล่านั้น เช่น P0, P1, P2 หรือไม่? พวกเขายังไม่รู้ว่าจะเริ่มต้นจากตรงไหน?

“AB-123 คือ P0…”

“อ๋อ แน่นอน” “ใช่” “แน่นอนอยู่แล้ว”

“แต่เราทำไม่ได้เพราะ XX-996 ยังไม่เสร็จ…”

“XX-996 คือ P2 ดังนั้นจึงไม่สามารถทำได้ก่อน P0…”

… เสียงคุ้นเคย?

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

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

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

สิ่งนี้ดำเนินต่อไปจนกระทั่งเรามี 10 หรือ 15 รายการที่ผู้คนคิดว่าทีมควรทำด้วยเหตุผลอย่างใดอย่างหนึ่ง จากนั้นฉันก็เริ่มจากด้านหนึ่งของกระดาน เลือกรายการ และถามว่าขึ้นอยู่กับส่วนอื่นๆ หรือไม่ ปรากฎว่าอันที่จริงอันนี้มีการขึ้นต่อกัน ดังนั้นมันถูก “บล็อก” โดยรายการอื่นบนกระดาน ฉันดึงลูกศรจากอันแรกไปอันที่สอง

สิ่งนี้ดำเนินต่อไปจนกระทั่งเราได้เยี่ยมชม “โหนด” ทั้งหมดบนกระดาน และเรามีสิ่งที่น่าสนใจให้ดู มีบางโหนดที่ถูกบล็อกโดยสิ่งอื่น ๆ ทุกประเภท แต่ก็มีบางโหนดที่ไม่มีอะไรปิดกั้น สิ่งนี้ไม่ขึ้นกับ P-this ใดๆ P- ที่ให้ความสำคัญกับผู้คนผูกมัดกับงานเหล่านี้ ฉันบอกเป็นนัยว่าลำดับความสำคัญของพวกเขาไม่ได้มีความหมายอะไรเลยหากคุณไม่สามารถคืบหน้าได้ ดังนั้นให้นำสิ่งที่สามารถทำได้ในตอนนี้และดำเนินการกับพวกเขา หากคุณทำสิ่งนี้ต่อไป ในที่สุดคุณก็จะได้ P0 ที่คุณคิดและมันจะเกิดขึ้น

จริงๆแล้วสถานการณ์คลี่คลายเหมือน Makefile ยักษ์สำหรับฉัน นี่คือที่ที่คุณพูดว่า โอเค ในการสร้าง my_project ฉันต้องสร้าง httpclient.o และ logging.o ในการสร้าง httpclient.o ฉันต้องมี libcurl ในระบบ ฉันยังไม่มี libcurl ในระบบ ดังนั้นฉันจึงยังไม่สามารถสร้าง httpclient ได้ แต่ฉัน *สามารถสร้าง* การบันทึกได้ เพราะมันไม่ได้ขึ้นอยู่กับอะไรเลย ดังนั้นคุณสามารถทำงานเกี่ยวกับการบันทึกหรือใช้งาน libcurl ได้ หรือถ้าคุณมีคนงานสองคน ให้ทำทั้งสองอย่างพร้อมกัน ไชโย

สำหรับฉัน “ลำดับความสำคัญ” ส่วนใหญ่เป็นไม้ประดับ ดูเหมือนว่าคุณจะใช้มันเป็นตัวแบ่งสาย ตัวอย่างเช่น สมมติว่าคุณมีห่วงโซ่การพึ่งพาหนึ่งชุดที่บล็อกงานที่เรียกว่า P0 (ลำดับความสำคัญสูงสุดตามที่คาดคะเน) และอีกรายการหนึ่งบล็อก P3 (โชคดี) คุณอาจพยายามทำอย่างแรกให้เสร็จมากกว่าทำอย่างหลัง และอาจเริ่มทำสิ่งนั้นก่อน มันเป็นระบบบอกใบ้ ไม่ใช่อาณัติ

มีเรื่องสนุกอีกอย่างที่พวกเราสองสามคนทำในงานเดียวกันนั้นในเวลาเดียวกัน ผู้ที่มีความคิดเหมือนกันหลายคนตัดสินใจว่าเราต้องการวิธีที่ดีกว่าในการจัดส่งซอฟต์แวร์ระบบที่สร้างโดยองค์กร ซึ่งทำงานบนทุกเครื่องในฟลีท – “ไบนารีแบบกระจายอย่างกว้างขวาง” หากคุณต้องการ พวกเราสามคนตัดสินใจที่จะทำมัน

เนื่องจากไม่มีใครเคยทำสิ่งนี้มาก่อน เราจึงรู้ว่าไม่มีทางที่เราจะได้รับ “แผนที่ถนน” ที่วางไว้ข้างหน้า เรารู้ว่าความสำเร็จเป็นอย่างไร แต่เราก็รู้ด้วยว่าเราจะต้องปรับตัวให้เข้ากับสภาพที่พบระหว่างทาง ด้วยเหตุผลดังกล่าว เราจึงเริ่มต้นด้วยการจัดส่งไบนารีด้วยมือ จากนั้นจึงจดบันทึกว่าส่วนใดของกระบวนการที่น่ากลัว เมื่อเราคิดว่าเรารับมือได้แล้วว่ามันคืออะไรและจะทำให้ดีขึ้นได้อย่างไร เราจะทำขั้นตอนนั้นโดยอัตโนมัติ จากนั้นเราจะย้ายสแต็กขึ้นไปหนึ่งระดับแล้วทำอีกครั้ง สิ่งนี้ดำเนินต่อไปจนกระทั่งสิ่งต่าง ๆ เกือบจะดำเนินไปเอง … และเรามีรายการ “สิ่งที่คุณต้องมีในการจัดส่ง WDB อย่างมีสติ” พอสมควร

ฉันเคยพูดถึงเรื่องนี้มาก่อนแล้ว แต่สิ่งที่ฉันยังไม่ได้แบ่งปันคือวิธีที่เราจัดการกับแนวคิด “โอ้ แล้วถ้าเราทำสิ่งนี้” ที่เกิดขึ้นระหว่างทาง เราคิดวิธีจัดการกับสิ่งเหล่านี้ และฉันชอบคิดว่ามันค่อนข้างมีมนุษยธรรมและไม่ได้ให้คำมั่นสัญญาใดๆ ที่เราไม่สามารถรักษาได้ นี่คือวิธีการทำงาน

เนื่องจากมีพวกเราสามคนทำงานในโครงการนี้ และชื่อยูนิกซ์ของเรา (ซึ่งเป็นชื่อเล่น IRC ของเราด้วย) จึงเป็นชื่อย่อที่แตกต่างกันสามชื่อ (A, B และ R) เราจึงใช้สิ่งนั้นเพื่อประโยชน์ของเรา เราจะเปิด IRC และพูดคุยเกี่ยวกับสิ่งต่าง ๆ และเมื่อเราได้แนวคิด เราจะเพิ่มรายการอื่นจากชุดของเราเอง นั่นคือ ความคิดแรกของฉันคือ R1 จากนั้น R2 จากนั้น R3 ในขณะที่ความคิดของคุณ B เป็น B1, B2, B3 และความคิดของคุณ A คือ A1, A2, A3 และอื่นๆ

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

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

“เฮ้ B ใน B5 คุณคิดที่จะเก็บสิ่งนั้นไว้ที่ไหน”

“ใช่ ฉันต้องการสิ่งนั้นใน svn”

“ใช่แล้ว มันทำให้ฉันเข้าใจมากขึ้นแล้ว ขอบคุณนะ!”

… คุณได้รับความคิด

เมื่อถึงจุดหนึ่ง เราเริ่มเย็บเข้าด้วยกัน โดยที่ A1 อาจขึ้นอยู่กับ A5 แต่แล้ว A5 ก็ขึ้นอยู่กับ R2 หลังจากทำเช่นนี้ได้สักพัก เราก็ได้รายการหลายประเภท

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

มีรายการที่ถูกบล็อกโดยรายการอื่นอย่างน้อยหนึ่งรายการ พวกเขามีแนวโน้มที่จะค่อนข้างใหญ่

จากนั้นก็มีไอเทมที่ปิดกั้นตัวเองตั้งแต่หนึ่งรายการขึ้นไป

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

ด้วยการวาดสิ่งนี้ออกเป็นพวงของโซ่ (คิดว่าเป็นวงกลมที่มีลูกศรชี้ไปที่วงกลมอื่น ๆ ) โดยได้รับความอนุเคราะห์จากตัวแสดง “จุด” / graphviz ในตัวของ Wiki เราสามารถดูที่ปลายของมันเพื่อดูว่าเป็นไปได้ กรี๊ดดดดด *ตอนนี้* นอกจากนี้เรายังสามารถดูรายการที่จะมีผลกระทบมากที่สุดในแง่ของการปลดบล็อกงานในอนาคต

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

ฉันจะสังเกตว่ากราฟได้รับการจัดเรียงเพื่อแสดงสิ่งต่าง ๆ ที่มีสีต่างกันและรูปแบบการแสดงผลขึ้นอยู่กับว่าพวกเขาถูกบล็อกหรือไม่และเสร็จสิ้นหรือไม่

ในบางครั้ง เราจะผ่านและตัดกราฟกลับมาเพื่อลบโหนดที่เสร็จแล้วและใช้พื้นที่เพียง การดูสิ่งต่าง ๆ ถูกโจมตีแล้วหายไปจากรายการและกราฟรู้สึกดีมาก

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

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

คุณจะป้องกันไม่ให้มีงาน/ตั๋ว/อะไรก็ตามที่จะไม่มีวันหายไปได้อย่างไร คุณจะไม่สร้างมันขึ้นมาจนกว่าคุณจะแน่ใจว่ามันต้องมีอยู่จริง

ข้อแม้: หากคุณมีหลายสิ่งหลายอย่างเกิดขึ้นจนคุณเสี่ยงต่อการ “สูญเสีย” บางอย่างเนื่องจากเป็นเพียงรายการบรรทัดบนหน้า wiki ที่ใดที่หนึ่ง คุณอาจไม่ต้องการลองทำสิ่งนี้กับโปรเจ็กต์ของคุณ (คุณอาจจะอยากหนีจากโปรเจ็กต์นั้นด้วย เพราะมันมีอะไรเกิดขึ้นมากมายเหลือเกิน)

Debian/Raspbian rngd ด้วย -S0 จะกัดคุณหลังจากผ่านไปหนึ่งสัปดาห์

ฉันใช้ Raspberry Pis เพื่อจุดประสงค์ในการรวบรวมข้อมูล และสังเกตเห็นว่าบางคนกำลังทำบางสิ่งที่ดูเหมือนจะไม่เหมาะสม มีกระบวนการที่เรียกว่า “rngd” ซึ่งชอบที่จะตื่นขึ้นทุก ๆ ครั้งและประกาศสิ่งต่าง ๆ เกี่ยวกับสิ่งที่เกิดขึ้น โดยปกติแล้วจะใช้เวลาประมาณทุกชั่วโมง และมีแนวโน้มที่จะดันหลายสิบบรรทัดไปที่ syslog ซึ่งฉันไม่สนใจเรื่องใดเลย

ดังนั้น หนึ่งในนั้น เพื่อที่จะไม่สร้างมลพิษต่อบันทึก และไม่เบิร์นการ์ด SD ด้วยการเขียนจำนวนมากที่เพิ่มคุณค่าให้กับชีวิตของฉันเป็นศูนย์ ฉันจึงตัดสินใจปิดด้วย “-S0” ตามคู่มือ:

ควบคุมช่วงเวลาที่ส่งออกสถิติไปยัง syslog โดยปกติทุกชั่วโมง สูงสุดคือหนึ่งสัปดาห์ (604800 วินาที) ตั้งค่าเป็น 0 เพื่อปิดใช้งานการบันทึกสถิติอัตโนมัติ เช่น เพื่อหลีกเลี่ยงการหมุนของฮาร์ดดิสก์ในระบบฝังตัว (การส่งสัญญาณ SIGUSR1 จะยังคงทำให้สถิติถูกบันทึก)

ฉันทำอย่างนั้นในเดือนกุมภาพันธ์ และมันหยุดการบันทึกจริงๆ ฉันมีความสุขมาก ฉันปล่อยให้คนอื่นอยู่คนเดียวในขณะนี้

เมื่อไม่กี่ชั่วโมงที่แล้ว ฉันล้อเล่นเกี่ยวกับสิ่งเหล่านี้ และสังเกตว่า rngd ของอันนั้นใช้ CPU ประมาณ 15% ในขณะที่อีกอันไม่ได้ทำอะไรเลย เรื่องแบบนี้ทำให้ฉันรำคาญใจ ฉันก็เลยยึดติดกับมันด้วยสติสัมปชัญญะ และนี่คือรางวัลของฉัน:

[pid 422] 23:43:16.512699 clock_nanosleep_time64(CLOCK_REALTIME, 0, {tv_sec=0, tv_nsec=0}, 0x7ee28c68) = 0 <0.000103>
[pid 422] 23:43:16.512969 clock_nanosleep_time64(CLOCK_REALTIME, 0, {tv_sec=0, tv_nsec=0}, 0x7ee28c68) = 0 <0.000101>
[ ... ซ้ำแล้วซ้ำเล่าเช่นนี้ ... ]

ในระยะสั้น WTF จบแล้ว ทำไมคุณถึงหมุนวนซ้ำแล้วซ้ำเล่า เรียกการนอนหลับ…โดยไม่ชักช้า? ลองดูสิ: tv_sec คือจำนวนวินาทีที่จะเข้าสู่โหมดสลีป tv_nsec คือจำนวนนาโนวินาทีในการนอนหลับ การเรียกมันด้วยโครงสร้างที่ตั้งค่าทั้งคู่เป็น 0 จะทำให้มันกลับมาในทันที โดยไม่แปลกใจเลย

ทำไมคุณจะทำเช่นนั้น? แล้วจะทำต่อไปทำไม? และทำไมคุณถึงทำอย่างนั้นตลอดไป ในเมื่อคุณมี CPU ของระบบถึง 15%?

ฉันไปแนบกับ gdb เพื่อค้นหาว่าการโทรเข้าสู่โหมดสลีปมาจากไหน แต่มีปัญหาเกิดขึ้น ดูเหมือนว่าไม่มีใครในดินแดน Raspbian ใส่ใจเกี่ยวกับการมีสัญลักษณ์การดีบักสำหรับแพ็คเกจของพวกเขา โดยปกติในโลกของ Debian คุณสามารถติดสิ่งพิเศษในไฟล์ต้นทาง apt ของคุณ ทำการอัปเดต แล้วคุณจะมีแพ็คเกจ -dbgsym โลกใบใหม่พร้อมให้คุณใช้งาน หากมีอยู่ใน Raspbian ฉันหาไม่พบ

ดังนั้นฉันจึงไม่มีสัญลักษณ์อื่นนอกเหนือจาก glibc เอง ฉันทิ้งแกนกลางไปโดยรู้ว่าฉันอาจจะจบลงด้วยการฆ่ากระบวนการในบางจุดและต้องการกลับมาที่มันในภายหลัง ฉันดีใจที่ได้ทำเพราะมันช่วยไขปริศนาได้ในภายหลัง

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

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

[กระทู้ปัจจุบันคือ 1 (กระทู้ 0x76f49200 (LWP 422))]
(gdb) bt
#0 0x76e22f8c ใน __GI___clock_nanosleep_time64 ([email protected]=0, [email protected]=0, req=0x7ee28c58, [email protected]=0x7ee28c50, rem=0x7ee28c68, [email protected]=0x7ee.unix/) sysv/linux/clock_nanosleep.c:52
# 1 0x76e23080 ใน __GI___clock_nanosleep ([email protected]=0, [email protected]=0, [email protected]=0x7ee28c9c, [email protected]=0x7ee28c9c) ที่ ../sysdeps/unix/sysv/linux/ clock_nanosleep.c:92
#2 0x76e29830 ใน __GI___nanosleep ([email protected]=0x7ee28c9c, [email protected]=0x7ee28c9c) ที่ nanosleep.c:27
#3 0x76e2971c ใน __sleep (seconds=0) ที่ ../sysdeps/posix/sleep.c:55
#4 0x00011470 ใน ?? ()

สังเกตว่าเธรดที่เป็นปัญหาคือสิ่งที่ gdb เรียก #1 ซึ่งก็คือ LWP 422 หรือ PID 422 หากคุณดู strace ของฉันจากเมื่อก่อน การเรียกเข้าสู่โหมดสลีปทั้งหมดนั้นมาจาก pid 422 สิ่งนี้บอกฉันว่าไม่ใช่ อีกหัวข้อหนึ่งที่ก่อให้เกิดความไม่ดี แต่เป็นเธรดหลัก

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

  
        sleepinterval = อาร์กิวเมนต์ -> stats_interval ?  
            อาร์กิวเมนต์->stats_interval : STATS_INTERVAL_MAX;  
        เวลานอน = ช่วงเวลานอน;  
        ในขณะที่ (!gotsigterm) {  
                เวลานอน = นอน (เวลานอน);  
                ถ้า ((arguments->stats_interval && sleeptime == 0) ||  
                    gotsigusr1 || ได้ซิกเตอร์) {  
                        dump_rng_stats();  
                        เวลานอน = ช่วงเวลานอน;  
                        gotsigusr1 = 0;  
                }  
        }  

เมื่อดูที่โค้ด sleepinterval จะได้รับการตั้งค่าจากนิพจน์ ternary ที่อาจรับค่า stats_interval หากไม่ใช่ศูนย์ หรือตั้งค่าเป็น STATS_INTERVAL_MAX ซึ่งจะกลายเป็น 604800 วินาที นั่นเป็นวินาทีที่มีค่าต่อสัปดาห์ และ 604800 ก็ปรากฏขึ้นทุกครั้งที่ฉันรันอันที่ฉันสร้างจากแหล่งที่มา ไม่แปลกใจเลย

เนื่องจาก strace และ gdb ได้พิสูจน์แล้วว่ารหัสการวนซ้ำมาจาก main และนี่คือจุดสิ้นสุดของ main สิ่งนี้จะเข้าสู่โหมดสลีปเป็นเวลา 0 วินาทีได้อย่างไร ท้ายที่สุด มันรีเซ็ตมันภายใน “ถ้า” ที่ดูแย่ในลูป และตั้งค่าเป็น sleepinterval และ sleepinterval คือ 604800 ดีมาก ใช่ไหม

ไม่จริง

ประมาณนี้เองที่ผมสังเกตว่าไม่ใช่การเรียกให้นอนเปล่าๆ อันที่จริงมัน ใช้ค่าที่ส่งคืนมา จากโหมดสลีป ฉันไม่เห็นสิ่งนี้มากนักและพลาดไปในตอนแรก

  
	เวลานอน = นอน (เวลานอน);  

สิ่งทั้งปวงนี้. ดังนั้น… สำหรับเราที่จะนอนหลับ (0) เวลานอนจะต้องเป็น 0 แต่เรารีเซ็ตมันให้สูงขึ้นเสมอใช่ไหม ไม่เราไม่

  
ถ้า ((arguments->stats_interval && sleeptime == 0) ||  
	  gotsigusr1 || ได้ซิกเตอร์) {  

คลี่กิ่งออกเป็นแบบนี้

อาร์กิวเมนต์ -> stats_interval เป็นจริงหรือไม่ มันถูกตั้งค่าเป็น 0 ดังนั้นจึงไม่ใช่ เราไม่ได้ดูส่วนที่เหลือของอันแรกนั้นด้วย ไม่ได้ตั้งค่า gotsigusr1 และ gotsigterm เนื่องจากเราไม่ได้รับสัญญาณ ความเป็นไปได้ OR เหล่านั้นไม่เป็นความจริง ดังนั้นเราจึงไม่แยกสาขา เราไม่ dump_rng_stats และเราไม่รีเซ็ตเวลาพักเครื่องเป็น sleepinterval

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

แต่จะเกิดอะไรขึ้นถ้าคุณถึงเวลาที่คุณขอให้รอ? แล้วมันคืนค่าศูนย์

สิ่งที่เราต้องทำคือเข้าสู่โหมดสลีปโดยไม่ได้รับสัญญาณใดสัญญาณหนึ่ง และมันจะคืนค่าเป็น 0 และไม่มีการรีเซ็ต ดังนั้นมันจะถูกเรียกด้วย 0 ซ้ำแล้วซ้ำเล่า และอีกครั้งและอีกครั้ง …………….. ในวงที่แน่นมาก เบิร์น CPU ไปตลอดทาง

เคล็ดลับและเหตุผลที่มันยากที่จะทำซ้ำก็คือคุณต้องรอหนึ่งสัปดาห์เต็มก่อนที่จะหมดเวลาครั้งแรกนั้น! ใช่. ลองนึกภาพความอดทนแบบนั้น

ฉันไม่มีความอดทนแบบนั้น ดังนั้นเพื่อทดสอบสมมติฐานของฉัน ฉันลด STATS_INTERVAL_MAX ลงเหลือ 30 วินาที และเริ่มสร้างบิลด์ใหม่ใน strace มันนั่งอยู่ที่นั่นเป็นเวลา 30 วินาที จากนั้นจึงเริ่มเคี้ยวซีพียูในทันทีในช่วงสลีปที่แน่นมาก

ดังนั้น ใช่ ถ้าคุณเรียกใช้ rngd ของ Debian ด้วย -S0 มันจะใช้ได้อย่างสมบูรณ์เป็นเวลาหนึ่งสัปดาห์หรือประมาณนั้น จากนั้นมันจะวนรอบแน่นที่จะผูกซีพียูตัวใดตัวหนึ่งของคุณตั้งแต่นั้นมาจนถึงกระบวนการ หยุดด้วยเหตุผลบางอย่าง น่ารัก.

หากคุณได้ลองใช้วิธีนี้บน Raspberry Pi ของคุณด้วยเหตุผลในการรักษาการ์ดที่คล้ายกัน คุณอาจต้องการไปดูว่าคุณมี rngd ที่กินแกนหรือไม่ ถ้าเวลาทำงานของคุณนานกว่าหนึ่งสัปดาห์ ฉันพนันได้เลยว่า

เชส

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

  
         gettimeofday(&เริ่ม, NULL);  
         ในขณะที่ (!gotsigterm && timeout_usec > 0 &&  
                      แบบสำรวจความคิดเห็น (&pfd, 1, timeout_usec) < 0 &&  
                      errno != EINTR) {  
                gettimeofday(&ตอนนี้ NULL);  
                timeout_usec -= elapsed_time(&เริ่ม & ตอนนี้);  
                เริ่ม = ตอนนี้;  
        }  

ทันทีที่ฉันเห็น “gettimeofday” และคิดว่า “ฉันเลือกสัปดาห์ที่ไม่ถูกต้องเพื่อหยุดบางสิ่งบางอย่าง” พวกเขากำลังคำนวณเวลาที่ผ่านไป… ด้วยนาฬิกาแขวน นั่นคือสิ่งที่ gettimeofday() มอบให้คุณ หากคุณต้องการนาฬิกาแบบโมโนโทนิก คุณต้องใช้ clock_gettime() และระบุนาฬิกาที่ถูกต้อง นี่เป็นเพียงการถามถึงปัญหาหากนาฬิกาของระบบเปลี่ยนไปในขณะที่กำลังทำงานอยู่

พูดแบบนี้: เป็นสิ่งที่ดีที่พวกเขาตรวจสอบอย่างชัดเจนว่า timeout_usec เป็นจำนวนบวก เนื่องจากถ้าคุณผ่านโพลหมดเวลาติดลบ นั่นหมายถึง “อนันต์” เรียบร้อยใช่มั้ย?

ฉันคิดว่าฉันจะหยุดอยู่ที่นั่นก่อนที่จะพบอย่างอื่น

คำติชมมากมายเกี่ยวกับ /bin/true และไฟล์ที่ว่างเปล่าสนุกสนานมากขึ้น

โอเค ว้าว โพสต์ ของฉันเกี่ยวกับไฟล์เปล่าได้สร้างคำติชมมากมาย ส่วนใหญ่สำหรับบรรทัดการทิ้งที่ด้านล่างเกี่ยวกับไฟล์เปล่าที่เป็นเวอร์ชันที่เล็กที่สุดของ /bin/true

ก่อนอื่น Rob Pike เขียนด้วยลิงก์ไปยัง ทวีตของ ไฟล์. ขอบคุณร็อบ! นั่นคือความคิดเห็นประเภทหนึ่งที่ทำให้ฉันคิดมาก: เมื่อคนที่รู้แน่นอนปรากฏขึ้นและให้คำตอบที่เชื่อถือได้

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

Garrett เขียนพร้อมลิงก์ไปยังเรื่องราวดีๆ เกี่ยวกับไฟล์ Zero-byte อีกไฟล์หนึ่งจากโลกของ CP/M ที่เรียกว่า The Infinitely Profitable Program (มองหาส่วนที่เกี่ยวกับ “go.com” ถ้าคุณใจร้อน)

ฉันยังได้ยินจากผู้เขียน งานชิ้นนี้เกี่ยวกับ POSIX true(1) ซึ่งชี้ให้เห็นข้อมูลอ้างอิงบางส่วน รวมถึงการอ้างอิงโดย John Chambers ที่เรียกว่า The /bin/true Command and Copyright ดังนั้น ดูเหมือนว่าผู้คนจะทุ่มเททำงานจริง ๆ เพื่อค้นหาว่ามันเกิดขึ้นได้อย่างไร

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

นอกจากไฟล์ Zero-byte แล้ว ปัญหาอีกอย่างที่เราเห็นก็คือเครื่องจะ *ผสมเนื้อหาไฟล์* เมื่อรีบูตระหว่างการดำเนินการเขียน ซึ่งมักจะปรากฏเป็นอึ RPM ที่ถูกเขียนไปยังไฟล์ที่ไม่มีธุรกิจที่มีข้อมูล RPM

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

เมื่อถึงจุดหนึ่ง มีคนตัดสินใจให้ “พร็อกซี่” จดจำสิ่งที่ได้รับการร้องขออย่างชัดเจนในกล่อง ดังนั้นพวกเขาจึงทิ้งรายการของรายการที่ร้องขอ หนึ่งรายการต่อบรรทัด ใน *ไฟล์ข้อความธรรมดา* วิธีนี้ใช้ได้ผล แต่แล้วมันก็ข้ามเส้นทางกับสัตว์ประหลาดที่เสียหายของระบบไฟล์ ไฟล์ของพวกเขาได้รวบรวมไบนารี crap ทุกประเภทซึ่งไม่มีการเชื่อมต่อกับสิ่งใดใน config store

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

สำหรับการถูครั้งสุดท้าย: ทุกเธรดเหล่านี้ทำให้กระบวนการใหญ่ขึ้นมาก นี่คือ VSZ ที่คุณเห็นในเครื่องมืออย่างเช่น ps ไม่ใช่หน่วยความจำกายภาพ แต่เป็นขนาด *เสมือน* โดยรวมของมัน อาจมากกว่าการจัดสรรทางกายภาพ (RSS) จริงของกระบวนการหลายเท่า

ในกรณีนี้ ด้วยเหตุผลบางอย่าง บุคคลที่มีเจตนาดีบางคนได้พยายามกำหนดขีดจำกัดว่าโปรแกรมจะได้รับมากเพียงใด พวกเขาใช้ ulimit (aka setrlimit) เพื่อทำสิ่งนี้ ปัญหาคือ RSS คือ *ไม่ใช่* หนึ่งในสิ่งที่คุณสามารถควบคุมได้ด้วย u/rlimits มีการตั้งค่าที่ดูเหมือนว่าจะใช้งานได้กับสิ่งต่าง ๆ แต่จำกัด *VSZ* เท่านั้น

ดังนั้น เมื่อทุกอย่างรวมกันในที่สุด คุณมี “พร็อกซี่” ที่ปรากฏขึ้น พยายามเริ่มเธรดจำนวนมากที่ไม่เคยหายไป จะบอลลูน VSZ ของมัน จากนั้นขีดจำกัดก็เริ่มขึ้น และเริ่มล้มเหลว การจัดสรรหน่วยความจำ นั่นคือ C ++ จะส่งข้อยกเว้น “การจัดสรรที่ไม่ดี” สำหรับสิ่งต่าง ๆ เช่น “ใหม่” และโปรแกรมจะตายเพราะไม่มีใครคาดหวังว่า * นั่น * จะล้มเหลว

ฉันไม่เคยรู้เลยว่ามีการผสมเกสรระหว่างไฟล์ในเครื่องของบริษัทนั้นมากน้อยเพียงใด เท่าที่เราทราบ อาจส่งผลให้เนื้อหาของ cat picture #1 ถูกเขียนลงในไฟล์ของ cat picture #2 หรือในทางกลับกัน นั่นจะเป็นความล้มเหลวด้านความเป็นส่วนตัวที่ยิ่งใหญ่ใช่ไหม

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

การแก้ไขหูดเหล่านี้ทั้งหมดเกี่ยวข้องกับการทำให้เคอร์เนลไม่ผสมบัฟเฟอร์ และเอา “ulimit -v” ที่มีเจตนาดีแต่ไร้ประโยชน์ในท้ายที่สุดซึ่งมีคนวางไว้ในสคริปต์เริ่มต้น สำหรับไฟล์ข้อความธรรมดา ฉันพยายามทำให้พวกเขาเป็นบางอย่างที่หนักแน่น (และไม่ใช่ “เคร่งเครียด”) ที่พิมพ์ด้วยการจัดกรอบหรือวิธีอื่นในการตรวจจับความเสียหาย แต่ผู้พัฒนาไม่ดำเนินการ ถอนหายใจ

AirPlay ในสภาพแวดล้อมที่มีความหนาแน่นสูงนั้นไม่ค่อยดี

AirPlay ของ Apple เป็นสิ่งที่มีประโยชน์เมื่อมีข้อ จำกัด กับบุคคลและอุปกรณ์ของตนเองและอุปกรณ์ของเพื่อนที่มาเยี่ยม (ซึ่งได้รับอนุญาตให้เข้าถึงเครือข่ายของโฮสต์) อนุญาตให้ส่งเพลงและ/หรือวิดีโอไปยังลำโพงหรือทีวีและแสดงผลเพื่อประโยชน์ของทุกคน

น่าเสียดายที่อย่างน้อย Apple TV ทำสิ่งที่โง่เขลานี้ (โดยค่าเริ่มต้นฉันค่อนข้างแน่ใจ) โฆษณาตัวเอง กับทุกคนในบริเวณใกล้เคียง ซึ่งหมายความว่าหากคุณอยู่ในสภาพแวดล้อมที่ค่อนข้างหนาแน่น เช่น อาคารอพาร์ตเมนต์ อาคารคอนโด หรือมีบ้านหลังใดหลังหนึ่งที่มีผนังบางเป็นกระดาษและไม่มีลานด้านข้าง คุณอาจจะมองเห็นอุปกรณ์ของเพื่อนบ้าน

ตอนนี้ แม้จะเป็นเรื่อง “สนุก” ที่จะเลือกอุปกรณ์ของตนเป็นครั้งคราวและทำให้มันทำสิ่งที่เป็น HDMI-CEC ในการเปิดทีวีเป็นหน้าจอ “ป้อนรหัสผ่าน” ในตอนกลางคืน แต่ก็น่าสะอิดสะเอียนที่ต้องข้ามไป ในรายการอุปกรณ์ เมื่อคุณใช้ Mac จะมีแถบดรอปดาวน์นี้ และคุณต้องแน่ใจว่าได้เลือกอันที่ถูกต้อง ด่วน มีอุปกรณ์ “ห้องนั่งเล่น” สี่เครื่อง ที่หนึ่งเป็นของคุณ?

แต่เดี๋ยวก่อน ยังมีอีก นี่เป็นส่วนที่ฉันต้องการรวบรวมผู้อ่านที่เก่งกว่าของฉันบางคนให้ไปลอง ดูเหมือนว่าอุปกรณ์ของเราพยายามเชื่อมต่อกับที่อยู่ IP ของอุปกรณ์ต่างประเทศ ในกรณีที่เราอยู่ในเครือข่ายเดียวกันกับมัน

ฉันต้องการใครสักคนเพื่อซื้อรถเอทีวี กำหนดค่าด้วยที่อยู่ IP ที่ “น่าสนใจ” (แม้ว่าฉันไม่รู้ด้วยซ้ำว่าในปี 2022 จะเป็นอย่างไร พูดตามตรง… มันไม่เหมือนสมัยก่อน) ตั้งค่าในนั้น โหมดที่เสนอตัวเองให้กับทุกคนในบริเวณใกล้เคียง จากนั้นจึงเข้าถึงได้กับคน Apple ทั้งหมด อาจรอ WWDC ถัดไปหรืออะไรทำนองนั้น

อย่างไรก็ตาม ตามทฤษฎีแล้ว อุปกรณ์เหล่านั้นทั้งหมดจะเริ่มพยายามสร้างการเชื่อมต่อ TCP ไปยังที่อยู่ IP นั้นบนพอร์ต 7000… ทางอินเทอร์เน็ต ทำกับอุปกรณ์ใกล้เคียงเพียงพอและมันจะดูเหมือน DDOS หรืออะไรทำนองนั้น บางทีนั่นอาจทำให้คนไม่พอใจมากพอที่จะทำอะไรบางอย่างให้เกิดขึ้น

อีกทางหนึ่ง คุณอาจรู้ว่าคุณมีวิธีการค้นหาที่อยู่ IP (ภายนอก หากอยู่หลัง NAT) ของอุปกรณ์ Apple ที่อยู่ใกล้คุณ สิ่งที่คุณต้องทำคือโน้มน้าวให้พยายามเชื่อมต่อกับโฮสต์จริงที่คุณควบคุม แล้วดูว่าใครมาเสียที ผู้โฆษณา weenie ทั้งหมดที่พยายามรวบรวมข้อมูลการตลาดตามที่อยู่ MAC ที่ทำการสแกน wifi และ BT จะน้ำลายไหลอย่างแน่นอน

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

โง่.

ฉันมีแรงจูงใจซ่อนเร้นในการเขียนสิ่งนี้ บางทีในที่สุด Apple จะทำอะไรบางอย่างเกี่ยวกับสิ่งนี้เพื่อให้เราสามารถเห็นอุปกรณ์ของเราเองในตัวเลือก AirPlay และไม่ต้องหลบสิ่งที่เหมือนกันจำนวนมาก มันเหมือนกับว่า ไปเถอะ ฉันรู้ว่าพวกเขาทั้งหมดต้องอาศัยอยู่ในคฤหาสน์ที่ไม่มีคนอื่นอยู่ใกล้ ๆ แต่พวกเราที่เหลือก็อัดแน่นเหมือนปลาซาร์ดีนและมีอุปกรณ์พิเศษโง่ ๆ มากมายปรากฏขึ้นอย่างต่อเนื่อง มันเลวร้ายลงทุกวันคริสต์มาส

เอาล่ะ แอปเปิล หยุดความบ้าคลั่งของ AirPlay

บางคนไม่สมควรเข้าห้องเครื่อง

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

มันคือ “เรามาทำสิ่งบ้าๆ กันที่ไม่มีข้อมูลใดๆ ระบุได้เลย” ที่นำฉันมาสู่เรื่องราวของวันนี้

ฉันกำลังทานอาหารเย็น โทรศัพท์ของฉันเริ่มดัง และฉันก็ปล่อยให้ไปที่วอยซ์เมล อะไรก็ตามที่รอได้ ต่อมาฉันตรวจสอบสิ่งต่าง ๆ และแน่นอนว่าเป็น “เว็บมาสเตอร์” ใหม่จากกิ๊กที่ฉันเป็นผู้ดูแลระบบ ข้อความของเขาเริ่มต้นในรูปแบบที่โดดเด่นที่สุด: “ทั้ง box1 และ box2 ขัดข้อง” ดำเนินการต่อด้วยคำพูดที่หยาบคายมากขึ้นแล้วเสริมว่าเขาได้รีบูต box2 (ด้วยปุ่มรีเซ็ตนั่นคือ)

box1 เป็นเมลเซิร์ฟเวอร์สำหรับการดำเนินการทั้งหมด box2 เป็นหนึ่งในเว็บเซิร์ฟเวอร์ ทั้งที่จะถูกลงจะเป็นเรื่องใหญ่ ยังไงฉันก็ไม่ซื้อ สิ่งเหล่านี้ไม่ได้ตายไปอย่างนั้นโดยเฉพาะในเวลาเดียวกัน

ฉันเดินกลับไปที่สำนักงานที่บ้านอย่างสงบ พลิกไปที่เซสชัน “งาน” ของฉันบน box1 ซึ่งอยู่ในระบบตลอดเวลา และกด ENTER มันยังมีชีวิตอยู่ ฉันโทรหาเขา และเขาถามว่า “แล้ว box2 ล่ะ” ฉันก็เลยโหลดหน้าเว็บบนกล่องนั้นใน Mozilla (ใช่ นี่มันนานมาแล้ว…) และมันก็ใช้ได้ ฉันแหย่ box3 เพื่อการวัดที่ดี ก็ยังดี

ต่อมา ฉันได้รับอีเมลที่น่าสนใจ

ขออภัยที่รบกวนคุณเกี่ยวกับสิ่งที่เรียกว่าการหยุดทำงาน มีบางอย่างผิดปกติเกิดขึ้นกับเครือข่าย 1 ในขณะที่ฉันได้รับที่อยู่ IP บนเครือข่าย 2 ฉันขอ (ชื่อ) สำหรับ IP คงที่สำหรับเวิร์กสเตชันของฉันบนเครือข่าย 1 เขาให้ xxx16 แก่ฉัน มันเชื่อมต่อกับ box4 และ box5 แต่ไม่ใช่กับ box1 และ box2 ฉันใช้ xxx1 เป็นเกตเวย์ ฉันกลับไปที่ dhcp และทุกอย่างสามารถเข้าถึงได้อีกครั้ง พรุ่งนี้ฉันจะถาม (ชื่อ) เกี่ยวกับเรื่องนี้

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

สิ่งที่เกิดขึ้นคือเขาได้รับที่อยู่ IP ที่ “เป็นพิษ” กาลครั้งหนึ่ง (ชื่อ) ได้ตั้งค่าการสแกนเครือข่ายนี้ซึ่งทำให้บันทึกของฉันเต็มไปด้วยอึ ฉันขอให้ (ชื่อ) เคาะมันออก เพราะฉันดูสิ่งเหล่านั้นจริง ๆ และมักจะปฏิบัติตามสัญญาณที่ให้มา Crapflooding บันทึกของฉันทำให้ยากต่อการค้นหาสิ่งที่บ้าจริงเช่นระบบไคลเอนต์ที่ติดไวรัส (และแย่กว่านั้น)

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

  
# (วันที่สองปีที่แล้ว): กล่องงี่เง่าที่ไม่หยุดสแกนฉัน  
ดรอป * xxx16 * * *  

เมื่อ “เว็บมาสเตอร์” นี้ยึดที่อยู่ IP ไว้ได้ เครื่องทั้งสองเครื่องที่เคยมีมาเมื่อเกิดเหตุการณ์นี้ยังคงทิ้งมันไว้ด้วยกฎ iptables ที่ธรรมดาและงี่เง่า เครื่องใดๆ ที่ “เกิด” ผ่านจุดใดก็ตามที่พวกเขาหยุดการสแกนไม่เคยได้รับกฎเพราะไม่มีอะไรจะตก และนั่นเป็นสาเหตุที่ box3, box4 และ box5 ไม่ได้ทำแบบเดียวกัน

มาดูกัน. คุณสามารถเข้าถึงเซิร์ฟเวอร์จำนวนมากที่ไม่ใช่ของคุณ คุณทำอะไรบางอย่างกับเวิร์กสเตชันของคุณ สิ่งต่อไปที่คุณรู้ คุณไม่สามารถเข้าถึงเซิร์ฟเวอร์บางตัวจากเวิร์กสเตชันนั้นได้ คุณยกเลิกสิ่งที่คุณทำกับเวิร์กสเตชันของคุณหรือไม่? ไม่ คุณพบเครื่องอื่นหรือไม่? ไม่ คุณขอให้คนอื่นลองตีมันด้วยไหม ไม่ คุณพยายามกระโดดเข้าไปในเครื่องที่ IS ตอบสนองแล้วพยายามกระตุ้นเครื่องที่ “ตาย” เครื่องใดเครื่องหนึ่งจากเครื่องนั้นหรือไม่? ไม่ คุณสังเกตเห็นความแตกต่างระหว่างโฮสต์ที่ล่มจริงๆ กับโฮสต์ที่เพิ่งทิ้งแพ็กเก็ตของคุณ เช่น โฮสต์ที่ไม่สามารถเข้าถึงได้จาก ICMP จากเราเตอร์ กับ… รู้ไหม ไม่มีอะไร ไม่.

คุณทำงานอะไร? คุณเข้าไปในห้องเซิร์ฟเวอร์และเริ่มกดปุ่มรีเซ็ตที่แผงด้านหน้าโดยคิดว่ามันจะมีประโยชน์

ต้องใช้บุคคลบางประเภทในการไปทำสิ่งต่าง ๆ เช่นนั้น

เวลาที่ผ่านไประหว่างการสัมภาษณ์ “แล็ปท็อป” การเข้ารหัส

คุณเคยสงสัยหรือไม่ว่าเวลาจะไปที่ไหนระหว่างการสัมภาษณ์เรื่อง “แล็ปท็อป” ที่เขียนโค้ด? นี่เป็นหนึ่งในสิ่งที่คุณนำคอมพิวเตอร์แล็ปท็อปเครื่องเล็กๆ มาเอง (หรือจัดหามาให้) และคุณคาดว่าจะแก้ปัญหาได้ทันที พวกเขาให้เวลาคุณประมาณ 60-90 นาทีในการทำเช่นนี้ และพวกเขาต้องการเห็นมันทำงาน มีการทดสอบ และสิ่งดีๆ ทั้งหมดนั้น

ผู้สัมภาษณ์ยื่นกระดาษให้คุณและอาจพูดคุยหรือไม่ก็ได้ จากนั้นพวกเขาก็ปล่อยคุณให้เป็นอิสระและหายไปชั่วขณะหนึ่ง มีเพียงคุณและเครื่องจักรเล็กๆ ของคุณเท่านั้น และอาจเป็นเพลงบางเพลงหากคุณคิดล่วงหน้า

เวลาไปไหน? ครั้งสุดท้ายที่ฉันผ่านมันไป มันเกิดขึ้นในหัวของฉัน:

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

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

ใช่ ฉันต้องหาวิธีบางอย่างในการแก้ปัญหาจริงที่พวกเขาให้มา จากนั้นฉันต้องเขียนมัน แต่ฉันยังต้องการทุกสิ่งที่จำเป็นในการสูดดมไฟล์นี้จริง ๆ และรับข้อมูลเพื่อเรียกใช้ผ่าน “เครื่องมือ” นั้นที่ฉันลงเอยด้วยการเขียน จอย.

ดังนั้น ฉันเดาว่าฉันสามารถเขียนสิ่งที่แย่ๆ เพื่อใช้ fgets เพื่ออ่านสิ่งนี้และให้ฉันเป็นพวงของบรรทัด จากนั้นตัดมันด้วยวิธีที่น่ากลัวจริงๆ บดผ่าน strtoul หรือบางสิ่งบางอย่างเพื่อสร้างคุณค่าจากพวกเขา และจากนั้นก็อาจจะ โทรเข้า “เครื่องยนต์” ของฉันด้วยสองอาร์กิวเมนต์ จอย.

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

มาเริ่มกันเลยดีกว่า อืม ฉันไม่มีของในห้องสมุดส่วนตัวของฉันเลย ดังนั้นฉันคิดว่าฉันจะต้องเขียนโค้ดมันแบบเดิมๆ นอกจากนี้ พวกเขากำลังจะสร้างสิ่งนี้บนอะไร? ฉันไม่รู้ว่ามันอยู่ที่ไหนในแง่ของคอมไพเลอร์ สมมติว่า C++98 เพื่อความปลอดภัย

โอเค ต้องไปรับไฟล์แล้วอ่านไฟล์ ดังนั้น…

  
int main (int argc, ถ่าน** argv) {  
  ถ้า (argc != 2) {  
    fprintf(stderr, "การใช้งาน: %s <file>\n", argv[0]);  
    ทางออก(1);  
  }  

… และแน่นอนว่านี่หมายความว่าเราต้องการ stdio.h สำหรับ fprintf และ stdlib.h เพื่อออกจากที่นั่น ดังนั้นให้เพิ่ม #includes เหล่านั้นที่ด้านบน

ทำต่อไป. เปิดของแล้วตะโกนว่าไม่มี ปกติฉันจะมีสิ่ง LOG ของตัวเอง แต่ไม่มีที่นี่ ล้มเหลวที่ฉันมักจะ fprintf บางสิ่งบางอย่างเพื่อ stderr ให้ข้อความและสตริงรูปแบบแล้วติดขัด strerror(errno) เข้าไป แต่เวลาสั้น perror นั้นมันห่วย แต่เร็วกว่า งั้นก็ช่างมันเถอะ ใช้มันซะ

  
  ไฟล์* f = fopen(argv[1], "r");  
   
  ถ้า (!f) {  
    perror("เปิด");  
    ทางออก(1);  
  }  

และตอนนี้เราต้องการ errno.h ด้วย ไป #รวมว่า.

ได้เวลาขึ้นบรรทัดแรกแล้ว ลองอ่านมันและเพิกเฉยต่อความจริงที่ว่ามันสามารถ EOF ในการอ่านนี้และเราอาจไม่ได้อะไรเลยเพราะอีกครั้งกดดันเวลาที่นี่ กร๊าก มันก็จะฟินๆ

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

  
  ถ่านบัฟ[1024];  
   
  fgets(buf, sizeof(buf), f);  
  buf[strlen(buf) - 1] = '\0';  

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

  
  int input_lines = atoi(buf);  

[ ตรวจสอบเวลา: ฉันใช้เวลา 17 นาทีแล้วในการ *เขียนโพสต์นี้* เพื่อให้ได้มาไกลขนาดนี้ ฉันจะยึดตามบันทึกของฉันและรหัสจากวันนั้นเมื่อหลายปีก่อน ติ๊ก ติ๊ก ติ๊ก. ]

พูดในสิ่งที่ฉันได้รับเพื่อจุดประสงค์ในการดีบักดีกว่า ใช้ stderr เพื่อไม่ให้เอาต์พุตเสียหาย

  
  fprintf(stderr, "XXX บรรทัดอินพุต: %d\n", input_lines);  

ตอนนี้ฉันเดาว่ามันถึงเวลาที่จะเริ่มวนรอบที่อ่านเรื่องไร้สาระนี้แล้วแยกมันและเก็บไว้ที่ไหนสักแห่ง ดังนั้น อืม…

  
  แผนที่<int, int> input_jobs; // คีย์: เวลาเริ่มต้น, val: เวลาทำงาน  
   
  ในขณะที่ (fgets(buf, sizeof(buf), f)) {  
    ถ้า (strlen(buf) < 1) {  
      ดำเนินต่อ;  
    }  
   
    buf[strlen(buf) - 1] = '\0';  
   
    ถ่าน* sp = strchr(buf, ' ');  
   
    ถ้า (!sp) {  
      fprintf(stderr, "บรรทัดไม่ดี (ไม่มีช่องว่าง): %s\n", buf);  
      ทางออก(1);  
    }  
   
    *sp = '\0';  
    ถ่าน* len_str = sp + 1;  
   
    int start_at = atoi(buf);  
    int run_for = atoi(len_str);  
   
    input_jobs[start_at] = run_for;  
  }  
   
  fclose(f);  

เลวร้ายมากที่นี่ ต้องเพิ่มเนื้อหาด้านบน: #include <map> และใช้ std::map ฉันหวังว่าพวกเขาจะไม่ให้เวลาเริ่มต้นซ้ำกัน มิฉะนั้นฉันจะบีบเวลาก่อนหน้า (ฉันคิดว่าพวกเขาพูดอะไรบางอย่างเช่น “สิ่งนี้จะไม่เกิดขึ้น” แต่ทำไมคุณถึงเชื่ออย่างนั้นล่ะ)

อีกครั้งด้วยการสุ่มสี่สุ่มห้าว่าเรามีข้อมูลที่ใช้งานได้สำหรับ atoi… และสิ่งที่ไม่ดีที่ไม่มีช่องว่างก็ไม่ควรเกิดขึ้น แต่อีกครั้ง ฉันไม่ไว้ใจพวกเขามากขนาดนั้น ฉันยินดีที่จะจัดการกับความโง่เขลาบางอย่าง แต่สิ่งนี้จะทำสิ่งเลวร้ายเมื่อได้รับ NULL กลับมาจาก strchr แล้วพยายามละเลยมันในภายหลัง ดังนั้นแทนที่จะเขียนหลุมพอยน์เตอร์ C ยุค 80 ที่น่ากลัวอีกอัน ให้ตายเถอะ

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

กลับขึ้นเหนือวง…

  
  int จริง = 0;  

… และในวง …

  
  ++จริง;  

… และหลังจากวนซ้ำ:

  
  ถ้า (จริง != input_lines) {  
    fprintf(stderr, "คาดว่า %d มี %d\n", input_lines, จริง);  
    ทางออก(1);  
  }  

ได้สิ ตอนนี้ฉันจะได้รู้ว่านั่นมันไร้สาระ อย่างน้อยก็ด้วยเหตุผลบางอย่าง

[ ตรวจสอบเวลา: ผ่านไป 27 นาทีในการเขียนโพสต์นี้ ]

ตอนนี้ฉันเดาว่าฉันจะต้องวนซ้ำข้อมูลที่ฉันอ่านและทำสิ่งที่มีประโยชน์กับมัน โอ้ ใช่แล้ว โดยการอ่านในตอนแรกและไม่ใช่ “การสตรีม” นั้น ฉันได้ผูกมัดตัวเองกับสถานการณ์หน่วยความจำ O(n) อย่างดีที่สุด และมันอาจจะจบลงที่เลวร้ายยิ่งกว่านั้น ดังนั้น “อ่านในแผนที่” ชั่วคราวนี้อาจจะต้องไปในบางจุดและฉันจะเรียก “เพิ่มสิ่งที่ฉันเพิ่งแยกวิเคราะห์” จากภายใน for ลูป จอย.

อย่างไรก็ตาม. ย้ำ. แต่เอาล่ะ C ++ 98 การทำซ้ำแบบเก่าไม่มีสิ่ง “สำหรับ const auto”

  
  แผนที่<int, int>::const_iterator ii;  
   
  int job_count = 0;  
  สำหรับ (ii = input_jobs.begin(); ii != input_jobs.end(); ++ii) {  
    const int& start_time = ii->ก่อน;  
    const int& run_time = ii->วินาที;  
    add_job(เริ่ม, เวลา, run_time, job_count++);  
  }  

และแน่นอนว่าตอนนี้เราต้องการบางอย่างที่อยู่เหนือ main ที่จะทำ add_job นี้ ดังนั้นเรามาเขียน stub เพื่อเริ่มต้นกัน

  
โมฆะคงที่ add_job (int start_time_raw, int run_time, int job_number) {  
  fprintf(stderr, "XXX add_job %d | %d | %d\n\n",  
          start_time_raw, run_time, job_number);  
  // XXX เขียนถึงฉัน  
}  


ตกลง. ฉันจะหยุดอยู่ที่นั่นตอนนี้ ตระหนักว่าสิ่งที่คุณเห็นคือ *รูปแบบสุดท้าย* ของรหัสนั้น มีหลายอย่างเกิดขึ้นระหว่างนั้น ตัวอย่างเช่น ดูว่ามันเรียกว่า “start_time_raw” ในฟังก์ชัน add_job อย่างไร นั่นเป็นเพราะค่าเวลาเริ่มต้นจากไฟล์กลายเป็น “HHMM” นั่นคือเวลา 12.00 น. อยู่ในไฟล์เป็น “1200” 1345 น. อยู่ในไฟล์เป็น “1345”

ตอนแรกฉันแยกวิเคราะห์ว่ามันเป็นสิ่งที่อยู่ในช่วง 0-1439 เพราะด้วยระบบที่ให้คุณกำหนดเวลาสิ่งของในเวลาที่กำหนดในระหว่างวันด้วยความแม่นยำหนึ่งนาทีโดย ส่วนตัว ฉันจะใช้ “จำนวน นาทีตั้งแต่เที่ยงคืน” เป็นฐาน พวกเขาไม่ได้ พวกเขาใช้เวลาที่มนุษย์อ่านได้น้อยกว่าโคลอนปกติที่เราวางไว้ตรงกลางเพื่อให้อ่านง่าย!

ฉันรู้ได้อย่างไร 1439? ฉันเคยเขียนตัวจัดตารางเวลามาก่อน และวันพลเรือนปกติที่ไม่มีการเปลี่ยน DST ใด ๆ อยู่ที่ 1440 นาที: 24 * 60 ฉันรู้จากการเขียนตัวจัดกำหนดการเดียวกันเหล่านั้นด้วยว่าสัปดาห์ของวันที่ไม่ใช่ DST เดียวกันนั้นคือ ยาว 10080 นาที เพราะนั่นเป็นเพียง 24 * 60 * 7 และคุณเจอตัวเลขนั้นเยอะมาก มันอบเข้ามาในหัวของคุณ หรืออย่างน้อย มันก็เข้ามาในหัว *ของฉัน* ฉันจะพูดอะไรได้ ล่ะ ฉันเป็นคนประหลาดแบบนั้น

ดังนั้นจึงเป็น start_time_raw เพราะยังไม่ได้แยกออกเป็นค่าที่เหมาะสมภายในอาร์เรย์ โค้ดบิตแรกในท้ายที่สุด add_job() จบลงด้วยการทำสิ่งที่แย่มากเพื่อเปลี่ยน HHMM เป็น “นาทีตั้งแต่เที่ยงคืน” ในช่วง 0-1439 เช่นนี้

  
  int start_hour = start_time_raw / 100;  
  int start_minute = start_time_raw % 100;  
   
  int start_time = start_hour * 60 + start_minute;  

แย่มากใช่มั้ย? ไม่มีการตรวจสุขภาพจิต มันแค่โมดิฟาย หาร ทวีคูณ บวก และดับไป

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

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

แต่คุณทำได้ในการสัมภาษณ์ไหม โดยไม่ต้อง ติดตั้งตามปกติ บนแป้นพิมพ์แล็ปท็อป กับหน้าจอแล็ปท็อป บนเก้าอี้ตลกๆ บนโต๊ะแปลกๆ กับนาฬิกาที่เดิน และมีคน (ตามทฤษฎี) คอยดูอยู่ คุณ? นอกจากนี้ คุณมีโอกาสที่จะไม่ได้รับงานนี้ คุณอาจต้องการงานเพื่อหาเงินเพื่อดูแลบ้านหรืออพาร์ตเมนต์ เลี้ยงดูคุณและคนที่คุณรัก และสิ่งดีๆ ทั้งหมดนั้น

แต่เดี๋ยวก่อนไม่มีแรงกดดัน

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

นอกจากนี้ฉันได้ทำ “argc, argv, fgets เป็น buf, สควอชขึ้นบรรทัดใหม่, ทำเป็นวง, สับมันในช่องว่างและจัดการกับผลลัพธ์” ใน C อาจมากกว่าร้อยครั้งในชีวิตของฉัน ถึงจุดนี้ ฉันรู้ทุกส่วน ฉันยังรู้ว่าส่วนใดที่อาจผิดพลาดได้ ฉันต้องตัดสินใจว่าจะข้ามอะไรไปและควรเก็บอะไรไว้เป็นการตรวจสุขภาพจิตในนามของการประหยัดเวลา ฉันไม่ต้องใช้เวลาพยายามทำให้สำเร็จ คนที่ยังไม่ได้ลงถนนสายนั้นก็คงจะไม่ง่ายนัก

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

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

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

มันไม่ใช่หลังจากที่ตัดการเชื่อมต่อจากปัญหาและใช้เวลาอยู่ห่างจากคอมพิวเตอร์ที่มันมาหาฉันและฉันก็คิดออก

นั่นอะไร? คุณไม่มีเวลาตัดการเชื่อมต่อแล้วกลับมาดูใหม่ เพราะคุณกำลังถูกกำหนดเวลา และพวกเขากำลังจะมาตรวจสอบคุณในไม่ช้านี้? เลวมาก! โชคดีรู้ว่าพลาดตรงไหน

ที่. ที่นั่นมีที่ที่เวลาไป

แถบด้านข้างที่ยึดไว้ล่วงหน้า: “เธอน่าจะใช้ Python” แค่ไปไกล ๆ. คุณ * ดังนั้น * ขาดประเด็น

อภิปรายสองหัวข้อ “สงครามศักดิ์สิทธิ์” พร้อมกัน

การไล่ล่า: โปรแกรมแก้ไขข้อความ *และ* แท็บเทียบกับช่องว่าง! อุ๊ย!

ฉันมี Macs ในชีวิตของฉัน พวกเขาได้รับการอัปเดตเป็นประจำ ในช่วงสองสามวันที่ผ่านมา พวกเขาได้รับ Monterey เวอร์ชัน 12.3 ดูเหมือนว่าจะไม่มีเหตุการณ์เกิดขึ้นเป็นส่วนใหญ่… จนกระทั่งฉันไปแก้ไขบางสิ่งโดยใช้สคริปต์ตัวตัดทอนเล็กๆ ของฉัน

ฉันมีสิ่งนี้ที่เรียกว่า “e” มาระยะหนึ่งแล้ว เป็นสคริปต์เล็ก ๆ ที่โง่ซึ่งทำหน้าที่ทำสองสิ่ง มันเริ่มตัว แก้ไข ของฉันด้วยไฟล์ที่กำหนด และเริ่มทำงานด้วยอาร์กิวเมนต์ที่ถูกต้องเพื่อปิดการใช้งานการตัดบรรทัดและเพื่อให้คีย์ [TAB] ใส่ในสองช่องว่างจริง ๆ

เหตุใดจึงมีสคริปต์และไม่ใช่ .nanorc ฉันคิดว่านี่ก่อนวันที่พวกเขามีไฟล์นั้น นอกจากนี้ยังมีความแตกต่างเล็กน้อย: ฉันเคยทำงานกับ Makefiles บ่อยมาก เช่นเดียวกับเมื่อก่อนฉันใช้เครื่องมือสร้าง no-Makefile C++ และในบริบทนั้น คุณ *ต้องการ* อักขระแท็บ no-joke ^I นั่นเป็นเพียงตัวคั่นเดียวที่จะอนุญาตเมื่อคุณเขียนส่วนต่อๆ ไปของกฎ

ดังนั้นสคริปต์ใบ้ของฉันจะใช้ “-w -E -T 2” เป็นส่วนใหญ่ ยกเว้นเมื่อทำงานบน Makefile เมื่อถึงจุดนั้นมันจะข้าม args เหล่านั้น ง่ายพอใช่มั้ย?

ฉันใช้สคริปต์นี้บนกล่อง Linux และ Mac มาเป็นเวลานานแล้ว และมันเพิ่งจะใช้งานไม่ได้บน Mac ตอนนี้ฉันได้รับข้อร้องเรียนเกี่ยวกับ “E” และ “T” ว่าไม่ใช่อาร์กิวเมนต์ที่ถูกต้อง จากนั้นก็แยก “อาร์กิวเมนต์เริ่มต้นที่เป็นไปได้สำหรับตัวแก้ไข pico” รออะไร?

ปิโก้กลับมาแล้ว? ใช่แล้วบน Macs ณ วันที่ 12.3 อันที่จริงแล้ว pico กลับมาแล้ว เพื่อให้แน่ใจว่าฉันไม่ได้จินตนาการถึงสิ่งต่าง ๆ ฉันจึงค้นหาเครื่องที่ยังไม่ได้อัปเกรดและตรวจสอบที่นั่น แน่นอนว่ามันคือนาโน ไม่ใช่ปิโก้

macOS ก่อน 12.3 มี pico เป็น symlink ที่ชี้ไปที่ nano

macOS 12.3 มี nano เป็น symlink… ชี้ไปที่ pico!

สำหรับผู้ที่ไม่ได้อยู่ในโลกนี้ pico เป็นส่วนหนึ่งของโปรแกรมรับส่งเมลแบบไพน์ที่แยกออกเป็นของตัวเอง มีปัญหาเรื่องใบอนุญาตแปลกๆ เป็นเวลาหลายปี และโดยทั่วไปไม่ใช่สิ่งที่ง่ายที่สุดในการค้นหา อาจเป็นเพราะเหตุนั้น นาโนจึงเริ่มต้นขึ้น เมื่อก่อนค่อนข้างใกล้เคียงในแง่ของคุณสมบัติและพฤติกรรม แต่นาโนก็แตกต่างไปในบางจุด มันหยิบความสามารถในการเปลี่ยนปุ่ม [TAB] เป็นช่องว่างจำนวนหนึ่งราวกับว่าคุณตีแถบพื้นที่นั้นหลายครั้ง ปิโกไม่ได้

ในบางจุด ฉันเปลี่ยนจากอักขระแท็บตามตัวอักษรในซอร์สโค้ดของฉันไปเป็นช่องว่าง อาจเป็นเพราะใช้สไตล์นั้นในที่ทำงานและไม่ได้เกลียดมัน จริงๆ แล้ว ที่ไหนสักแห่งระหว่างทาง ฉันเริ่มโดยอาศัยพฤติกรรมนาโนโดยไม่รู้ตัว

การอัปเดต macOS 12.3 ได้เปลี่ยนระบบพื้นฐานอย่างเงียบๆ จาก nano 2.0.6 เป็น pico 5.09 ดังนั้นหากคุณใช้สวิตช์เหล่านั้น แสดงว่าคุณโชคไม่ดี คำแนะนำของฉันหากคุณสนใจเกี่ยวกับสิ่งนี้คือไปรับ nano จาก Macports หรืออะไรก็ตาม และลืมเกี่ยวกับการใช้ตัวแก้ไขสต็อก นั่นคือสิ่งที่ฉันกำลังจะทำ อย่างน้อยฉันก็ไม่ต้องตั้งโปรแกรมนิ้วใหม่เพราะ “e foo” ยังคงเป็น “e foo” ไม่ว่ามันจะเรียกอะไรอยู่ข้างใต้

สำหรับการขาดคุณสมบัติใน pico นั้นค่อนข้างแปลกจริงๆ หากคุณไปเจาะลึกในซอร์ส พวกเขามี random.c ที่มีฟังก์ชันที่เรียกว่า tab ซึ่งอ้างว่า “จำลองแท็บหยุด” โดยใช้ช่องว่าง ที่กล่าวว่าฉันไม่พบสถานที่ใดที่จะเรียกมันด้วยค่าวิเศษที่จะทำให้มันประพฤติอย่างนั้น

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

ฉันจะไม่แปลกใจเลยหากสวิตช์นี้เป็นเพียงมากกว่าที่ Apple จะลบ GPLed ออกจากระบบปฏิบัติการ – ดูเหมือนว่า pico จะใช้ใบอนุญาต Apache พวกเขาทิ้ง bash สำหรับ zsh (ใบอนุญาต MIT) ในบางจุด (ฉันคิดว่า Big Sur) และตอนนี้เป็นเช่นนี้ ตกลงตามนั้น

สิ่งโง่ๆ ที่บางครั้งคุณสามารถทำได้ด้วยฮาร์ดลิงก์

นี่เป็นกลอุบายที่เก่าและงี่เง่าที่คุณสามารถทำได้กับระบบไฟล์บางระบบในบางสถานการณ์ในสมัยก่อน… และอาจจะยังสามารถทำได้ในบางที่ในปัจจุบัน

สมมติว่าคุณมีบัญชีอยู่ในกล่อง Unixy ที่คลุมเครือซึ่งคุณไม่ได้เรียกใช้ และคุณกำลังมองหาช่องโหว่เพื่อทำการรูท คุณสังเกตเห็นว่ามีบางโปรแกรมที่ติดตั้ง suid root และมีประวัติความปลอดภัยที่แย่มาก มันเต็มไปด้วยการปฏิบัติที่แย่มาก และดูเหมือนว่าทุกเดือนจะมีช่องโหว่ใหม่ และผู้ดูแลระบบต้องแข่งกันแก้ไขก่อนที่สคริปต์ตัวเล็ก ๆ ของโลกจะใช้มันสำหรับความชั่วร้ายที่ยิ่งใหญ่

ปัญหาคือในขณะที่เวอร์ชัน X อาจมีช่องโหว่ แต่จะถูกลบออกและจะถูกแทนที่ด้วยเวอร์ชัน Y โดยไม่มีช่องโหว่นั้น เมื่อคุณได้เครื่องมือที่จะบุกเข้าไปใน X มันจะหายไป

แต่…จะเกิดอะไรขึ้นถ้าคุณสามารถเก็บสำเนาของ X ไว้ได้ในภายหลัง

สิ่งที่คุณต้องทำคือสร้างฮาร์ดลิงก์โดยชี้ไปที่ไฟล์ที่คุณต้องการเก็บรักษา เก็บไว้ในจุดที่บัญชีของคุณเขียนได้ จากนั้นพูด /usr/bin/sudo (เพราะ ไม่เคย มีปัญหาด้านความปลอดภัย…) ถูกแทนที่ด้วยไฟล์ใหม่ในบางจุด และคุณจะต้องเก็บเวอร์ชันเก่าไว้ เมื่อคุณได้เครื่องมือที่จะเปิดมัน ออกไปเลย!

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

แน่นอนว่าทุกวันนี้ มันไม่ง่ายเลยสำหรับระบบที่ทันสมัยกว่าที่คุณพบ Debian 11 ที่นี่ไม่ยอมให้ฉันทำ – มันคือเมือง EPERM Rocky 8 (เช่น CentOS 8 และ RHEL 8 ด้วย) ก็จะไม่ทำเช่นนั้น พวกเขาทั้งคู่มีขยะใน /usr/lib/sysctl.d เพื่อล็อคสิ่งนี้ แต่การติดตั้งเวิร์กสเตชัน Slackware 14.2 ตัวเก่าของฉันทำให้ฉันทำได้เมื่อลองครั้งสุดท้ายเมื่อประมาณหนึ่งปีที่แล้ว ว่าไงนะ? ฉันพนันได้เลยว่ามันยังคงใช้งานได้ถ้าฉันขุดไดรฟ์เก่าออกแล้วเปิดมันขึ้นมา

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

อนึ่ง นี่คือซอสวิเศษ: /proc/sys/fs/protected_hardlinks อ่าน man page สำหรับ proc(5) เพื่อเรียนรู้เพิ่มเติมเกี่ยวกับมัน

ที่ตลกก็คือมีการอภิปรายเกี่ยวกับเรื่องนี้ในรายการส่งเมลของเคอร์เนล linux เมื่อเดือนพฤศจิกายน 2546 ตามบันทึกดั้งเดิมของฉันในหัวข้อนี้ ผมก็เลยไปหาดูเอาเองว่า นี่แหละ กระทู้ที่อ่านเมื่อนานมาแล้ว เป็นที่น่าสนใจที่จะทราบว่า เท่าที่ฉันสามารถบอกได้ ไม่มีอะไรเปลี่ยนแปลงต้นน้ำจริงๆ ผู้ดูแลระบบที่หวาดระแวงคนนี้อย่างฉันไม่มีทางเลือกนอกจากใช้แพตช์ Openwall (ยอดเยี่ยมที่สุด) เพื่อล็อคสิ่งนี้ ฉันใช้มันในเครื่องที่ทำงานซึ่งมีผู้ใช้ที่ไม่ใช่พนักงาน… เผื่อไว้

ปรากฏปุ่ม /proc นี้ปรากฏขึ้นใน Linux 3.6 และดูเหมือนว่าเป็นปี 2012 อืม พ.ศ. 2546…และ พ.ศ. 2555 เป็นเวลานาน เห็นได้ชัดว่าอุปกรณ์ประกอบฉากที่บ้าคลั่งนั้นเกิดจากการที่ผู้กล้า lkml และทำให้มันเกิดขึ้นที่ต้นน้ำในที่สุด

สถานการณ์ทั้งหมดนี้น่ากลัว อ่านเพิ่มเติมเกี่ยวกับเรื่อง นี้

เอาผลเบอร์รี่

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

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

อย่างไรก็ตาม บริษัทเทคโนโลยีต่างๆ ได้ตัดสินใจที่จะผ่านจุดนี้ไป และทำให้เกิดแนวคิด “microkitchens” ทั้งหมดนี้ นี่คือที่ที่พวกเขาวางตราสินค้าไว้บนคูลเลอร์ (แทนที่จะเป็น “Coca-Cola” หรือ “Pepsi”) และบรรจุของเหลวที่มีรสหวานเป็นฟองทุกชนิดที่พวกเขาสามารถหยิบจับได้ พวกเขามีชั้นวางและชั้นวางของที่เต็มไปด้วยขนมขบเคี้ยวกรุบกรอบน้ำตาลและคาร์โบไฮเดรตที่น่าสนใจทุกประเภท พวกเขายังมีเครื่องชงกาแฟและเอสเปรสโซแบบมืออาชีพเพื่อให้ผู้คนสามารถขับกล่อมทั้งสำนักงานด้วยทักษะการนึ่งของพวกเขา

เงื่อนไขเปลี่ยนแปลงอยู่เสมอ และบริษัทต้องการชดใช้เงินบางส่วนที่พวกเขาใช้ไปกับสิ่งนี้ ครัวขนาดเล็กบางส่วนหายไปและบางส่วนหดตัว และผู้คนบ่น แน่นอนฉันทำ… ครั้งแรกที่มันเกิดขึ้น พวกเขาอ้างว่าผลประโยชน์เหล่านี้เป็นส่วนหนึ่งของเงินเดือนของฉัน และนี่คือเหตุผลที่พวกเขาเสนอสิ่งที่ฉันทำ ฉันเขียนเกี่ยวกับเรื่องนี้ในอีกไม่กี่ปีต่อมา และถูกนำไปทำงานทางอินเทอร์เน็ต

เมื่อถึงเวลาที่งาน Big Tech ครั้งต่อไปของฉันเกิดขึ้น ฉันไม่มีความเข้าใจผิดเกี่ยวกับสถานการณ์อาหารเลย มันจะอยู่ที่นั่นชั่วขณะหนึ่ง และจากนั้นมันก็จะหดตัวลง และแน่นอน ตลอดสี่ปีครึ่งต่อจากนี้ มันก็ทำอย่างนั้นจริงๆ ฉันแค่ยิ้มให้คนที่กำลังจะผ่านมันเป็นครั้งแรก

ทุกๆ อย่างที่เกิดขึ้นที่บริษัท G ก็เกิดขึ้นที่บริษัท F ซึ่งใช้เวลาเพียงไม่นาน และไม่ได้เกิดขึ้นในลำดับเดียวกันเสมอไป

นานหลังจากนั้น ฉันสมัครอย่างโง่เขลาเพื่อทำสิ่งนี้อีกครั้ง แต่คราวนี้ฉันวางแผนที่จะจัดการกับสิ่งเหล่านี้ด้วยตัวเอง ผู้คนมักจะพาฉันไปรับประทานอาหารกลางวันที่สถานที่จัดงาน แต่ฉันพยายามที่จะออกจากสำนักงานให้มากที่สุด สำนักงานของบริษัทนี้ตั้งอยู่กลางเมืองใหญ่จริงๆ (ถ้ามีปัญหา) และสามารถเดินไปสถานที่ต่างๆ ได้มากมาย ฉันสามารถซื้อพิซซ่า ไก่ทอด บาร์เบอร์เกอร์ ซุปและสลัดกับคุกกี้ พิซซ่าอีกประเภทหนึ่ง อาหารจิตวิญญาณ… ทั้งหมดด้วยการเดินเท้า นอกจากนี้ยังมีร้าน Philz Coffee อยู่ฝั่งตรงข้ามถนนสำหรับช่วงบ่ายที่สิ่งต่างๆ ไม่ค่อยดี นัก และฉันแค่อยากจะหนีไปพักสักครู่แล้วเติมพลังก่อนจะลองอีกครั้ง

ดังนั้นฉันเขียนอะไรกลับไปในปี 2019 ในขณะที่อยู่ในงานนั้น? นี้:

เวลาที่ดีที่สุดในการเก็บผลเบอร์รี่ฟรีในห้องเบรกเกอร์ (หรือน้ำอัดลม ของว่าง ลูกอม หรือคอมบูชาบนก๊อก หรือ …) คือเมื่อวาน นี่เป็นความจริงเสมอ

ยิ่งคุณนำมันออกไปเร็วเท่าไร ประวัติของบริษัทก็จะ “หมดไป” เร็วเท่านั้น และเปลี่ยนจากจุดที่เจ็บกลายเป็นเรื่องตลก (ห้องประชุม “ไม่มีผลไม้” ทั้งหมด) ไปสู่ตำนาน (“ทำไม ชื่อนั้นเหรอ?”) และสุดท้ายแล้ว “คนพวกนี้ก็แค่มีสิทธิและโง่เง่า”

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

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

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

อย่า แพ็คพนักงานแน่น จนคุณขับรถออกไปทานอาหารกลางวันไม่ได้เพราะจะไม่มีที่จอดรถเมื่อคุณกลับมา

ชื่นชมความจริงที่ว่าการให้โอกาสพวกเขาเปลี่ยนเกียร์อาจนำมุมมองใหม่ๆ ที่คุณจะไม่ได้รับจากการจ้างทาสที่ไม่ออกจากอาคารเพียงครั้งเดียวในเก้าชั่วโมง

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

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

ขอให้สนุกกับมัน

คำถามเกี่ยวกับรถบรรทุกก่อสร้างบนรางรถไฟ

วันอื่น รสชาติท้องถิ่นอีกเล็กน้อย แต่คราวนี้ เป็นสิ่งที่ฉันหวังว่าฉันไม่ต้องเขียนเกี่ยวกับ

ในเดือนสิงหาคม 2012 ฉัน เขียน เกี่ยวกับการเห็นรถบรรทุกซ่อมบำรุงกลิ้งไปตามเส้นทาง Caltrain ใน Mountain View มีสิ่งที่แนบมาพิเศษเพื่อให้อยู่บนราง แขนไม่เคยลงมาเพื่อข้าม มันเข้าใกล้ได้ จากนั้นผู้คนข้างในก็มองไปรอบๆ และเดินผ่านไป และแขนก็ไม่เคยขยับเขยื้อนเลย ไม่มีไฟกระพริบหรือระฆัง

จากความเข้าใจของฉันเกี่ยวกับวิธีการทำงานของทางม้าลายเหล่านั้น ที่กล่าวว่า “สิ่งที่ถือรถบรรทุกนั้นไว้กับรางไม่สามารถเชื่อมต่อพวกเขาในลักษณะใดก็ตามที่รถไฟทำเพื่อกระตุ้นแขนข้าม”

เกตส์? ประตูอะไร?

นี้ไม่ดี แล้ววันนี้ก็เกิดขึ้น เช้าตรู่ของวันนี้ Caltrain ชน * รถบรรทุกสองคัน * บนรางทางเหนือของ Millbrae จากนั้นก็ เกิดไฟไหม้ กลุ่มคนได้รับบาดเจ็บ ถูกเขย่าขวัญมากขึ้น

นี่ไม่ใช่รถบรรทุกสุ่มจากคนงี่เง่าสุ่ม ๆ ขึ้น ๆ ลง ๆ เหล่านี้เป็นรถบรรทุกก่อสร้างของตัวเองซึ่งกำลังดำเนินการติดตั้งไฟฟ้าเหนือศีรษะสำหรับรถไฟฟ้าในอนาคต

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

เราน่าจะได้ยินมากขึ้นเกี่ยวกับสิ่งที่สัญญาณพูดและไม่ว่ารถไฟจะผ่านสัญญาณสีแดงหรือไม่ ฉันแค่มีความรู้สึกไม่ดีที่พวกเขาเห็นสีเขียวและเดินต่อไป