Cicho uruchom zadanie w tle

12

Wiem, że możesz tego użyć, aby uruchomić proces w tle, bez otrzymywania powiadomienia, gdy proces zostanie umieszczony w tle i kiedy zostanie to zrobione w następujący sposób:

(Command &) &> / dev / null

Jednak usuwa to opcję pułapki po zakończeniu procesu ( trap child_done CHLD).

Jak mogę mieć oba?

Tyilo
źródło

Odpowiedzi:

5

bufor zadań może ci pomóc.

Jak w freshmeat.net :

bufor zadań to system wsadowy w systemie Unix, w którym buforowane zadania są uruchamiane jeden po drugim. Ilość zadań do uruchomienia na raz można ustawić w dowolnym momencie. Każdy użytkownik w każdym systemie ma własną kolejkę zadań. Zadania są uruchamiane we właściwym kontekście (w kolejce) z dowolnej powłoki / procesu, a jego wyniki / wyniki można łatwo obejrzeć. Jest to bardzo przydatne, gdy wiesz, że twoje polecenia zależą od dużej ilości pamięci RAM, dużej ilości miejsca na dysku, dają dużo danych wyjściowych lub z jakiegokolwiek powodu lepiej nie uruchamiać ich wszystkich jednocześnie, podczas gdy chcesz zachować twoje zasoby są zajęte dla maksymalnego wykorzystania. Jego interfejs pozwala łatwo używać go w skryptach.

Bufor zadań jest dostępny w Debianie , Ubuntu i innych dystrybucjach.

Pozwala na uruchomienie kolejki zadań i dostęp do ich wyników na żądanie.

Na przykład:

$ 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

Jeśli wykonujesz wiele zadań w tle, na pewno ci to pomoże.

Możesz je uruchamiać sekwencyjnie lub w ustalonej liczbie gniazd. Można również ustalić zależności między zadaniami (uruchom zadanie 1 tylko wtedy, gdy zadanie0 zakończyło się pomyślnie).

Raúl Salinas-Monteagudo
źródło
3

Oto jak to zrobić w obu przypadkach {ba,z}sh.

Korzystanie z funkcji pomaga nie potrzebują, aby zapisać i przywrócić stan zsh„s monitorzmiennej przy użyciu 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
}

Używając tego w następujący sposób:

trap 'echo child done' CHLD
silent_background sleep 1

Wyprodukuje oczekiwany child donekomunikat.

Tom Hale
źródło
2

Przekierowanie danych wyjściowych polecenia wydaje się być nieistotne, ponieważ powiadomienie jest wysyłane przez powłokę, gdy zadanie jest uruchamiane asynchronicznie. Mówiąc dokładniej, jest to funkcja powłoki (funkcja) związana z kontrolą zadań .

Tutaj cytat z „Bash Reference Manual”, rozdział „Job Job”, rozdział pierwszy.

Powłoka wiąże zadanie z każdym potokiem. Przechowuje tabelę aktualnie wykonywanych zadań, która może być wymieniona w jobspoleceniu. Gdy Bash uruchamia zadanie asynchronicznie, drukuje linię, która wygląda następująco:

[1] 25647

wskazując, że to zadanie jest zadaniem nr 1 i że identyfikator procesu ostatniego procesu w potoku powiązanym z tym zadaniem to 25647. Wszystkie procesy w jednym potoku są członkami tego samego zadania. Bash używa abstrakcji JOB jako podstawy kontroli zadań.

Zauważ, że skrypt powłoki nie wyświetla tego powiadomienia.

$ cat test
#!/bin/bash

true & echo true
$ ./test
true

W rzeczywistości

Zsh

Dokumentacja Zsh zawiera podobne informacje na temat tych powiadomień, patrz man 1 zshmiscsekcja „ZADANIA”. Te powiadomienia nie są wyświetlane, gdy kontrola zadań jest wyłączona.

MONITOR ( -m , ksh: -m )

    Zezwalaj na kontrolę zadań. Ustawiony domyślnie w interaktywnej powłoce.

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

Grzmotnąć

Wygląda na to, że Bash zawsze wyświetla np [1] 25647. „Ostateczne powiadomienie” np. [1]+ Done trueNie jest wyświetlane, gdy kontrola zadań jest wyłączona.

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

Kontrola zadań wyłączona

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

Wniosek

Nie wiem, czy wyłączenie kontroli zadań w celu ukrycia powiadomień jest dobrą rzeczą?

Zasoby

Fólkvangr
źródło
1

Możesz wywołać zshjako nieinteraktywną powłokę, aby wyłączyć powiadomienia o zadaniach.

zsh -c '
   trap "echo trapped child_done" CHLD
   sleep 5 &
   #wait
   sleep 10 # simulate other running cmds
   echo script done
'
nad
źródło
0

Zobacz następujący przykład:

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

To działa dobrze. Nie ma potrzeby ( ): tworzy niepotrzebną podpowłokę. { }to tylko polecenia grupujące.

Gilles Quenot
źródło
To drukuje, [2] 49591a [2] + 49591 exit 1 find /usrkiedy nie powinno drukować żadnego z nich!
Tyilo,
Niestety, źle zrozumiałem twoje pytanie.
Gilles Quenot
0

To stare pytanie, ale możliwą odpowiedzią (w bash, nie testowane z zsh) jest użycie kontroli zadań w podpowłoce: (command & wait)

Uwaga: bash pomija początkowe / końcowe komunikaty zadań w tle w podpowłoce i nie ma potrzeby przekierowywania.

Philippe
źródło
Myślę, że tęskniłeś za pułapką. O ile rozumiem pytanie, że podproces powinien zostać uruchomiony, coś zostanie zrobione podczas wykonywania supprocesu, a następnie, gdy podproces zakończy się, coś innego powinno zostać wykonane. W swoim rozwiązaniu uruchamiasz podproces, czekając na to w podpowłoce, a główna powłoka czeka na podpowłokę. Pozbywa się to wiadomości, ale nie możesz zrobić czegoś równolegle.
Raphael Ahrens,
Nie, (sleep 5 & wait)opóźnia 5 sekund.
Tom Hale