¿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?
¿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?
Respuestas:
Citando 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
Para que pueda realizar una comprobación simple:
case $(ps -o stat= -p $$) in
*+*) echo "Running in foreground" ;;
*) echo "Running in background" ;;
esac
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.
Todas las soluciones anteriores implican procesos de desove, etc. Muy, muy feo, ya que .bashrc
se 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
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 -l
argumento. 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 stdout
no 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 pgrp
y tpgid
( ver el proc / [pid] / / stat sección de la página hombre - man 5 proc
).