Comment un script bash peut-il détecter s'il s'exécute en arrière-plan?


29

Existe-t-il un moyen pour un script bash de savoir s'il s'exécute au premier plan ou en arrière-plan, et qu'il peut donc se comporter légèrement différemment dans chaque cas?


Notez qu'un processus peut passer du premier plan à l'arrière-plan et vice versa en raison du contrôle des tâches.
Barmar

1
Vous pouvez également être intéressé à savoir si le script s'exécute à partir d'un shell interactif
GnP

Réponses:


31

Citant man ps:

CODES D'ÉTAT DU PROCESSUS

   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

Vous pouvez donc effectuer une simple vérification:

case $(ps -o stat= -p $$) in
  *+*) echo "Running in foreground" ;;
  *) echo "Running in background" ;;
esac

Certes, tout ce qui est invoqué dans $ (...) s'exécute en arrière-plan ....? Je suppose que le groupe de processus est la chose importante cependant, je ne peux pas nier que cela fonctionne.
Ed Randall

2

Regardez le fichier /etc/bash.bashrc ".

La ligne contenant "$ PS1". Ensuite, faites un "man bash" et recherchez le jeton PS1.

[ -z "$PS1" ] && return

quitte un script qui n'est pas interactif.


1

Toutes les solutions précédentes impliquent des processus d'apparition, etc. Très, très moche, car .bashrcest appelé à chaque lancement d'un shell bash, donc ces solutions finissent par lancer des milliers de processus.

Beaucoup plus propre demande bash lui-même: bash a une variable prédéfinie $-qui a "i" si elle s'exécute dans un shell interactif. Par exemple, mettre cela dans votre .bashrc est beaucoup plus propre et beaucoup moins cher et, surtout, cela fonctionnera toujours!

case "$-" in 

    *i*) # interactive shell

    ;;
esac

POURQUOI CRIEZ-VOUS? Ça a l' air très, très moche ...
Pierre.Vriens

Solution simple et correcte.
Ed Randall

Cette solution ne fonctionne pas si vous lancez le script à partir d'un shell interactif.
ingroxd

0

Alors que vous pourriez penser que vérifier si le shell est exécuté en mode interactif donnera le même résultat, en pratique, ce n'est pas le cas. Le concept semble similaire mais est en réalité différent. Vous pouvez exécuter un script interactif dans l' entrée d'alimentation en arrière-plan grâce à expect . Vous pouvez également lancer votre script avec bash avec l' -largument. Nous ne pouvons donc pas compter sur l'interactivité bash pour vérifier si notre script est exécuté en arrière-plan ou au premier plan.

La réponse de devnull est donc correcte . Pour déterminer si le processus s'exécute au premier plan, l'utilitaire ps vérifie si le groupe de processus (pgrp) est le même que l'ID de groupe de processus associé au terminal de contrôle de la session (tpgid) et ajoute un +signe dans la sortie en fonction du processus Etat.

Sachant cela, nous pouvons certainement avoir une version pure bash du test:

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

Dans le code ci-dessus, nous générons le résultat dans un fichier texte car il stdoutn'est pas connecté lorsqu'un processus est exécuté en arrière-plan.

Veuillez noter que les 4e et 8e éléments du tableau correspondent respectivement à pgrpet tpgid( voir la section / proc / [pid] / stat de la page de manuel - man 5 proc).

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.