Como um script bash pode detectar se está sendo executado em segundo plano?

28

Existe uma maneira de um script bash saber se está sendo executado em primeiro plano ou em segundo plano e, portanto, pode se comportar de maneira ligeiramente diferente em cada caso?

dan
fonte
Observe que um processo pode passar do primeiro plano para o segundo plano e vice-versa devido ao controle do trabalho.
Barmar
1
Você também pode estar interessado em saber se o script está sendo executado a partir de um shell interativo
GnP

Respostas:

30

Citação man ps:

CÓDIGOS DO ESTADO DO PROCESSO

   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

Então você pode executar uma verificação simples:

case $(ps -o stat= -p $$) in
  *+*) echo "Running in foreground" ;;
  *) echo "Running in background" ;;
esac
devnull
fonte
Certamente, qualquer coisa invocada dentro de $ (...) está sendo executada em segundo plano ....? Acho que o grupo de processos é o mais importante, não posso negar que funciona.
Ed Randall
2

Veja o arquivo /etc/bash.bashrc ".

A linha que tem "$ PS1". Então faça um "man bash" e procure o token PS1.

[ -z "$PS1" ] && return

sai de um script que não é interativo.

user62612
fonte
1

Todas as soluções anteriores envolvem processos de geração, etc. Muito, muito feio, já que .bashrcé chamado toda vez que um bash shell é iniciado, portanto, essas soluções acabam lançando milhares de processos.

Muito mais limpo é perguntar ao próprio bash: o bash possui uma variável predefinida $-que possui "i" se estiver sendo executada em um shell interativo. Por exemplo, colocar isso no seu .bashrc é muito mais limpo e muito mais barato e, o mais importante, sempre funcionará!

case "$-" in 

    *i*) # interactive shell

    ;;
esac
user265919
fonte
POR QUE VOCÊ ESTÁ GRITANDO? Isso parece muito, muito feio ...
Pierre.Vriens
Solução simples e correta.
Ed Randall
0

Embora você possa pensar que verificar se o shell é executado no modo interativo dará o mesmo resultado, na prática, isso não acontece. O conceito parece semelhante, mas é realmente diferente. Você pode executar um script interativo na entrada de alimentação em segundo plano, graças ao esperado . Além disso, você pode iniciar seu script com bash com o-l argumento Portanto, não podemos confiar na interatividade do bash para verificar se nosso script é executado em segundo plano ou em primeiro plano.

A resposta do devnull está correta . Para determinar se o processo está sendo executado em primeiro plano, o utilitário ps verifica se o grupo de processos (pgrp) é igual ao ID do grupo de processos associado ao terminal de controle da sessão (tpgid) e adiciona um +sinal na saída de acordo com o processo Estado.

Sabendo disso, podemos definitivamente ter uma versão pura do bash do teste:

#!/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

No código acima, estamos produzindo o resultado em um arquivo de texto porque stdoutnão está conectado quando um processo é executado em segundo plano.

Observe que o quarto e o oitavo elementos da tabela correspondem respectivamente a pgrpe tpgid( consulte a seção / proc / [pid] / stat da página de manual - man 5 proc).

wget
fonte