Âm thầm bắt đầu nhiệm vụ trong nền


12

Tôi biết rằng bạn có thể sử dụng điều này để bắt đầu một quá trình trong nền, mà không nhận được thông báo khi quá trình được đặt trong nền và khi nó được thực hiện như vậy:

(lệnh &) &> / dev / null

Tuy nhiên, điều này loại bỏ tùy chọn để bẫy khi quá trình kết thúc ( trap child_done CHLD).

Làm thế nào tôi có thể có cả hai?

Câu trả lời:


5

bộ đệm nhiệm vụ có thể giúp bạn.

Như trong Freshmeat.net :

bộ đệm tác vụ là một hệ thống bó Unix, trong đó các tác vụ được bộ đệm chạy lần lượt. Số lượng công việc để chạy cùng một lúc có thể được đặt bất cứ lúc nào. Mỗi người dùng trong mỗi hệ thống có hàng đợi công việc riêng của mình. Các tác vụ được chạy trong ngữ cảnh chính xác (của enqueue) từ bất kỳ shell / process nào, và kết quả / kết quả của nó có thể dễ dàng được xem. Nó rất hữu ích khi bạn biết rằng các lệnh của bạn phụ thuộc vào rất nhiều RAM, sử dụng nhiều đĩa, cho nhiều đầu ra hoặc vì bất kỳ lý do gì tốt hơn là không chạy tất cả chúng cùng một lúc, trong khi bạn muốn giữ tài nguyên của bạn bận rộn cho benfit tối đa. Giao diện của nó cho phép sử dụng nó dễ dàng trong các kịch bản.

Bộ đệm tác vụ có sẵn trong Debian , Ubuntu và các bản phân phối khác.

Nó cho phép bạn có một hàng các tác vụ để chạy và truy cập các kết quả đầu ra của chúng theo ý muốn.

Ví dụ:

$ 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

Nếu bạn điều hành nhiều công việc trong nền, nó chắc chắn sẽ giúp bạn.

Bạn có thể chạy chúng tuần tự hoặc trong một số lượng vị trí đặt trước. Bạn cũng có thể thiết lập các phụ thuộc giữa các tác vụ (chỉ chạy task1 nếu task0 hoàn thành thành công).


3

Đây là cách để làm điều đó trong cả hai {ba,z}sh.

Sử dụng một chức năng giúp không cần phải lưu và khôi phục lại tình trạng zshcủa monitorbiến bằng cách sử dụng setopt 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
}

Sử dụng như sau:

trap 'echo child done' CHLD
silent_background sleep 1

Sẽ tạo ra child donethông điệp mong đợi .


xem unix.stackexchange.com/q/456549/4778 để biết giải thích, hy vọng.
ctrl-alt-delor

2

Việc chuyển hướng đầu ra lệnh dường như không liên quan vì thông báo được gửi bởi trình bao khi công việc được bắt đầu không đồng bộ. Chính xác hơn, đó là một tính năng shell (fonctionality) liên quan đến kiểm soát công việc .

Ở đây, một trích dẫn xuất phát từ "Hướng dẫn tham khảo Bash", chương "Kiểm soát công việc", phần một.

Shell liên kết một JOB với mỗi đường ống. Nó giữ một bảng các công việc hiện đang thực thi, có thể được liệt kê với jobslệnh. Khi Bash bắt đầu một công việc không đồng bộ, nó sẽ in một dòng giống như:

[1] 25647

chỉ ra rằng công việc này là công việc số 1 và ID tiến trình của quy trình cuối cùng trong đường ống liên quan đến công việc này là 25647. Tất cả các quy trình trong một đường ống dẫn đều là thành viên của cùng một công việc. Bash sử dụng sự trừu tượng JOB làm cơ sở để kiểm soát công việc.

Lưu ý rằng tập lệnh shell không hiển thị thông báo này.

$ cat test
#!/bin/bash

true & echo true
$ ./test
true

Thực ra

Zsh

Tài liệu Zsh cung cấp các chỉ dẫn tương tự về các thông báo này, xem man 1 zshmiscphần "CÔNG VIỆC". Các thông báo này không được hiển thị khi kiểm soát công việc bị vô hiệu hóa.

GIÁM SÁT ( -m , ksh: -m )

    Cho phép kiểm soát công việc. Đặt theo mặc định trong vỏ tương tác.

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

Bash

Dường như Bash luôn hiển thị ví dụ [1] 25647. Ví dụ "thông báo cuối cùng" [1]+ Done truekhông được hiển thị khi điều khiển công việc bị tắt.

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

Kiểm soát công việc bị vô hiệu hóa

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

Phần kết luận

Tôi không biết nếu vô hiệu hóa kiểm soát công việc để ẩn thông báo là một điều tốt?

Tài nguyên


1

Bạn có thể gọi zshnhư một vỏ không tương tác để vô hiệu hóa thông báo công việc.

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

0

Xem ví dụ sau:

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

Điều đó làm việc tốt. Không cần ( ): điều đó làm cho một subshell không cần thiết. { }chỉ là nhóm lệnh.


Đó là in [2] 49591[2] + 49591 exit 1 find /usr, khi nó nên in cả hai!
Tyilo

Xin lỗi, hiểu nhầm câu hỏi của bạn như vậy.
Gilles Quenot

0

Đây là một câu hỏi cũ, nhưng một câu trả lời có thể (trong bash, không được kiểm tra với zsh) là sử dụng điều khiển công việc trong subshell: (command & wait)

Lưu ý: bash ngăn chặn các thông báo công việc bắt đầu / kết thúc trong lớp con và không cần chuyển hướng.


Tôi nghĩ rằng bạn đã bỏ lỡ một phần với cái bẫy. Theo như tôi hiểu câu hỏi thì quá trình con nên được bắt đầu, một cái gì đó sẽ được thực hiện trong khi siêu tiến trình thực thi và sau đó khi quá trình con kết thúc, một thứ khác sẽ được thực thi. Với giải pháp của bạn, bạn bắt đầu tiến trình con chờ nó trong lớp con và lớp vỏ chính chờ lớp con. Điều này được loại bỏ các tin nhắn, nhưng bạn không thể làm điều gì đó song song.
Raphael AhDR

Không, (sleep 5 & wait)trì hoãn 5 giây.
Tom Hale
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.