Как я мог скрыть стандартный вывод процесса только, когда он работает в фоне?
Например,
test.sh
#!/bin/bash
for i in $(seq 200); do
echo $i
done
Теперь, я запускаю скрипт. Я останавливаю его. Я возвратился, это для тестирования его продолжает бежать. Затем я поместил его на фон, но это продолжает печатать в стандартном выводе, и я не могу продолжать работать. Существует ли способ перенаправить или скрыться, процесс произвел ТОЛЬКО, когда это находится на фоне?
dione@saturno:~$ ./test.sh
1
2
3
^Z
[1]+ Detenido ./test.sh
dione@saturno:~$ fg %1
./test.sh
4
5
6
^Z
[1]+ Detenido ./test.sh
dione@saturno:~$ %1 &
[1]+ ./test.sh &
dione@saturno:~$ 7
8
9
10
11
12
13
14
15
fg
./test.sh
16
17
^C
dione@saturno:~$
Этот сценарий перенаправляет stdout к /dev/null
только если сценарий работает в фоновом режиме:
#!/bin/sh
case "$(ps -o stat= -p $$)" in
*+*) : ;;
*) exec 1>/dev/null ;;
esac
for i in $(seq 200); do
echo $i
done
Ключ здесь то, что ps
stat
поле имеет a +
в нем, когда задание является передним планом. Если +
отсутствует, мы находимся в фоне.
Если Вы хотите иметь в наличии stdout для некоторых вещей, но не других, мы можем создать дескриптор файла 3 для дискреционного вывода и сохранить stdout активный для другого вывода. Сценарий ниже реализует это. Это отправляет вывод цикла в дескриптор файла 3. Описание файла 3 является или stdout, если задание работает на переднем плане или /dev/null
если это работает в фоновом режиме:
#!/bin/sh
case "$(ps -o stat= -p $$)" in
*+*) exec 3<&1 ;;
*) exec 3>/dev/null ;;
esac
for i in $(seq 200); do
echo $i
done >&3
Создайте эту функцию удара:
bkg() { "$@" >/dev/null & }
Затем в любое время то, что Вы хотите к шумной команде, сказать seq 200
, в фоне введите:
bkg seq 200
Команда будет выполнена в фоне, и от его stdout избавятся.
Сделать определение bkg
постоянный, поместите определение в ~/.bashrc
.
Перенаправление вывода рабочего процесса не легко. Но могли бы быть альтернативы, если Вы работаете от запуска:
some_long_runnning_command | tail -n 1000 & pkill -STOP tail
С этим методом, начиная с tail
имеет SIGSTOP
отправленный в него, он ничего не произведет, пока Вы явно не принесете его к приоритетному использованию fg
(или что-то подобное), и пока сценарий не закончился. Корректируйтесь 1000
получить столько строк, сколько Вы хотите.
Лучшая альтернатива могла бы быть grep
:
some_long_runnning_command | grep . --color=never & pkill -STOP sed
Можно предупредить SIGCONT
и SIGSTOP
кому: grep
запустить и остановить вывод, как Вы хотите.
Это может, вероятно, быть объединено с прикреплением открытых дескрипторов файлов от ТАК вопрос, связанный выше (возможно, со сценарием в этом ответе) так, чтобы это могло быть сделано с процессами, уже открытыми.
Если буферизация является действительно проблемой с grep
, как Volker Siegel указывает, затем можно было бы рассмотреть использование более сложного набора команд. Во-первых, отметьте это sort
использование временные файлы, таким образом буферизуя не должно быть проблемой для него. Это будет действовать как комбинация tail
и grep
- ожидание до команды закончено, как tail
, и хранение всего вывода, как grep
. Что-то как:
some_long_runnning_command | awk '{$0=";"$0}1' | sort -k1.1,1.1 --stable | sed 's/^;//' & pkill -STOP sed
Потеря здесь - то, что Вы не можете запустить и остановить вывод по желанию, и существует огромное вычисление, израсходованное в бесполезном sort
, а также работа, израсходованная в добавлении и удалении ;
.
Дальнейшие тесты показывают, что Volker действительно корректен:
Для сценария как (называют его test.sh
):
#! /bin/bash
for i in $(seq 1000000); do echo $i; echo $i > /tmp/log; done
и команда:
./test.sh | grep . --color=never & pkill -STOP grep
число в /tmp/log
застрял в 12 768 (с подобной фигурой для. И с командой
./test.sh | awk '{$0=";"$0}1' | sort -k1.1,1.1 --stable | sed 's/^;//' & pkill -STOP sed
Сценарий работал к завершению (/tmp/log
имел 1000000
) без взгляда от sed
.
Мне все еще не удалось интегрировать это с методом GDB, но этим, как это, может быть сделан функционировать как функцию, подобную John1024. Проблема состоит в том, что у Вас нет хорошего способа знать, закончился ли процесс, так как оболочка только уведомляет Вас, если все задание закончилось. Таким образом, необходимо будет использовать функцию проверки:
function check ()
{
local PROC=${1:-$(jobs -p %%)}
kill -0 $PROC 2>/dev/null && echo "The process is still running." || echo "The process is not running."
}
function bg ()
{
"$@" | awk '{$0=";"$0}1' | sort -k1.1,1.1 --stable | sed 's/^;//' &
local PID=$!
sleep 0.1s
kill -STOP $PID
cat <<EOF
To get the output, do:
kill -CONT $PID
To check if the process has finished, do:
check $(jobs -p %%)
EOF
}
Вы могли перенестись "$@"
в другой функции, которая уведомит Вас, после того как задание сделано, с помощью чего-то как notify-send
или write
.
Это было хорошее осуществление, но в конечном счете самый простой путь состоит в том, чтобы перенаправить к /dev/null
и забудьте вывод: Как перенаправить вывод приложения в предпосылках к/dev/null.