Bash: การนอนไม่ จำกัด (การปิดกั้นแบบไม่ จำกัด )


158

ผมใช้startxในการเริ่มต้น X .xinitrcซึ่งจะประเมินผลการศึกษาของฉัน ในของฉันฉันจะเริ่มต้นจัดการหน้าต่างของฉันโดยใช้.xinitrc /usr/bin/mywmตอนนี้ถ้าฉันฆ่า WM ของฉัน (เพื่อทดสอบ WM อื่น ๆ ) X จะสิ้นสุดเช่นกันเพราะ.xinitrcสคริปต์มาถึง EOF ดังนั้นฉันจึงเพิ่มสิ่งนี้ในตอนท้ายของ.xinitrc:

while true; do sleep 10000; done

วิธีนี้ X จะไม่ยุติลงถ้าฉันฆ่า WM ของฉัน ตอนนี้คำถามของฉัน: ฉันจะนอนหลับไม่ จำกัดแทนการวนลูปได้อย่างไร มีคำสั่งที่จะชอบแช่แข็งสคริปต์หรือไม่

ขอแสดงความนับถืออย่างสูง

คำตอบ:


330

sleep infinity ทำในสิ่งที่มันแนะนำและทำงานได้โดยไม่ใช้แมว


16
เย็น. น่าเสียดายที่ busybox ของฉันไม่เข้าใจ
ไม่ใช่ผู้ใช้

12
BSD (หรืออย่างน้อย OS X) ก็ไม่เข้าใจsleep infinityเช่นกันถึงแม้ว่ามันจะเป็นสิ่งที่ยอดเยี่ยมในการเรียนรู้เกี่ยวกับ Linux อย่างไรก็ตามwhile true; do sleep 86400; doneควรเป็นตัวแทนที่เพียงพอ
Ivan X

16
เกี่ยวกับเรื่องนี้ฉันได้ทำการวิจัยที่ฉันบันทึกไว้ในคำตอบที่แยกต่างหาก เพื่อสรุป: infinityจะแปลงใน C จาก "สตริง" doubleเพื่อ จากนั้นdoubleจะถูกปัดเศษเป็นค่าสูงสุดที่อนุญาตtimespecซึ่งหมายถึงจำนวนวินาทีที่มาก (ขึ้นอยู่กับสถาปัตยกรรม) แต่ในทางทฤษฎีแล้ว จำกัด
jp48

72

tail ไม่บล็อก

เช่นเคย: สำหรับทุกสิ่งมีคำตอบที่สั้นเข้าใจง่ายง่ายต่อการติดตามและผิดทั้งหมด นี่tail -f /dev/nullตกอยู่ในหมวดหมู่นี้;)

ถ้าคุณดูด้วยstrace tail -f /dev/nullคุณจะสังเกตเห็นว่าวิธีนี้อยู่ไกลจากการปิดกั้น! อาจยิ่งแย่ไปกว่าsleepโซลูชันในคำถามเนื่องจากใช้ทรัพยากรที่มีค่า (ภายใต้ Linux) เช่นinotifyระบบ นอกจากนี้ยังมีกระบวนการอื่น ๆ ที่เขียนเพื่อ/dev/nullทำให้เป็นtailวง (บน Ubuntu64 16.10 ของฉันจะเพิ่ม 10 syscalls ต่อวินาทีในระบบที่ยุ่งอยู่แล้ว)

คำถามคือสำหรับคำสั่งการปิดกั้น

น่าเสียดายที่ไม่มีสิ่งนั้น ..

อ่าน: ฉันไม่รู้วิธีเก็บถาวรด้วยเชลล์โดยตรง

ทุกอย่าง (แม้sleep infinity) จะถูกขัดจังหวะโดยสัญญาณบางอย่าง sleepดังนั้นถ้าคุณต้องการที่จะแน่ใจว่าจริงๆมันไม่ได้ล้ำกลับมาก็จะต้องทำงานในวงเช่นคุณได้แล้วสำหรับคุณ โปรดทราบว่า (บน Linux) /bin/sleepเห็นได้ชัดว่าถูกปกคลุมที่ 24 วัน (ดูที่strace sleep infinity) ดังนั้นสิ่งที่ดีที่สุดที่คุณสามารถทำได้คือ:

