Jak ustalić, czy proces jest uruchomiony, czy nie i wykorzystać go do utworzenia skryptu powłoki warunkowej?

108

Jak mogę ustalić, czy proces jest uruchomiony, czy nie, a następnie uruchomić skrypt bash w celu wykonania pewnych czynności w oparciu o ten warunek?

Na przykład:

  • jeśli proces abcjest uruchomiony, zrób to

  • jeśli nie działa, zrób to.

Nirmik
źródło
1
Należy pamiętać, że żadne z poniższych rozwiązań nie uwzględnia stanu procesu. Komentarz do jednego z moich pytań przywiódł mnie tutaj, ale odpowiedź wpędziła mnie w różne stany programu, takie jak zombieproces ”(nie to, co nazwałbym„ działającym ”procesem). Pełna lista tego, co wskazują STATwartości kolumny na wyjściu ps, jest tutaj dla tych, którzy są skłonni do napisania odpowiedzi, która to uwzględnia, lub edycji własnych.
user66001,
Powiązana dyskusja: unix.stackexchange.com/questions/74185/…
blong
istnieje najlepszy sposób na sprawdzenie procesu: stackoverflow.com/questions/3043978/...
Trevor Boyd Smith

Odpowiedzi:

166

Skrypt bash do zrobienia czegoś takiego wyglądałby mniej więcej tak:

#!/bin/bash

# Check if gedit is running
# -x flag only match processes whose name (or command line if -f is
# specified) exactly match the pattern. 

if pgrep -x "gedit" > /dev/null
then
    echo "Running"
else
    echo "Stopped"
fi

Ten skrypt sprawdza, czy program „gedit” jest uruchomiony.

Lub możesz tylko sprawdzić, czy program nie działa w następujący sposób:

if ! pgrep -x "gedit" > /dev/null
then
    echo "Stopped"
fi
John Vrbanac
źródło
@DreadPirateShawn czy możesz mi powiedzieć, dlaczego używasz / dev / null, a nie tylko 0? Użycie liczby sprawia, że ​​kod jest znacznie bardziej czytelny, przynajmniej dla nooba (takiego jak ja). Bez przekierowań, bez niczego
Silviu
2
@Silviu huh? Googling /dev/null: „/ dev / null przekierowuje standardowe wyjście polecenia do urządzenia zerowego, które jest specjalnym urządzeniem, które odrzuca zapisane na nim informacje” ... użycie 0spowoduje przekierowanie wyjścia polecenia do pliku o nazwie 0. W takim przypadku radzę poczuć się bardziej komfortowo > /dev/null- zobaczysz to wszędzie, ponieważ jest to standardowy / właściwy sposób odrzucania danych wyjściowych.
DreadPirateShawn
Woot dzięki, użyłem tego do miłego małego skryptu, który sprawdza, czy program działa przed jego uruchomieniem. (chociaż musiałem go trochę rozszerzyć, ponieważ plik wykonywalny google chrome nie ma takiej samej nazwy jak polecenie uruchomienia, nazwa exec to po prostu chrome.)
Cestarian
3
Dodaj -xparametr, aby pgrepszukał dokładnej aplikacji, w przeciwnym razie otrzyma fałszywą poprawkę, jeśli znajdzie ten sam ciąg w nazwie innej aplikacji. Właśnie spędziłem 1 godzinę, aby się tego dowiedzieć.
Thanos Apostolou
1
Aby sprawdzić, czy program nie działa, użyj! pgrep
Mohammed Noureldin
36

Każde rozwiązanie, które wykorzystuje coś takiego ps aux | grep abclub pgrep abcjest wadliwe.

Dlaczego?

Ponieważ nie sprawdzasz, czy określony proces jest uruchomiony, sprawdzasz, czy są uruchomione procesy, które się zgadzają abc. Każdy użytkownik może łatwo utworzyć i uruchomić plik wykonywalny o nazwie abc(lub który zawiera abcgdzieś w nazwie lub argumentach), co powoduje fałszywie dodatni wynik testu. Istnieją różne opcje można zastosować do ps, grepi pgrep, aby zawęzić wyszukiwanie, ale nadal nie będzie wiarygodny test.

Jak więc w sposób niezawodny przetestować określony działający proces?

To zależy od tego, do czego potrzebujesz testu.

Chcę się upewnić, że usługa abc jest uruchomiona, a jeśli nie, uruchom ją

Po to są init i upstart. Uruchomią usługę i upewnią się, że jej pid zostanie zapisany w pliku pid. Spróbuj ponownie uruchomić usługę (przez init lub upstart), a ona sprawdzi plik pid i uruchom go, jeśli go nie ma, lub przerwij, jeśli już działa. To wciąż nie jest w 100% niezawodne, ale jest tak blisko, jak to tylko możliwe.

