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?
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?
Risposte:
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
Quindi potresti eseguire un semplice controllo:
case $(ps -o stat= -p $$) in
*+*) echo "Running in foreground" ;;
*) echo "Running in background" ;;
esac
Tutte le soluzioni precedenti riguardano i processi di generazione, ecc. Molto, molto brutto, poiché .bashrc
viene 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
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' -l
argomento. 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é stdout
non è collegato quando un processo viene eseguito in background.
Notare che il 4 ° e l'8 ° elemento della tabella corrispondono rispettivamente a pgrp
e tpgid
( vedere la sezione / proc / [pid] / stat della pagina man - man 5 proc
).