while :; do sleep 2073600; done

(โปรดทราบว่าฉันเชื่อว่าsleepลูปภายในสำหรับค่าที่สูงกว่า 24 วัน แต่หมายความว่า: มันไม่ได้ปิดกั้นมันวนซ้ำช้ามากดังนั้นทำไมไม่ย้ายลูปนี้ไปด้านนอก?)

.. แต่คุณสามารถเข้ามาใกล้มากโดยไม่มีชื่อ fifo

คุณสามารถสร้างสิ่งที่บล็อกจริง ๆ ตราบใดที่ไม่มีสัญญาณที่ส่งไปยังกระบวนการ การใช้งานต่อไปนี้bash 42 PID และ 1 fifo:

bash -c 'coproc { exec >&-; read; }; eval exec "${COPROC[0]}<&-"; wait'

คุณสามารถตรวจสอบว่าบล็อกนี้จริงๆด้วยstraceถ้าคุณต้องการ:

strace -ff bash -c '..see above..'

วิธีสร้างสิ่งนี้

readบล็อกหากไม่มีข้อมูลอินพุต (ดูคำตอบอื่น ๆ ) อย่างไรก็ตามโดยทั่วไปtty(aka. stdin) นั้นไม่ใช่แหล่งข้อมูลที่ดีเนื่องจากจะปิดเมื่อผู้ใช้ออกจากระบบ ttyนอกจากนี้ยังอาจขโมยการป้อนข้อมูลบางส่วนจาก ไม่ดี.

ในการสร้างreadบล็อกเราต้องรอสิ่งfifoที่จะไม่ส่งคืนสิ่งใด ในbash 4มีคำสั่งที่ว่าสามารถให้เรามีเช่น:fifo coprocหากเรารอการบล็อกread(ซึ่งก็คือของเราcoproc) เราก็เสร็จแล้ว น่าเศร้าที่ต้องเปิด PID สองอันและกfifo.

ตัวแปรที่มีชื่อ fifo

หากคุณไม่ต้องการใช้ชื่อfifoคุณสามารถทำได้ดังนี้:

mkfifo "$HOME/.pause.fifo" 2>/dev/null; read <"$HOME/.pause.fifo"