Zobacz Jak mogę sprawdzić, czy mój serwer gier nadal działa ... w przypadku innych rozwiązań.

abc to mój skrypt. Muszę się upewnić, że działa tylko jedna instancja mojego skryptu.

W takim przypadku użyj pliku blokady lub lockdir. Na przykład

#!/usr/bin/env bash

if ! mkdir /tmp/abc.lock; then
    printf "Failed to acquire lock.\n" >&2
    exit 1
fi
trap 'rm -rf /tmp/abc.lock' EXIT  # remove the lockdir on exit

# rest of script ...

Zobacz Bash FAQ 45, aby uzyskać informacje na temat innych sposobów blokowania.

geirha
źródło
3
Chociaż jest to technicznie prawdą, osobiście nie spotkałem takiego problemu w prawdziwym życiu. Większość programów nie zmienia swoich nazw w sposób, który łamie skrypty. W przypadku prostych skryptów coś podobnego pgreplub pscałkowicie wystarczającego, a twoje podejście wydaje się przesadne. Jeśli piszesz skrypt do publicznej dystrybucji, powinieneś napisać go w najbezpieczniejszy możliwy sposób.
Scott Severance
2
@ScottSeverance Programy zmieniające nazwy nie stanowią problemu; niezależnie od tego wymagałoby to interwencji. To inni użytkownicy uruchamiający ten sam program lub inne programy o podobnych nazwach, które nagle spowodują, że skrypt uzyska fałszywe alarmy, a tym samym zrobią coś złego. Po prostu wolę „działa” niż „głównie działa”.
geirha
2
Źle powiedziałem. Ale wielu z nas prowadzi systemy dla jednego użytkownika. W sytuacji wielu użytkowników łatwo jest również grep dla nazwy użytkownika.
Scott Severance
1
co się stanie, jeśli skrypt nie zadziała w czasie wykonywania i zginie przed odblokowaniem pliku?
jp093121,
2
@ jp093121 Pułapka EXIT jest wyzwalana, gdy skrypt kończy działanie. Bez względu na to, czy kończy pracę, ponieważ osiąga koniec skryptu, polecenie wyjścia lub odbiera sygnał (który można obsłużyć), rmpolecenie jest uruchamiane. Tak długo, jak kończy się po ustawieniu pułapki, zamek powinien zniknąć.
geirha
18

Oto, czego używam:

#!/bin/bash

#check if abc is running
if pgrep abc >/dev/null 2>&1
  then
     # abc is running
  else
     # abc is not running
fi

W prostym języku angielskim: jeśli „pgrep” zwraca 0, proces jest uruchomiony, w przeciwnym razie nie.


Powiązana lektura:

Skrypty Bash :: Porównania ciągów

Instrukcje Ubuntu pgrep

Zuul
źródło
dzięki! też próbowałem tego i to też działa idealnie :)
Nirmik
pgrepma tę samą „cechę” limitu 15 znaków, o której wspominano wcześniej, dlatego też na przykład pgrep gnome-power-managerrównież by się nie powiodła
Thorsen
1
Upewnij się, że używasz -xopcji pgrep : „ Dopasowuj tylko procesy, których nazwa (lub wiersz poleceń, jeśli podano -f) jest dokładnie zgodny ze wzorcem”.
Alastair Irvine
5

Zwykle mam pidof -x $(basename $0)na swoich skryptach, aby sprawdzić, czy już działa.

Rommel Cid
źródło
2

Riffując pomysł @ rommel-cid, możesz użyć pidofz || (||), aby uruchomić polecenie, jeśli proces nie istnieje, i &&, aby uruchomić coś, jeśli proces istnieje, tworząc w ten sposób szybką warunek if / then / else. Na przykład tutaj jest jeden z uruchomionym procesem (moja przeglądarka chrome, którego nazwa procesu to „chrome”) i jeden testujący proces, który nie istnieje. Pominąłem standardowe wyjście, używając 1> / dev / null, aby nie drukowało:

$ (pidof chrome 1>/dev/null && echo "its running? ok, so am i then" ) || echo "it's not running? ok i'll run instea\
d"
its running? ok, so am i then
$ (pidof nosuchprocess 1>/dev/null && echo "its running? ok, so am i then" ) || echo "it's not running? ok i'll run\
 instead"
it's not running? ok i'll run instead
$
yuvilio
źródło
1

Żadne z „prostych” rozwiązań nie działało dla mnie, ponieważ plik binarny, który muszę sprawdzić, nie jest zainstalowany w całym systemie, więc muszę sprawdzić ścieżkę, która z kolei wymaga zastosowania ps -ef | greppodejścia:

app="$_sdir/Logic 1.2.18 (64-bit)/Logic"

app_pid=`ps -ef | grep "$app" | awk '{print $2}'`

