W jaki sposób skrypt bash może wykryć, czy działa w tle?


28

Czy istnieje sposób, aby skrypt bash wiedział, czy działa na pierwszym planie, czy w tle, a więc może zachowywać się nieco inaczej w każdym przypadku?


Należy pamiętać, że proces może przejść z pierwszego planu do tła i odwrotnie, ze względu na kontrolę zadań.
Barmar

1
Być może zainteresuje Cię również informacja, czy skrypt działa z interaktywnej powłoki
GnP

Odpowiedzi:


30

Cytowanie man ps:

KODY PAŃSTWA PROCESU

   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

Abyś mógł wykonać proste sprawdzenie:

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

Na pewno cokolwiek przywołanego w ciągu $ (...) samo działa w tle ....? Myślę, że grupa procesowa jest jednak ważna, nie mogę zaprzeczyć, że działa.
Ed Randall

2

Spójrz na plik /etc/bash.bashrc ".

Linia, która ma „$ PS1”. Następnie wykonaj „man bash” i poszukaj tokena PS1.

[ -z "$PS1" ] && return

wychodzi ze skryptu, który nie jest interaktywny.


1

Wszystkie poprzednie rozwiązania obejmują procesy odradzania itp. Bardzo, bardzo brzydkie, ponieważ .bashrcsą wywoływane za każdym razem, gdy uruchamiana jest powłoka bash, stąd te rozwiązania kończą uruchamianie tysiąca procesów.

Znacznie czystsze jest pytanie samego basha: bash ma predefiniowaną zmienną, $-która ma „i”, jeśli działa w interaktywnej powłoce. Na przykład umieszczenie tego w pliku .bashrc jest znacznie czystsze i znacznie tańsze, a co najważniejsze, zawsze będzie działać!

case "$-" in 

    *i*) # interactive shell

    ;;
esac

CZEMU KRZYCZYSZ? To wygląda bardzo, bardzo brzydko ...
Pierre.Vriens,

Proste, prawidłowe rozwiązanie.
Ed Randall

0

Choć można by pomyśleć, że sprawdzenie, czy powłoka jest uruchomiona w trybie interaktywnym, da ten sam rezultat, w praktyce tak nie jest. Koncepcja wygląda podobnie, ale w rzeczywistości jest inna. Możesz uruchomić interaktywny skrypt w danych wejściowych do karmienia w tle, dzięki oczekiwaniu . Możesz także uruchomić skrypt za pomocą bash z -largumentem. Nie możemy zatem polegać na interaktywności bash, aby sprawdzić, czy nasz skrypt jest uruchamiany w tle, czy na pierwszym planie.

Odpowiedź devnull jest zatem poprawna . Aby ustalić, czy proces działa na pierwszym planie, narzędzie ps sprawdza, czy grupa procesów (pgrp) jest taka sama jak identyfikator grupy procesów powiązany z terminalem sterującym sesji (tpgid) i dodaje +znak w danych wyjściowych zgodnie z procesem stan.

Wiedząc o tym, zdecydowanie możemy mieć wersję testową opartą wyłącznie na bashu:

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

W powyższym kodzie wyświetlamy wynik w pliku tekstowym, ponieważ stdoutnie jest on połączony, gdy proces jest uruchomiony w tle.

Zwróć uwagę, że czwarty i ósmy element tabeli odpowiadają odpowiednio pgrpi tpgid( patrz sekcja / proc / [pid] / stat na stronie podręcznika - man 5 proc).

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.