การไม่ใช้ลูปในการอ่านเป็นเรื่องที่ค่อนข้างเลอะเทอะ แต่คุณสามารถนำสิ่งนี้กลับมาใช้ซ้ำได้fifoบ่อยเท่าที่คุณต้องการและทำให้การreadเลิกใช้โดยใช้touch "$HOME/.pause.fifo"(ถ้ามีมากกว่าการรอการอ่านเพียงครั้งเดียว

หรือใช้ Linux pause()syscall

สำหรับการบล็อกแบบไม่ จำกัด มีการเรียกเคอร์เนล Linux ซึ่งเรียกว่าpause()ทำสิ่งที่เราต้องการ: รอตลอดไป (จนกว่าสัญญาณจะมาถึง) อย่างไรก็ตามไม่มีโปรแกรม userspace สำหรับเรื่องนี้ (ยัง)

สร้างโปรแกรมดังกล่าวเป็นเรื่องง่าย นี่เป็นตัวอย่างเพื่อสร้างโปรแกรมลีนุกซ์ขนาดเล็กมากที่เรียกว่าpauseหยุดชั่วคราวไปเรื่อย ๆ (ต้องการdiet, gccฯลฯ ):

printf '#include <unistd.h>\nint main(){for(;;)pause();}' > pause.c;
diet -Os cc pause.c -o pause;
strip -s pause;
ls -al pause

python

หากคุณไม่ต้องการรวบรวมบางสิ่งด้วยตัวคุณเอง แต่คุณได้pythonติดตั้งแล้วคุณสามารถใช้สิ่งนี้ภายใต้ Linux:

python -c 'while 1: import ctypes; ctypes.CDLL(None).pause()'

(หมายเหตุ: ใช้ exec python -c ...เพื่อแทนที่เชลล์ปัจจุบันซึ่งจะเพิ่ม PID หนึ่งตัวโซลูชันสามารถปรับปรุงได้ด้วยการเปลี่ยนเส้นทาง IO บางส่วนเช่นกันการปล่อย FD ที่ไม่ได้ใช้จะขึ้นอยู่กับคุณ)

วิธีการทำงาน (ฉันคิดว่า): ctypes.CDLL(None)โหลดไลบรารี C มาตรฐานและเรียกใช้pause()ฟังก์ชันในภายในวงเพิ่มเติมบางอย่าง มีประสิทธิภาพน้อยกว่ารุ่น C แต่ใช้งานได้

คำแนะนำของฉันสำหรับคุณ:

อยู่ที่การนอนหลับวน ง่ายต่อการเข้าใจพกพาได้มากและบล็อกเวลาส่วนใหญ่


1
@Andrew ปกติคุณไม่จำเป็นต้องtrap(ซึ่งปรับเปลี่ยนพฤติกรรมของเชลล์เพื่อส่งสัญญาณ) หรือพื้นหลัง (ซึ่งทำให้เชลล์สามารถสกัดสัญญาณจากเทอร์มินัลเช่น Strg + C) ดังนั้นsleep infinityก็พอ (พฤติกรรมเช่นexec sleep infinityถ้ามันเป็นคำสั่งที่ผ่านมา. เพื่อดูการใช้งานที่แตกต่างกันstrace -ffDI4 bash -c 'YOURCODEHERE') การนอนหลับวนลูปจะดีกว่าเพราะsleepสามารถกลับมาในบางสถานการณ์ ตัวอย่างเช่นคุณไม่ต้องการให้ X11 ปิดกระทันหันใน a killall sleepเพียงเพราะ.xstartupสิ้นสุดในsleep infinityแทนการวนรอบสลีป
Tino

อาจจะคลุมเครือเล็กน้อย แต่s6-pauseเป็นคำสั่ง userland เพื่อรันpause()โดยไม่สนใจสัญญาณต่างๆ
แพทริค

@Tino /bin/sleepไม่ได้ต่อยอดใน 24 วันตามที่คุณพูด มันจะดีถ้าคุณสามารถอัปเดต บน Linux ตอนนี้โค้ดนี้ทำงาน มันnanosleep()ปิดบัง syscalls แต่ละรายการเป็น 24 วัน แต่จะเรียกพวกมันเป็นวง ดังนั้นsleep infinityไม่ควรออกหลังจาก 24 วัน อินฟินิตี้ในเชิงบวกได้รับการดัดแปลงเป็นdouble struct timespecดูrpl_nanosleepใน GDB infinityรับการแปลงเป็น{ tv_sec = 9223372036854775807, tv_nsec = 999999999 }บน Ubuntu 16.04
nh2

@ nh2 มันถูกกล่าวถึงแล้วในข้อความที่ว่าการนอนหลับอาจวนซ้ำแทนที่จะถูกบล็อกอย่างสมบูรณ์ ตอนนี้ฉันแก้ไขมันเล็กน้อยเพื่อหวังว่าจะทำให้ข้อเท็จจริงนี้ชัดเจนยิ่งขึ้น โปรดทราบว่า " น่าจะเป็น " เพราะจากstraceคนเดียวฉันไม่สามารถพิสูจน์ได้ว่ามีรหัสการวนซ้ำที่รวบรวมอยู่sleepและฉันไม่ต้องการที่จะรอ 24 วันเพื่อทดสอบ (หรือถอดรหัส/bin/sleep) มันจะเป็นการดีกว่าที่จะตั้งโปรแกรมป้องกันหากไม่มีการพิสูจน์ทางคณิตศาสตร์อย่างหนักสิ่งที่เป็นจริงอย่างที่มันเป็น อย่าเชื่อถืออะไรเลย:killall -9 sleep
Tino

ตัวเลือกหยุดชั่วคราว () สามารถทำได้อย่างง่ายดายด้วย Perl: perl -MPOSIX -e 'หยุดชั่วคราว ()'
tgoodhart

70

บางทีนี่อาจดูน่าเกลียด แต่ทำไมไม่เพียงแค่รันcatและปล่อยให้มันรออินพุตตลอดไป?


4
วิธีนี้ใช้ไม่ได้หากคุณไม่มีท่อห้อยที่จะอ่าน กรุณาแนะนำ
Matt Joiner

2
@ Matt อาจทำท่อและcatมันได้หรือไม่ mkfifo pipe && cat pipe
Michał Trybus

สิ่งที่ @twalberg พูด แต่นอกจากนี้คุณสามารถกำหนดใหม่เป็น 3 และยกเลิกการเชื่อมโยงดังที่แสดงไว้ที่นี่: superuser.com/a/633185/762481
jp48

32

TL; DR: sleep infinityนอนหลับจริงเวลาสูงสุดที่อนุญาตซึ่งมี จำกัด

สงสัยว่าทำไมสิ่งนี้ไม่ได้บันทึกไว้ที่ใดฉันรำคาญที่จะอ่านแหล่งข้อมูลจาก coreutils ของ GNUและฉันพบว่ามันประมวลผลอย่างคร่าว ๆ ดังนี้

  1. ใช้strtodจาก C stdlib บนอาร์กิวเมนต์แรกเพื่อแปลง 'อนันต์' เป็นความแม่นยำสองเท่า ดังนั้นสมมติว่ามีความแม่นยำสองเท่าของ IEEE 754 ค่าอนันต์บวก 64 บิตจะถูกเก็บไว้ในsecondsตัวแปร
  2. วิงวอนxnanosleep(seconds)( พบใน gnulib ) นี้จะเรียกในทางกลับกันdtotimespec(seconds)( ยังอยู่ใน gnulib ) การแปลงจากไปdoublestruct timespec
  3. struct timespecเป็นเพียงตัวเลขคู่หนึ่ง: ส่วนจำนวนเต็ม (เป็นวินาที) และส่วนที่เป็นเศษส่วน (เป็นนาโนวินาที) อย่างไร้เดียงสาแปลงอินฟินิตี้บวกจำนวนเต็มจะส่งผลให้พฤติกรรมที่ไม่ได้กำหนด (ดู§6.3.1.4จากมาตรฐาน C) TYPE_MAXIMUM (time_t)ดังนั้นแทนที่จะตัดทอนไป
  4. ค่าจริงของTYPE_MAXIMUM (time_t)ไม่ได้ตั้งอยู่ในมาตรฐาน (แม้sizeof(time_t)ไม่ใช่) ตัวอย่างเช่นลองเลือก x86-64 จากเคอร์เนล Linux ล่าสุด

นี่คือTIME_T_MAXในเคอร์เนล Linux ซึ่งกำหนด ( time.h) เป็น:

(time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)

ทราบว่าtime_tเป็น__kernel_time_tและtime_tเป็นlong; ใช้โมเดลข้อมูล LP64 ดังนั้นsizeof(long)เป็น 8 (64 บิต)

ซึ่งผลลัพธ์ใน: TIME_T_MAX = 9223372036854775807.

นั่นคือ: sleep infiniteผลลัพธ์ในเวลาพักจริงของ 9223372036854775807 วินาที (10 ^ 11 ปี) และสำหรับระบบลินุกซ์ 32 บิต ( sizeof(long)คือ 4 (32 บิต)): 2147483647 วินาที (68 ปีดูปัญหาปี 2038 ด้วย )


แก้ไข : เห็นได้ชัดว่าnanosecondsฟังก์ชั่นที่เรียกว่าไม่ใช่ syscall โดยตรง แต่เป็น wrapper ขึ้นอยู่กับระบบปฏิบัติการ ( กำหนดไว้ใน gnulib )

มีขั้นตอนพิเศษเป็นผลเป็นเพราะบางระบบที่HAVE_BUG_BIG_NANOSLEEPมีการtrueนอนหลับที่ถูกตัดทอนถึง 24 วันและจากนั้นก็เรียกในวง นี่เป็นกรณีสำหรับ distros Linux บางตัว (หรือทั้งหมด) โปรดทราบว่าเสื้อคลุมนี้อาจไม่ได้ใช้หากการทดสอบกำหนดค่า - เวลาสำเร็จ ( แหล่งที่มา )

โดยเฉพาะอย่างยิ่งที่จะเป็น24 * 24 * 60 * 60 = 2073600 seconds(บวก 999999999 นาโนวินาที) แต่สิ่งนี้ถูกเรียกในลูปเพื่อให้เคารพเวลาสลีปทั้งหมดที่ระบุ ดังนั้นข้อสรุปก่อนหน้านี้ยังคงใช้ได้


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

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


1
ใน coreutils ถัดไปsleep infinityตอนนี้จะนอนหลับตลอดไปโดยไม่วน: lists.gnu.org/archive/html/bug-gnulib/2020-02/msg00081.html
Vladimir Panteleev

8

sleep infinityดูดีที่สุด แต่บางครั้งมันก็ใช้ไม่ได้ด้วยเหตุผลบางอย่าง ในกรณีที่คุณสามารถลองคำสั่งปิดกั้นอื่น ๆ เช่นcat, read, tail -f /dev/null, grep aฯลฯ


1
tail -f /dev/nullยังเป็นวิธีแก้ปัญหาการทำงานสำหรับฉันบนแพลตฟอร์ม SaaS
schmunk

2
tail -f /dev/nullยังมีข้อได้เปรียบของการไม่บริโภค stdin ฉันใช้มันด้วยเหตุผลนั้น
Sudo Bash

ผู้ที่พิจารณาตัวเลือกนี้ควรอ่านคำตอบนี้เพื่อเรียนรู้เกี่ยวกับการแยกตัวเลือกนี้
เงา

6

สิ่งที่เกี่ยวกับการส่งSIGSTOPให้กับตัวเอง?

สิ่งนี้ควรหยุดกระบวนการชั่วคราวจนกว่าจะได้รับ SIGCONT ซึ่งเป็นในกรณีของคุณ: ไม่เคย

kill -STOP "$$";
# grace time for signal delivery
sleep 60;

6
สัญญาณอะซิงโครนัส ดังนั้นต่อไปนี้สามารถเกิดขึ้นได้: a) เชลล์เรียกว่า kill b) kill บอกเคอร์เนลว่าเชลล์จะได้รับสัญญาณ STOP c) kill จะยุติและกลับไปที่เชลล์ d) เชลล์จะดำเนินการต่อไป (อาจสิ้นสุดลงเนื่องจากสคริปต์สิ้นสุด) e) เคอร์เนล ส่งสัญญาณ STOP ไปที่ shell
ไม่ใช่ผู้ใช้