if `ps -p $app_pid > /dev/null`; then
    echo "An instance of logic analyzer is appear to be running."
    echo "Not starting another instance."
    exit 5
else
    nohup "$app" &> /dev/null &
fi
ceremcem
źródło
0

Pierwsza rzecz, jaka przyszła mi do głowy dla twojego problemu:
ps aux | grep -i abcpokaże szczegóły procesu, jeśli jest on uruchomiony. Możesz dopasować liczbę linii lub czas, przez który jest uruchomiony, i porównać z zerem lub inną manipulacją. Po uruchomieniu powyższego polecenia wyświetli się co najmniej jeden wiersz danych wyjściowych, tj. Szczegóły dotyczące procesu utworzonego za pomocą tego polecenia grep. Zajmij się tym.
To powinno wystarczyć jako zwykły hack. Umieść go w skrypcie bash i sprawdź, czy jest pomocny.

drake01
źródło
0

Używanie start-stop-daemon:

/sbin/start-stop-daemon --background --make-pidfile --pidfile /tmp/foo.pid -S --startas /usr/bin/program -- arg1 arg2

Działa jak zwykły użytkownik.

Martin Monperrus
źródło
0

Odkryłem, że zaakceptowana odpowiedź wysłana przez @Johna Vrbanaca nie działała dla mnie i że odpowiedź wysłana przez @geirha nie odpowiada na pierwotne pytanie.

Rozwiązanie Johna Vrbanaca nie działało, aby sprawdzić, czy proces PHP jest uruchomiony, czy nie dla mnie, używam CentOS 7.

Odpowiedź @ geirha tylko upewnia się, że instancja nie jest jeszcze uruchomiona przed uruchomieniem kolejnej. To nie było oryginalne pytanie, pierwotne pytanie polegało na sprawdzeniu, czy proces jest uruchomiony, czy nie.

Oto, co zadziałało dla mnie:

Powiedzmy, że mój proces miał ciąg „Jane” w nazwie procesu. Przekona się, czy jest uruchomiony, czy nie. Działa to dla skryptów BASH i PHP.

ps -aux | grep "[J]ane" > /dev/null 2>&1
if [[ "$?" == "0" ]]; then
    echo "It's running"
else
    echo "It's not running"
fi
Wayne Workman
źródło
1
Ach, ponieważ jest to strona z pytaniami i odpowiedziami na temat Ubuntu, nic dziwnego, że niektóre odpowiedzi tutaj nie działają na CentOS 7, ponieważ Linux jest tutaj nie na temat. Inne wersje systemu Linux są obsługiwane na stronie unix.stackexchange.com
Elder Geek,
chociaż autor odpowiedzi używa CentOS, ta odpowiedź jest nadal ważna dla Ubuntu.
Phillip -Zyan K Lee- Stockmann
0
## bash

## function to check if a process is alive and running:

_isRunning() {
    ps -o comm= -C "$1" 2>/dev/null | grep -x "$1" >/dev/null 2>&1
}

## example 1: checking if "gedit" is running

if _isRunning gedit; then
    echo "gedit is running"
else
    echo "gedit is not running"
fi

## example 2: start lxpanel if it is not there

if ! _isRunning lxpanel; then
    lxpanel &
fi

## or

_isRunning lxpanel || (lxpanel &)

Uwaga : pgrep -x lxpanellub pidof lxpanelnadal zgłasza, że lxpaneldziała, nawet gdy jest nieczynny (zombie); więc aby uzyskać żywy proces, musimy użyć psigrep

Bach Lien
źródło
-1

Według stanu na 23 września 2016 r. Pgrep wymaga opcji „-x”, aby skrypt Muru działał.

#!/bin/bash

if pgrep -x "conky" > /dev/null 2>&1
then
  echo "conky running already"
else
  echo "now starting conky"
  conky
fi
exit 0

Próbowałem i przetestowałem powyższy skrypt na komputerze Ubuntu 16.04.1. Cieszyć się!

dzmanto
źródło
-1
#!/bin/bash
while [ true ]; do     # Endless loop.
  pid=`pgrep -x ${1}`  # Get a pid.
  if [ -z $pid ]; then # If there is none,
    ${1} &             # Start Param to background.
  else
    sleep 60           # Else wait.
  fi
done
użytkownik7449824
źródło
1
Witamy w Ask Ubuntu! Zalecam edycję tej odpowiedzi, aby rozszerzyć ją o szczegółowe informacje na temat jej działania. (Zobacz także Jak napisać dobrą odpowiedź? Zawiera ogólne porady na temat tego, jakie rodzaje odpowiedzi są uważane za najcenniejsze na AskUbuntu.)
David Foerster
-3

isProcessRunning () {if [$ (pidof $ 1)> / dev / null]; następnie retval = 'true'; else retval = „false”; fi; echo $ retval; }

isProcessRunning geany

prawdziwe

Dominik
źródło