Bash sposób, aby sprawdzić, czy proces działa już w tle (i pomiń na nim ponowne wykonanie)?


11

Czy mogę utworzyć linię poleceń bash, która uruchamia określone polecenie, tylko jeśli proces jeszcze nie działa (w tle)?

Jak sprawdzić *, jeśli polecenie jest już uruchomione?

(więc mogę dodać kolejne polecenie z &&pomiędzy nimi, aby następne było wykonywane tylko wtedy, gdy pierwsze jest prawdziwe).

*: testuj, ustalaj, odkrywaj, dowiedz się


3
ps -ef | grep -v grep | grep "process_name" || run_command_here
Rahul Patil

1
@RahulPatil możesz użyć pgrep "process_name"zamiastps | grep | grep
pośpiesz

hmm, zapominam, że ..: D
Rahul Patil

1
Dlaczego nie użyjesz pliku „blokady”, a gdy uruchomisz go po raz drugi, uruchomi się on tylko wtedy, gdy plik blokady zniknie.
BitsOfNix

najlepszy sposób, aby sprawdzić, czy proces istnieje: stackoverflow.com/questions/3043978/...
Trevor Boyd Smith

Odpowiedzi:



3

Od czasu do czasu korzystałem z tej techniki:

$ pgrep <process name> || <process name>

Wcześniej pgreprobiono to w ten sposób:

$ ps -eaf | grep -q <[p]rocess name> || <process name>

przykład

Trochę z tym [p]sprawia, że ​​tak się grepnie stanie.

$ ps -eaf | grep -q [s]leep || sleep 10

2

Może to być trudne, ponieważ możesz mieć osobne instancje tego samego procesu, które działają niezależnie. Na przykład serwery nasłuchujące na różnych portach lub usługi działające jako różni użytkownicy. Aby rozróżnić te instancje, musisz przypisać każdemu z nich unikalny tag. Znacznik jest często plikiem, ale może być lokalnym gniazdem w abstrakcyjnej przestrzeni nazw, portem TCP itp. - wystarczy dowolny unikalny identyfikator. Gdy znacznik jest plikiem, może to być zwykły plik zawierający identyfikator procesu (plik pid) lub nazwaną potok lub gniazdo, na którym nasłuchuje plik itp. Idealnie, znacznik jest punktem końcowym komunikacji, który umożliwia klientom połączenie do tego procesu.

Każdy z tych rodzajów tagów powoduje inny sposób sprawdzenia, czy szukana instancja jest uruchomiona. Na przykład, z lokalnym gniazdem plików, spróbuj się z nim połączyć i rozpocznij proces, jeśli proces nie nasłuchuje na tym gnieździe. Jeśli znacznik jest plikiem pid, sprawdź, czy istnieje proces o tym identyfikatorze procesu, ale uważaj, aby był on delikatny, ponieważ jeśli proces umarł, może istnieć niepowiązany proces, który ponownie użył swojego identyfikatora. Uważaj, że jeśli dwóch klientów spróbuje dotrzeć do procesu w krótkim czasie, obaj mogą stwierdzić, że proces nie istnieje i obaj próbują go uruchomić; odpowiednia ochrona przed takimi warunkami wyścigowymi może być trudna.

Łatwiej jest zarządzać instancjami, gdy wszystkie są uruchamiane przez ten sam proces superwizora, a ten proces superwizora wykrywa moment śmierci instancji i odpowiednio reaguje. Wiele programów monitorujących usługi, które mogą to zrobić.

Jeśli program nie reaguje na znany punkt końcowy komunikacji i nie jest zarządzany przez program nadzorujący, znacznikiem biednego człowieka jest plik pid: plik zawierający identyfikator procesu. Po uruchomieniu procesu zapisz pid do pliku o wcześniej ustalonej nazwie. Gdy potrzebujesz, aby proces istniał, przeczytaj plik pid i sprawdź, czy istnieje proces z tym pid. Po zabiciu procesu usuń plik pid. Najistotniejszym problemem związanym z nienadzorowanym plikiem pid jest to, że jeśli proces umrze, jego pid może zostać ponownie wykorzystany przez jakiś niezwiązany proces. Powinieneś przynajmniej sprawdzić nazwę procesu lub plik wykonywalny procesu, aby upewnić się, że rozmawiasz z właściwym procesem. Wiele wariantów Uniksa ma polecenie pgrep :pgrep SOMENAME zawiera listę procesów, których nazwa zawiera SOMENAME jako podciąg, z dodatkowymi opcjami ograniczającymi do konkretnego użytkownika, wymagającymi dokładnego dopasowania, zmieniającymi, które z kilku możliwych pojęć „nazwa procesu” jest używana itp.


1

Możesz użyć tego podejścia:

if [[ -z $(ps -C appname -opid=) ]]; then
    appname && secondapp
fi

1

Inne opcje:

  • pgrep -xq processname
    • Pasuje tylko do pierwszych 15 znaków w systemie GNU / Linux
    • Nie obejmuje przodków w systemie OS X
  • ps -eo comm= | sed 's|.*/||' | grep -xq processname
    • Pasuje tylko do pierwszych 15 znaków w systemie GNU / Linux
    • sed 's|.*/||' usuwa części dirname w OS X

W GNU / Linux ps -o commobcięte nazwy poleceń do 15 znaków i pgrepa ps -Cjedynie dopasować pierwsze 15 znaków.

ps -C (dopasuj nazwy poleceń) nie jest obsługiwane w systemie OS X.

W OS X ps -o commdrukuje bezwzględne ścieżki poleceń i ps -co commdrukuje tylko nazwy poleceń. W GNU ps -o commdrukuje tylko nazwy poleceń i -cma inne znaczenie.

Pgrep w OS X nie obejmuje procesów przodków (takich jak bash, Terminal lub uruchomione) bez -a. Pgrep GNU zawiera je domyślnie i nie obsługuje -a.

grep -xi pgrep -xnie sugeruj -F, więc użyj, -Fxjeśli nazwa procesu może zawierać znaki regularne.


-C też nie jest dostępny w moim
cygwinie

1

Przykro mi, ale wszystkie te rozwiązania nie obsługują contab, ponieważ ta sama linia poleceń pojawi się dwukrotnie w wyniku „ps”.

Oto moje:

## Test pour voir si le même script tourne déjà
## Un fichier .pid est utilisé pour stocké le numéro de process
## Si le pid est en train de tourner alors on sort.
lock_file=$0".pid"
[ -r $lock_file ] && read pid <$lock_file
if [ "$pid" -gt 1 ] && [ `ps --no-headers -p "$pid" | wc -l` -gt 0 ] ; then
    echo "WARNING : le process $pid tourne deja : $0"
    ps -edf | grep `basename $0` | grep -v grep
    echo "WARNING : Arrêt de cette instance ($$)."
    exit 7
fi
echo $$ >$lock_file

Za co jest ci przykro Co to jest contab? Masz na myśli sprawdzanie z cronpracy?
Anthon

0

Z Bash

#!/usr/bin/env bash

[[ $# -eq 0 ]] && { echo -e "Usage:\t\t $0 <Process_name>  <Command here>"; exit 1;  }

ifnotrun(){
        local p=$1
        if ! ps -C "$1" -opid=
        then
                cmd=($@)
                echo ${cmd[@]:1}
        else
                echo "Process \"$p\" Already Running.."
                exit 1
        fi

}

ifnotrun $*

Uwaga: - usuń, echojeśli wyjście wygląda OK.


0

Wyjaśnię przypadek, w którym uruchamiasz komendę w beckgreoud. „$!” zapisz PID ostatniego procesu w tle. Możesz więc użyć go do znalezienia go w tabelach procesów zgodnie z powyższymi odpowiedziami:

sleep 4 &
ps -ef | grep -w  $!  ...

Wbudowane polecenie „jobs” - spróbuj tego:

sleep 4&
J=`jobs`
while [ "$J" ]; do
        sleep 1
        jobs # This line flush the jobs' bufer.
        J=`jobs`
done

Odnośnie opcji „&&”

Zamiast && użyj polecenia czekaj. W poniższym przykładzie myproc2 nie uruchomi się, dopóki myproc1 nie zakończy się:

myproc1 &
wait
myproc2

0

Uzyskaj stan swojego procesu:

ps -lp $(pgrep <YOUR_PROCESS_NAME>) | tail -1 | awk '{print $11}'

Odniesienie:

D    uninterruptible sleep (usually IO)
R    running or runnable (on run queue)
S    interruptible sleep (waiting for an event to complete)
T    stopped, either by a job control signal or because it is being traced
W    paging (not valid since the 2.6.xx kernel)
X    dead (should never be seen)
Z    defunct ("zombie") process, terminated but not reaped by its parent

Na przykład użyłem go do warunkowego odtworzenia lub wstrzymania mojego procesu sox na sesji tmux:

/usr/local/bin/tmux if-shell -t sox "[ $(ps -lp $(pgrep sox) | tail -1 | awk '{print $11}') == 'T' ]" \
  'send -t sox "fg" Enter' \
  'send -t sox C-z'

-1

Możesz użyć go w skrypcie:

if [ `ps -ef | grep "script.sh" | grep -v grep | wc -l` -gt 1 ] ; then
echo "RUNNING...."
else
echo "NOT RUNNING..."
fi
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.