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?
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?
Odpowiedzi:
Cytowanie 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
Abyś mógł wykonać proste sprawdzenie:
case $(ps -o stat= -p $$) in
*+*) echo "Running in foreground" ;;
*) echo "Running in background" ;;
esac
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.
Wszystkie poprzednie rozwiązania obejmują procesy odradzania itp. Bardzo, bardzo brzydkie, ponieważ .bashrc
są 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
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 -l
argumentem. 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ż stdout
nie jest on połączony, gdy proces jest uruchomiony w tle.
Zwróć uwagę, że czwarty i ósmy element tabeli odpowiadają odpowiednio pgrp
i tpgid
( patrz sekcja / proc / [pid] / stat na stronie podręcznika - man 5 proc
).