เริ่มงานเงียบ ๆ ในเบื้องหลัง


12

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

(คำสั่ง &) &> / dev / null

อย่างไรก็ตามสิ่งนี้จะลบตัวเลือกเพื่อดักจับเมื่อกระบวนการเสร็จสิ้น ( trap child_done CHLD)

ฉันจะมีทั้งคู่ได้อย่างไร

คำตอบ:


5

ตัวจัดคิวงานอาจช่วยคุณได้

เช่นเดียวกับในfreshmeat.net :

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

ตัวจัดคิวงานพร้อมใช้งานในDebian , Ubuntu และ distros อื่น ๆ

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

ตัวอย่างเช่น:

$ tsp sleep 5
0 
$ tsp sleep 5 
1
$ tsp
ID   State      Output               E-Level  Times(r/u/s)   Command [run=1/1]
2    running    /tmp/ts-out.ZWn6Le                           sleep 5
1    finished   /tmp/ts-out.Fhlcle   0        5.00/0.00/0.01 sleep 5

หากคุณทำงานเป็นจำนวนมากในเบื้องหลังมันจะช่วยคุณได้แน่นอน

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


3

ต่อไปนี้เป็นวิธีทำทั้งสอง{ba,z}shอย่าง

การใช้ฟังก์ชั่นช่วยให้ไม่จำเป็นต้องมีการบันทึกและเรียกคืนสถานะของzsh's ตัวแปรโดยการใช้monitorsetopt local_options

# Run the command given by "$@" in the background
silent_background() {
  if [[ -n $ZSH_VERSION ]]; then  # zsh:  /superuser//a/1285272/365890
    setopt local_options no_notify no_monitor
    "$@" &
  elif [[ -n $BASH_VERSION ]]; then  # bash: /programming//a/27340076/5353461
    { 2>&3 "$@"& } 3>&2 2>/dev/null
  else  # Unknownness - just background it
    "$@" &
  fi
}

ใช้สิ่งนี้ดังนี้:

trap 'echo child done' CHLD
silent_background sleep 1

จะผลิตchild doneข้อความที่คาดหวัง


ดูunix.stackexchange.com/q/456549/4778สำหรับคำอธิบายความหวัง
ctrl-alt-delor

2

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

ที่นี่คำพูดที่มาจาก "คู่มืออ้างอิง Bash" บทที่ "การควบคุมงาน" ส่วนที่หนึ่ง

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

[1] 25647

ระบุว่างานนี้เป็นงานหมายเลข 1 และ ID กระบวนการของกระบวนการสุดท้ายในไปป์ไลน์ที่เชื่อมโยงกับงานนี้คือ 25647 กระบวนการทั้งหมดในขั้นตอนเดียวเป็นสมาชิกของงานเดียวกัน Bash ใช้นามธรรม JOB เป็นพื้นฐานสำหรับการควบคุมงาน

โปรดทราบว่าเชลล์สคริปต์ไม่แสดงการแจ้งเตือนนี้

$ cat test
#!/bin/bash

true & echo true
$ ./test
true

ในข้อเท็จจริง

zsh

เอกสาร Zsh ให้ข้อบ่งชี้ที่คล้ายคลึงกันเกี่ยวกับการแจ้งเตือนเหล่านี้ดูman 1 zshmiscหัวข้อ "งาน" การแจ้งเตือนเหล่านี้จะไม่ปรากฏเมื่อปิดการควบคุมงาน

หน้าจอ ( -m , ksh: -m )

    อนุญาตการควบคุมงาน ตั้งค่าเริ่มต้นในเปลือกโต้ตอบ

zsh_prompt % setopt no_monitor
zsh_prompt % true & echo true
true
zsh_prompt %
zsh_prompt % 

ทุบตี

[1] 25647มันดูเหมือนว่าทุบตีเสมอแสดงเช่น "การแจ้งเตือนครั้งสุดท้าย" เช่น[1]+ Done trueไม่ปรากฏขึ้นเมื่อปิดการควบคุมงาน

bash_prompt $ true & echo true
[1] 25647
true
bash_prompt $ 
[1]+  Done                    true

ปิดใช้งานการควบคุมงาน

bash_prompt $ set +m       # disable job control
bash_prompt $ true & echo true
[1] 25685
bash_prompt $
bash_prompt $

ข้อสรุป

ฉันไม่ทราบว่าปิดการใช้งานการควบคุมงานเพื่อซ่อนการแจ้งเตือนเป็นสิ่งที่ดี?

ทรัพยากร


1

คุณอาจเรียกใช้zshเป็นเชลล์แบบไม่มีการโต้ตอบเพื่อปิดใช้งานการแจ้งเตือนงาน

zsh -c '
   trap "echo trapped child_done" CHLD
   sleep 5 &
   #wait
   sleep 10 # simulate other running cmds
   echo script done
'

0

ดูตัวอย่างต่อไปนี้:

trap 'echo "DONE"' 0
{ find /usr & } &> /dev/null
wait

ที่ใช้งานได้ดี ไม่ต้องการ( ): นั่นทำให้ subshell ไม่จำเป็น { }เป็นเพียงการจัดกลุ่มคำสั่ง


มันพิมพ์ออกมา[2] 49591และ[2] + 49591 exit 1 find /usrเมื่อมันไม่ควรพิมพ์สิ่งเหล่านี้!
Tyilo

ขออภัยเข้าใจคำถามของคุณผิด
Gilles Quenot

0

นี่เป็นคำถามเก่า แต่คำตอบที่เป็นไปได้ (ใน bash, ไม่ทดสอบด้วย zsh) คือการใช้การควบคุมงานใน subshell: (command & wait)

หมายเหตุ: bash ไม่แสดงข้อความงานพื้นหลังเริ่มต้น / สิ้นสุดในเชลล์ย่อยและไม่จำเป็นต้องเปลี่ยนเส้นทาง


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

ไม่(sleep 5 & wait)ล่าช้า 5 วินาที
Tom Hale
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.