Come può uno script bash rilevare se è in esecuzione in background?


28

C'è modo per uno script bash di sapere se è in esecuzione in primo piano o in background, e quindi può comportarsi in modo leggermente diverso in ciascun caso?


Si noti che un processo può spostarsi dal primo piano allo sfondo e viceversa a causa del controllo del lavoro.
Barmar,

1
Potresti anche essere interessato a sapere se lo script è in esecuzione da una shell interattiva
GnP

Risposte:


30

Citando man ps:

CODICI DI STATO DI 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

Quindi potresti eseguire un semplice controllo:

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

Sicuramente qualsiasi cosa invocata in $ (...) è in esecuzione in background ....? Immagino che il gruppo di processo sia la cosa importante, non posso negare che funzioni.
Ed Randall,

2

Guarda il file /etc/bash.bashrc ".

La linea che ha "$ PS1". Quindi fai un "man bash" e cerca il token PS1.

[ -z "$PS1" ] && return

esce da uno script non interattivo.


1

Tutte le soluzioni precedenti riguardano i processi di generazione, ecc. Molto, molto brutto, poiché .bashrcviene chiamato ogni volta che viene lanciata una shell bash, quindi quelle soluzioni finiscono con il lancio di migliaia di processi.

Molto più pulito si sta chiedendo bash: bash ha una variabile predefinita $-che ha "i" se è in esecuzione in una shell interattiva. Ad esempio, metterlo nel tuo .bashrc è molto più pulito e molto più economico e, soprattutto, funzionerà sempre!

case "$-" in 

    *i*) # interactive shell

    ;;
esac

Perché stai urlando? Che sembra molto, molto brutta ...
Pierre.Vriens

Soluzione semplice e corretta.
Ed Randall,

0

Mentre potresti pensare che il controllo se la shell viene eseguita in modalità interattiva darà lo stesso risultato, in pratica non lo è. Il concetto sembra simile ma in realtà è diverso. È possibile eseguire uno script interattivo nell'input di alimentazione in background grazie ad aspettarsi . Inoltre, potresti avviare il tuo script con bash con l' -largomento. Non possiamo quindi fare affidamento sull'interattività bash per verificare se il nostro script viene eseguito in background o in primo piano.

La risposta di devnull è quindi corretta . Per determinare se il processo è in esecuzione in primo piano, l'utilità ps verifica se il gruppo di processi (pgrp) è lo stesso dell'ID del gruppo di processi associato al terminale di controllo della sessione (tpgid) e aggiunge un +segno nell'output in base al processo stato.

Sapendo che, possiamo sicuramente avere una versione bash pura del 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

Nel codice sopra, stiamo producendo il risultato in un file di testo perché stdoutnon è collegato quando un processo viene eseguito in background.

Notare che il 4 ° e l'8 ° elemento della tabella corrispondono rispettivamente a pgrpe tpgid( vedere la sezione / proc / [pid] / stat della pagina man - man 5 proc).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.