1
@temple ความเข้าใจที่ยอดเยี่ยมไม่ได้คิดเกี่ยวกับลักษณะของสัญญาณแบบอะซิงโครนัส ขอบคุณ!
michuelnik

4

ให้ฉันอธิบายว่าทำไมsleep infinityทำงานแม้ว่ามันจะไม่ได้รับการบันทึกไว้ คำตอบของ jp48ก็มีประโยชน์เช่นกัน

สิ่งที่สำคัญที่สุด: โดยการระบุinfหรือinfinity(ทั้งตัวพิมพ์เล็กและใหญ่) คุณสามารถเข้าสู่โหมดสลีปเป็นเวลานานที่สุดที่ใบอนุญาตใช้งานของคุณ (เช่นค่าที่น้อยกว่าHUGE_VALและTYPE_MAXIMUM(time_t) )

ทีนี้มาดูรายละเอียดกันดีกว่า รหัสที่มาของsleepคำสั่งที่สามารถอ่านได้จากcoreutils / src / sleep.c ฟังก์ชั่นทำสิ่งนี้:

double s; //seconds
xstrtod (argv[i], &p, &s, cl_strtod); //`p` is not essential (just used for error check).
xnanosleep (s);

ความเข้าใจ xstrtod (argv[i], &p, &s, cl_strtod)

