Мовчки почати завдання у фоновому режимі


12

Я знаю, що ви можете використовувати це для запуску процесу у фоновому режимі, не отримуючи повідомлення, коли процес виводиться на задній план і коли це робиться так:

(команда &) &> / dev / null

Однак це знімає можливість пастки, коли процес закінчується ( trap child_done CHLD).

Як я можу мати обоє?

Відповіді:


5

спілера завдань може вам допомогти.

Як на freshmeat.net :

Скулер завдань - пакетна система Unix, де спільовані завдання виконуються одна за одною. Кількість завдань, які потрібно запустити одразу, можна встановити в будь-який час. У кожного користувача в кожній системі є своя черга завдань. Завдання виконуються у правильному контексті (заданому записі) з будь-якої оболонки / процесу, і його результати / результати можна легко переглянути. Це дуже корисно, коли ви знаєте, що ваші команди залежать від великої кількості оперативної пам’яті, багато використання диска, дають багато виводу, або з будь-якої причини краще не запускати їх все одночасно, поки ви хочете зберегти ваші ресурси зайняті для отримання максимальної користі. Його інтерфейс дозволяє легко використовувати його в сценаріях.

Задача-шпулер доступна в Debian , Ubuntu та інших дистрибутивах.

Це дозволяє вам мати чергу завдань для запуску та отримувати доступ до їх результатів лише за бажанням.

Наприклад:

$ 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, лише якщо завдання0 успішно виконано).


3

Ось як це зробити в обох {ba,z}sh.

Використання функції допомагає не необхідності зберігати і відновлювати стан zsh«S monitorзмінного шляхом використання 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
}

Використовуючи це так:

trap 'echo child done' CHLD
silent_background sleep 1

Виведе очікуване child doneповідомлення.


див. unix.stackexchange.com/q/456549/4778 для пояснення, сподіваємось.
ctrl-alt-delor

2

Перенаправлення виводу команди здається неактуальним, оскільки повідомлення надсилається оболонкою, коли завдання запускається асинхронно. Точніше, це особливість оболонки (функціональність), пов'язана з контролем роботи .

Ось цитата, що надходить із "Довідкового керівництва Bash", розділу "Контроль роботи", перший розділ.

Оболонка асоціює РОБОТУ з кожним трубопроводом. Він зберігає таблицю поточних виконуваних завдань, яка може бути вказана разом з jobsкомандою. Коли Bash починає роботу асинхронно, він друкує рядок, який виглядає так:

[1] 25647

що вказує на те, що це завдання є завданням № 1 і що ідентифікатор процесу останнього процесу в конвеєрі, пов'язаному з цим завданням, становить 25647. Усі процеси в одному трубопроводі є членами одного завдання. Bash використовує абстракцію JOB як основу для контролю за роботою.

Зауважте, що сценарій оболонки не відображає це сповіщення.

$ cat test
#!/bin/bash

true & echo true
$ ./test
true

У фактах

Зш

Документація Zsh містить подібні вказівки щодо цих повідомлень, див. man 1 zshmiscРозділ "РОБОТИ". Ці сповіщення не відображаються, коли контроль роботи відключений.

МОНІТОР ( , кш: )

    Дозволити контроль роботи. Встановити за замовчуванням в інтерактивній оболонці.

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

Баш

Здається, що Bash завжди відображає напр [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

Це добре працює. Немає необхідності ( ): це робить не потрібну передплату. { }- це лише групування команд.


Це друкує, [2] 49591і [2] + 49591 exit 1 find /usrколи воно не повинно надрукувати жодне з них!
Тиїло

Вибачте, так неправильно зрозуміли ваше запитання.
Жиль Кінот

0

Це давнє запитання, але можлива відповідь (в bash, не перевірена на zsh) полягає у використанні управління роботою в нижній частині: (command & wait)

Примітка: bash пригнічує початкові / кінцеві повідомлення фонових завдань у підпакеті, і немає необхідності в перенаправлення.


Я думаю, ти пропустив частину з пасткою. Наскільки я розумію питання, підпроцес повинен бути запущений, щось буде зроблено під час виконання підпроцесу, а потім, коли підпроцес закінчиться, слід виконати щось інше. За допомогою свого рішення ви запускаєте підпроцес, дочекавшись його в підклітині, а основна оболонка чекає нижньої частини. Це позбавляється від повідомлень, але ви не можете робити щось паралельно.
Рафаель Аренс

Ні, (sleep 5 & wait)затримує 5 секунд.
Том Хейл
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.