Запуск команд bash в фоновом режиме без задания печати и идентификаторов процессов - PullRequest
57 голосов
/ 07 октября 2011

Запустить процесс в фоновом режиме в bash довольно просто.

$ echo "Hello I'm a background task" &
[1] 2076
Hello I'm a background task
[1]+  Done                    echo "Hello I'm a background task"

Однако вывод является подробным. В первой строке напечатан идентификатор задания и идентификатор процесса фоновой задачи, затем у нас есть вывод команды, наконец, у нас есть идентификатор задания, его статус и команда, которая запустила задание.

Есть ли способ подавить вывод при выполнении фоновой задачи, чтобы вывод выглядел точно так же, как без амперсанда в конце? То есть:

$ echo "Hello I'm a background task" &
Hello I'm a background task

Причина, по которой я спрашиваю, состоит в том, что я хочу запустить фоновый процесс как часть команды завершения табуляции, поэтому вывод этой команды должен быть непрерывным, чтобы иметь какой-либо смысл.

Ответы [ 8 ]

70 голосов
/ 07 октября 2011

Не связано с завершением, но вы можете подавить этот вывод, поместив вызов в подоболочку:

(echo "Hello I'm a background task" &)
11 голосов
/ 07 октября 2011

В некоторых более новых версиях bash и в ksh93 его можно окружить вложенной оболочкой или группой процессов (т. Е. { ... }).

/home/shellter $ { echo "Hello I'm a background task" & } 2>/dev/null
Hello I'm a background task
/home/shellter $
9 голосов
/ 14 апреля 2014

Опираясь на ответ @ shellter, это сработало для меня:

tyler@Tyler-Linux:~$ { echo "Hello I'm a background task" & disown; } 2>/dev/null; sleep .1;
Hello I'm a background task
tyler@Tyler-Linux:~$

Я не знаю причины этого, но я вспомнил из старого поста, что disown не позволяет bash выводить идентификаторы процесса.

6 голосов
/ 07 декабря 2014

Основываясь на приведенном выше ответе, если вам нужно разрешить stderr пройти из команды:

f() { echo "Hello I'm a background task" >&2; }
{ f 2>&3 &} 3>&2 2>/dev/null
5 голосов
/ 27 июня 2018

Исходя из этого ответа , я придумал более сжатый и правильный:

silent_background() {
    { 2>&3 "$@"& } 3>&2 2>/dev/null
    disown &>/dev/null  # Prevent whine if job has already completed
}
silent_background date
4 голосов
/ 21 марта 2017

Извините за ответ на старый пост, но я полагаю, что это полезно для других, и это первый ответ в Google.

У меня возникла проблема с этим методом (подоболочки) и я использовал 'wait'. Однако, когда я запускал ее внутри функции, я смог сделать это:

function a {
    echo "I'm background task $1"
    sleep 5
}

function b {
    for i in {1..10}; do
        a $i &
    done
    wait
} 2>/dev/null

И когда я запускаю его:

$ b
I'm background task 1
I'm background task 3
I'm background task 2
I'm background task 4
I'm background task 6
I'm background task 7
I'm background task 5
I'm background task 9
I'm background task 8
I'm background task 10

И у меня есть задержка в 5 секунд, прежде чем я получу свою подсказку.

4 голосов
/ 13 июня 2016

Попробуйте:

user@host:~$ read < <( echo "Hello I'm a background task" & echo $! )
user@host:~$ echo $REPLY
28677

И вы скрыли как выход , так и PID . Обратите внимание, что вы все равно можете получить PID из $ REPLY

1 голос
/ 26 сентября 2017

Решение для подоболочки работает, но я также хотел иметь возможность ждать фоновых заданий (и не иметь сообщения «Готово» в конце).$! из подоболочки не является ожидаемым в текущей интерактивной оболочке.Единственное решение, которое мне помогло, - это использовать собственную функцию ожидания, которая очень проста:

myWait() {
  while true; do
    sleep 1; STOP=1
    for p in $*; do
      ps -p $p >/dev/null && STOP=0 && break
    done
    ((STOP==1)) && return 0
  done
}

i=0
((i++)); p[$i]=$(do_whatever1 & echo $!)
((i++)); p[$i]=$(do_whatever2 & echo $!)
..
myWait ${p[*]}

Достаточно просто.

...