xstrtod()

ตามgnulib / lib / xstrtod.cโทรของxstrtod()สตริงแปลงargv[i]เป็นค่าจุดลอยและเก็บไว้เพื่อใช้ฟังก์ชั่นแปลง*scl_strtod()

cl_strtod()

ที่สามารถมองเห็นได้จากcoreutils / lib / CL-strtod.c , แปลงสตริงเป็นค่าจุดลอยโดยใช้cl_strtod()strtod()

strtod()

ตามman 3 strtod, แปลงสตริงค่าเป็นประเภทstrtod() doublemanpage พูดว่า

รูปแบบที่คาดหวังของสตริง (ส่วนเริ่มต้นของ) คือ ... หรือ (iii) อินฟินิตี้หรือ ...

และอินฟินิตี้หมายถึง

อนันต์คือ "INF" หรือ "INFINITY" โดยไม่สนใจขนาดตัวพิมพ์

แม้ว่าเอกสารจะบอก

หากค่าที่ถูกต้องจะทำให้เกิดการล้น, บวกหรือลบHUGE_VAL( HUGE_VALF, HUGE_VALL) จะถูกส่งกลับ

มันไม่ชัดเจนว่าวิธีการปฏิบัติไม่มีที่สิ้นสุด ดังนั้นเรามาดูรหัสที่มาgnulib / lib / strtod.c สิ่งที่เราต้องการอ่านคือ

