¿Cómo puede un script bash detectar si se está ejecutando en segundo plano?

28

¿Hay alguna forma de que un script bash sepa si se está ejecutando en primer plano o en segundo plano, y para que pueda comportarse de manera ligeramente diferente en cada caso?

dan
fuente
Tenga en cuenta que un proceso puede pasar de primer plano a segundo plano y viceversa debido al control del trabajo.
Barmar
1
También puede interesarle saber si el script se ejecuta desde un shell interactivo
GnP

Respuestas:

30

Citando man ps:

CÓDIGOS ESTATALES DE PROCESO

   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

Para que pueda realizar una comprobación simple:

case $(ps -o stat= -p $$) in
  *+*) echo "Running in foreground" ;;
  *) echo "Running in background" ;;
esac
devnull
fuente
¿Seguramente todo lo invocado dentro de $ (...) se está ejecutando en segundo plano ...? Sin embargo, supongo que el grupo de procesos es lo importante, no puedo negar que funciona.
Ed Randall
2

Mire el archivo /etc/bash.bashrc ".

La línea que tiene "$ PS1". Luego haz un "man bash" y busca el token PS1.

[ -z "$PS1" ] && return

sale de un script que no es interactivo.

usuario62612
fuente
1

Todas las soluciones anteriores implican procesos de desove, etc. Muy, muy feo, ya que .bashrcse llama cada vez que se inicia un bash shell, por lo tanto, esas soluciones terminan lanzando miles de procesos.

Mucho más limpio es preguntar bash en sí: bash tiene una variable predefinida $-que tiene "i" si se ejecuta en un shell interactivo. Por ejemplo, poner esto en su .bashrc es mucho más limpio y mucho más barato y, lo más importante, ¡siempre funcionará!

case "$-" in 

    *i*) # interactive shell

    ;;
esac
usuario265919
fuente
¿PORQUE ESTAS GRITANDO? Eso se ve muy, muy feo ...
Pierre.Vriens
Solución simple y correcta.
Ed Randall
0

Si bien podría pensar que verificar si el shell se ejecuta en modo interactivo dará el mismo resultado, en la práctica, esto no lo es. El concepto se ve similar pero en realidad es diferente. Puede ejecutar un script interactivo en la entrada de alimentación en segundo plano gracias a esperar . Además, puede iniciar su script con bash con el -largumento. Por lo tanto, no podemos confiar en la interactividad bash para verificar si nuestro script se ejecuta en segundo plano o en primer plano.

La respuesta de devnull es, por lo tanto, correcta . Para determinar si el proceso se está ejecutando en primer plano, la utilidad ps comprueba si el grupo de proceso (pgrp) es el mismo que el ID del grupo de proceso asociado con el terminal de control de la sesión (tpgid) y agrega un +signo en la salida de acuerdo con el proceso estado.

Sabiendo eso, definitivamente podemos tener una versión pura de bash de la prueba:

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

En el código anterior, estamos generando el resultado en un archivo de texto porque stdoutno está conectado cuando un proceso se ejecuta en segundo plano.

Tenga en cuenta los días 4 y los elementos 8 de la tabla corresponden respectivamente a pgrpy tpgid( ver el proc / [pid] / / stat sección de la página hombre - man 5 proc).

wget
fuente