Выполнение команд 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

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

8 51

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

edit

как подсказано @ 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 не является "ожидаемым" в текущей интерактивной оболочке. Единственным решением, которое сработало для меня, было использовать мою собственную функцию ожидания, которая очень проста:

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