Выполнение команд bash в фоновом режиме без печати идентификаторов заданий и процессов

запустить процесс в фоновом режиме в 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

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

8 ответов


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

(echo "Hello I'm a background task" &)

вам придется окружить его под-оболочкой или группой процессов (т. е. { ... }).

/home/shellter $ { echo "Hello I'm a background task" & } 2>/dev/null
Hello I'm a background task
/home/shellter $

IHTH

редактировать

как подсказано @ Mark 's downvote, я исследовал, что это не работает правильно в bash. Это работает, как показано в разделе ksh93.

занят прямо сейчас, но я обновлю этот ответ тем, что я включил в комментарии к этому и ответу @Tizord, но я не вижу простого ответа на то, как перенаправить std-err от фоновой задачи. (Вероятно, это возможно с exec манипуляции)


основываясь на ответе @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:~$

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


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

f() { echo "Hello I'm a background task" >&2; }
{ f 2>&3 &} 3>&2 2>/dev/null

попробуй:

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

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


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

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

function a {
    echo "I'm background task "
    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 секунд, прежде чем я получу приглашение обратно.


решение subshell работает, но я также хотел иметь возможность ждать фоновых заданий (и не иметь сообщения "готово" в конце). $! from a subshell не является "waitable" в текущей интерактивной оболочке. Единственное решение, которое сработало для меня, - использовать мою собственную функцию ожидания, которая очень проста:

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[*]}

достаточно легко.


на основе ответ, Я придумал более краткое и правильное:

silent_background() {
    { 2>&3 "$@"& } 3>&2 2>/dev/null
    disown &>/dev/null  # Prevent whine if job has already completed
}
silent_background date