else if (c_tolower (*s) == 'i'
         && c_tolower (s[1]) == 'n'
         && c_tolower (s[2]) == 'f')
  {
    s += 3;
    if (c_tolower (*s) == 'i'
        && c_tolower (s[1]) == 'n'
        && c_tolower (s[2]) == 'i'
        && c_tolower (s[3]) == 't'
        && c_tolower (s[4]) == 'y')
      s += 5;
    num = HUGE_VAL;
    errno = saved_errno;
  }

ดังนั้นINFและINFINITY(ทั้งกรณีตาย) HUGE_VALได้รับการยกย่องว่าเป็น

HUGE_VAL ครอบครัว

ลองใช้N1570เป็นมาตรฐาน C HUGE_VAL, HUGE_VALFและHUGE_VALLแมโครที่กำหนดไว้ใน§7.12-3

มาโคร
    HUGE_VAL
ขยายเป็นนิพจน์ค่าคงที่เป็นบวกสองเท่าซึ่งไม่จำเป็นต้องแทนค่าได้ในลักษณะลอยตัว แมโคร
    HUGE_VALF
    HUGE_VALL
จะลอยตามลำดับและ analogs HUGE_VALคู่ที่ยาวนานของ

HUGE_VAL, HUGE_VALFและHUGE_VALLสามารถเป็นอนันต์เชิงบวกในการดำเนินการที่สนับสนุนอินฟินิตี้

และใน§7.12.1-5

หากผลลอยล้นและการปัดเศษเริ่มต้นมีผลแล้วฟังก์ชั่นส่งกลับค่าของแมโครHUGE_VAL, HUGE_VALFหรือHUGE_VALLตามประเภทผลตอบแทน

ความเข้าใจ xnanosleep (s)

xstrtod()ตอนนี้เราเข้าใจสาระสำคัญทั้งหมดของ จากคำอธิบายข้างต้นก็คือคริสตัลที่ชัดเจนว่าเราได้เห็นเป็นครั้งแรกจริงหมายถึงxnanosleep(s)xnanosleep(HUGE_VALL)

xnanosleep()

ตามซอร์สโค้ดgnulib / lib / xnanosleep.cส่วนxnanosleep(s)ใหญ่ทำสิ่งนี้:

struct timespec ts_sleep = dtotimespec (s);
nanosleep (&ts_sleep, NULL);

dtotimespec()

ฟังก์ชั่นนี้จะแปลงข้อโต้แย้งของพิมพ์กับวัตถุของการพิมพ์double struct timespecเพราะมันเป็นเรื่องง่ายมากให้ฉันอ้างอิงรหัสที่มาgnulib / lib / dtotimespec.c ความคิดเห็นทั้งหมดถูกเพิ่มโดยฉัน

struct timespec
dtotimespec (double sec)
{
  if (! (TYPE_MINIMUM (time_t) < sec)) //underflow case
    return make_timespec (TYPE_MINIMUM (time_t), 0);
  else if (! (sec < 1.0 + TYPE_MAXIMUM (time_t))) //overflow case
    return make_timespec (TYPE_MAXIMUM (time_t), TIMESPEC_HZ - 1);
  else //normal case (looks complex but does nothing technical)
    {
      time_t s = sec;
      double frac = TIMESPEC_HZ * (sec - s);
      long ns = frac;
      ns += ns < frac;
      s += ns / TIMESPEC_HZ;
      ns %= TIMESPEC_HZ;

      if (ns < 0)
        {
          s--;
          ns += TIMESPEC_HZ;
        }

      return make_timespec (s, ns);
    }
}

