Подтвердить что ты не робот

Bash: отключить фоновый режим

Гуру оболочки,

У меня есть оболочка bash script, в которой я запускаю функцию фона, скажем foo(), чтобы отобразить индикатор выполнения для скучной и длинной команды:

foo()
{
    while [ 1 ]
    do
        #massively cool progress bar display code
        sleep 1
    done
}

foo &
foo_pid=$!

boring_and_long_command
kill $foo_pid >/dev/null 2>&1
sleep 10

теперь, когда foo умирает, я вижу следующий текст:

/home/user/script: line XXX: 30290 Killed                  foo

Это полностью разрушает удивительность моего, в противном случае массивного охлаждения, индикатора выполнения.

Как мне избавиться от этого сообщения?

4b9b3361

Ответ 1

kill $foo_pid
wait $foo_pid 2>/dev/null

Кстати, я не знаю о вашем массовом прохладном баре прогресса, но вы видели Pipe Viewer (pv)? http://www.ivarch.com/programs/pv.shtml

Ответ 2

Просто натолкнулся на это сам, и осознанное "отречение" - это то, что мы ищем.

foo &
foo_pid=$!
disown

boring_and_long_command
kill $foo_pid
sleep 10

Сообщение о смерти печатается, потому что процесс все еще находится в списке оболочек наблюдаемых "заданий". Команда disown удалит последний из созданных процессов из этого списка, чтобы отладочное сообщение не было сгенерировано, когда оно было убито, даже с SIGKILL (-9).

Ответ 3

Попробуйте заменить строку kill $foo_pid >/dev/null 2>&1 на строку:

(kill $foo_pid 2>&1) >/dev/null

Обновление

Этот ответ неверен по причине, объясненной @mklement0 в его комментарии:

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

Ответ 4

Это решение, с которым я столкнулся с подобной проблемой (хотел показать временную метку во время длительных процессов). Это реализует функцию killsub, которая позволяет вам убить любую подоболочку тихо, пока вы знаете pid. Обратите внимание, что команды trap важны для включения: в случае прерывания script, подоболочка не будет продолжать работать.

foo()
{
    while [ 1 ]
    do
        #massively cool progress bar display code
        sleep 1
    done
}

#Kills the sub process quietly
function killsub() 
{

    kill -9 ${1} 2>/dev/null
    wait ${1} 2>/dev/null

}

foo &
foo_pid=$!

#Add a trap incase of unexpected interruptions
trap 'killsub ${foo_pid}; exit' INT TERM EXIT

boring_and_long_command

#Kill foo after finished
killsub ${foo_pid}

#Reset trap
trap - INT TERM EXIT

Ответ 5

Этот "взлом", похоже, работает:

# Some trickery to hide killed message
exec 3>&2          # 3 is now a copy of 2
exec 2> /dev/null  # 2 now points to /dev/null
kill $foo_pid >/dev/null 2>&1
sleep 1            # sleep to wait for process to die
exec 2>&3          # restore stderr to saved
exec 3>&-          # close saved version

и он был вдохновлен здесь. Мировой порядок восстановлен.

Ответ 6

Добавить в начале функции:

trap 'exit 0' TERM

Ответ 7

В отношении использования "wait": это лучший ответ, который я думаю. См. fooobar.com/questions/121227/... для примера того, как это выглядит/работает.

Ответ 8

Другой способ сделать это:

    func_terminate_service(){

      [[ "$(pidof ${1})" ]] && killall ${1}
      sleep 2
      [[ "$(pidof ${1})" ]] && kill -9 "$(pidof ${1})" 

    }

назовите его

    func_terminate_service "firefox"

Ответ 9

Еще один способ отключить уведомления о работе - это включить в команду sh -c 'cmd &' команду для создания вашей команды.

#!/bin/bash

foo()
{
   while [ 1 ]
   do
       sleep 1
   done
}

#foo &
#foo_pid=$!

export -f foo
foo_pid=`sh -c 'foo & echo ${!}' | head -1`

# if shell does not support exporting functions (export -f foo)
#arg1='foo() { while [ 1 ]; do sleep 1; done; }'
#foo_pid=`sh -c 'eval "$1"; foo & echo ${!}' _ "$arg1" | head -1`


sleep 3
echo kill ${foo_pid}
kill ${foo_pid}
sleep 3
exit

Ответ 10

Вы можете использовать set +m прежде, чтобы подавить это. Больше информации об этом здесь