Как скрипт bash может определить, работает ли он в фоновом режиме?

29

Есть ли способ для bash-скрипта узнать, работает ли он на переднем плане или в фоне, и поэтому он может вести себя немного по-разному в каждом случае?

Дан
источник
Обратите внимание, что процесс может перемещаться с переднего плана на задний план и наоборот из-за управления заданиями.
Бармар
1
Вам также может быть интересно узнать, запущен
GnP

Ответы:

31

Цитирование man ps:

КОДЫ ГОСУДАРСТВЕННОГО ПРОЦЕССА

   Here are the different values that the s, stat and state output
   specifiers (header "STAT" or "S") will display to describe the state of
   a process.
   ...
   +    is in the foreground process group

Таким образом, вы можете выполнить простую проверку:

case $(ps -o stat= -p $$) in
  *+*) echo "Running in foreground" ;;
  *) echo "Running in background" ;;
esac
devnull
источник
Конечно, все, что вызывается в $ (...), само работает в фоновом режиме ....? Я думаю, что группа процессов - важная вещь, не могу отрицать, что она работает.
Эд Рэндалл
2

Посмотрите на файл /etc/bash.bashrc ".

Строка, которая имеет «$ PS1». Затем выполните «man bash» и найдите маркер PS1.

[ -z "$PS1" ] && return

выходит из сценария, который не является интерактивным.

user62612
источник
1

Все предыдущие решения включают процессы порождения и т. Д. Очень, очень уродливо, так как .bashrcвызывается каждый раз, когда запускается оболочка bash, следовательно, эти решения заканчивают запуск тысяч процессов.

Большая часть спрашивает сам bash: bash имеет предопределенную переменную, $-которая имеет «i», если она работает в интерактивной оболочке. Например, поместить это в ваш .bashrc намного чище, намного дешевле и, что самое важное, всегда будет работать!

case "$-" in 

    *i*) # interactive shell

    ;;
esac
user265919
источник
ПОЧЕМУ ТЫ ХОЧЕШЬ? Это выглядит очень, очень некрасиво ...
Pierre.Vriens
Простое, правильное решение.
Эд Рэндалл
Это решение не работает, если вы запускаете скрипт из интерактивной оболочки.
ingroxd
0

Хотя вы можете подумать, что проверка запуска оболочки в интерактивном режиме даст тот же результат, на практике это не так. Концепция выглядит похожей, но на самом деле другая. Вы можете запустить интерактивный скрипт в фоновом режиме ввода, благодаря ожидаемому . Также вы можете запустить ваш скрипт с bash с -lаргументом. Таким образом, мы не можем полагаться на интерактивность bash, чтобы проверить, выполняется ли наш скрипт в фоновом режиме или на переднем плане.

Ответ от Devnull, таким образом, правильный . Чтобы определить, выполняется ли процесс на переднем плане, утилита ps проверяет, совпадает ли группа процессов (pgrp) с идентификатором группы процессов, связанным с управляющим терминалом сеанса (tpgid), и добавляет +знак в выходной файл в соответствии с процессом. штат.

Зная это, мы можем определенно иметь чистую версию теста bash:

#!/usr/bin/env bash

IFS=$' '
retval=($(</proc/$$/stat))
IFS=$' \t\n'
if [[ "${retval[3]}" == "${retval[7]}" ]]; then
    echo "Background" > ./result.txt
else
    echo "Foreground" > ./result.txt
fi
exit

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

Обратите внимание, что 4-й и 8-й элементы таблицы соответственно соответствуют pgrpи tpgid( см. Раздел / proc / [pid] / stat на странице man - man 5 proc).

Wget
источник