เนื่องจากtime_tถูกกำหนดให้เป็นประเภทอินทิกรัล (ดู§7.27.1-3) มันเป็นธรรมชาติที่เราถือว่าค่าสูงสุดของประเภทtime_tมีขนาดเล็กกว่าHUGE_VAL(ของประเภทdouble) ซึ่งหมายความว่าเราเข้าสู่กรณีโอเวอร์โฟลว์ (อันที่จริงข้อสมมติฐานนี้ไม่จำเป็นเนื่องจากในทุกกรณีขั้นตอนนั้นเหมือนกัน)

make_timespec()

make_timespec()ผนังสุดท้ายที่เราต้องปีนขึ้นเป็น โชคดีมากมันง่ายมากที่จะอ้างถึงซอร์สโค้ดgnulib / lib / timespec.hก็เพียงพอแล้ว

_GL_TIMESPEC_INLINE struct timespec
make_timespec (time_t s, long int ns)
{
  struct timespec r;
  r.tv_sec = s;
  r.tv_nsec = ns;
  return r;
}

2

ฉันเพิ่งมีความจำเป็นต้องทำเช่นนี้ ฉันมาพร้อมกับฟังก์ชั่นต่อไปนี้ที่จะช่วยให้ bash นอนหลับตลอดไปโดยไม่ต้องเรียกโปรแกรมภายนอก:

snore()
{
    local IFS
    [[ -n "${_snore_fd:-}" ]] || { exec {_snore_fd}<> <(:); } 2>/dev/null ||
    {
        # workaround for MacOS and similar systems
        local fifo
        fifo=$(mktemp -u)
        mkfifo -m 700 "$fifo"
        exec {_snore_fd}<>"$fifo"
        rm "$fifo"
    }
    read ${1:+-t "$1"} -u $_snore_fd || :
}

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

สิ่งนี้สามารถเรียกได้เหมือน / bin / sleep และมันจะเข้าสู่โหมดสลีปตามเวลาที่ร้องขอ เรียกว่าไม่มีพารามิเตอร์มันจะวางตลอดไป

snore 0.1  # sleeps for 0.1 seconds
snore 10   # sleeps for 10 seconds
snore      # sleeps forever

มีรายละเอียดมากเกินไปในบล็อกของฉันที่นี่


1

วิธีการนี้จะไม่ใช้ทรัพยากรใด ๆ ในการทำให้กระบวนการมีชีวิตชีวา

while :; do sleep 1; done & kill -STOP $! && wait $!

ทำให้พังถล่ม

  • while :; do sleep 1; done & สร้างกระบวนการจำลองในพื้นหลัง
  • kill -STOP $! หยุดกระบวนการพื้นหลัง
  • wait $! รอกระบวนการพื้นหลังซึ่งจะถูกบล็อกตลอดไปทำให้กระบวนการพื้นหลังหยุดก่อน

0

แทนที่จะฆ่าตัวจัดการหน้าต่างให้ลองเรียกใช้ตัวจัดการใหม่ด้วย--replaceหรือ-replaceถ้ามี


1
หากฉันใช้ฉันมักจะได้รับการเตือนเช่น--replace another window manager is already runningนั่นไม่สมเหตุสมผลเลยสำหรับฉัน
watain

-2
while :; do read; done

ไม่ต้องรอให้เด็กนอนหลับ


1
กินนี้ถ้าเรื่องนี้ยังคงเกิดขึ้นจะเชื่อมต่อกับstdin ttyหากคุณเรียกใช้กับ< /dev/nullมันลูปไม่ว่าง อาจมีประโยชน์ในบางสถานการณ์ดังนั้นฉันจึงไม่ลงคะแนน
Tino

1
นี่เป็นความคิดที่แย่มากมันแค่กินซีพียูจำนวนมาก
โมฮัมเหม็ Noureldin
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.