Vraag Hoe te bepalen of een proces draait of niet en gebruik het om een ​​conditioneel shellscript te maken?


Hoe kan ik bepalen of een proces wordt uitgevoerd of niet en vervolgens een bash-script uitvoeren sommige dingen op basis van die voorwaarde?

Bijvoorbeeld:

  • als proces abc draait, doe dit

  • als dat niet lukt, doe dat dan.


83
2018-06-29 21:53


oorsprong


Voel het belangrijk om op te merken dat geen van de onderstaande oplossingen rekening houden met de status van het proces. Een opmerking over een van mijn vragen bracht me hier, maar een antwoord erop hingen me in verschillende toestanden van een programma, zoals zombie proces '(niet wat ik zou omschrijven als een "lopend" proces). Een volledige lijst van wat de STAT kolomwaarden, in de uitvoer van ps, geeft aan is hier voor diegenen die geneigd zijn om een ​​antwoord te schrijven dat dit onderbrengt, of hun eigen antwoord te bewerken. - user66001
Gerelateerde discussie: unix.stackexchange.com/questions/74185/... - blong
beste manier om te controleren of het proces bestaat: stackoverflow.com/questions/3043978/... - Trevor Boyd Smith


antwoorden:


Een bash-script om zoiets te doen zou er ongeveer zo uitzien:

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

Dit script controleert of het programma "gedit" actief is.

Of u kunt alleen controleren of het programma niet als volgt werkt:

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

138
2018-06-29 22:08



@DreadPirateShawn kun je me vertellen waarom / dev / null gebruiken en niet gewoon een 0? Het gebruik van het nummer maakt de code veel leesbaarder, althans voor een noob (zoals ik). Geen omleiding, niets - Silviu
@Silviu hè? googlen /dev/null: "/ dev / null leidt de standaarduitvoer van het commando om naar het null-apparaat, wat een speciaal apparaat is dat de informatie weggooit die erin is geschreven" ... met behulp van 0 zou de uitvoer van de opdracht omleiden naar een bestand met de naam 0. In dit geval zou ik adviseren om meer vertrouwd te raken met > /dev/null - je ziet het overal, want het is de standaard / juiste manier om output weg te gooien. - DreadPirateShawn
Woot bedankt, ik heb dit gebruikt voor een leuk klein script dat controleert of een programma draait voordat het wordt uitgevoerd. (hoewel ik het een beetje moest uitbreiden omdat het uitvoerbare bestand van google chrome niet dezelfde naam heeft als de opdracht 'uitvoeren', is de naam exec alleen maar chrome.) - Cestarian
Voeg alstublieft de -x parameter naar pgrep zodat het op zoek is naar de exacte toepassing of anders zal het een vals correct krijgen als het dezelfde reeks vindt binnen de naam van een andere app. Ik heb net 1 uur besteed om dat uit te vinden. - Thanos Apostolou
Gebruik om te controleren of het programma niet actief is ! pgrep - Mohammed Noureldin


Elke oplossing die zoiets gebruikt ps aux | grep abc of pgrep abc zijn gebrekkig.

Waarom?

Omdat u niet controleert of een specifiek proces wordt uitgevoerd, controleert u of er processen worden uitgevoerd die toevallig overeenkomen abc. Elke gebruiker kan eenvoudig een uitvoerbaar benoemde maken en uitvoeren abc (of dat bevat abc ergens in zijn naam of argumenten), wat een vals positief voor uw test veroorzaakt. Er zijn verschillende opties die u kunt toepassen ps, grep en pgrep om de zoekopdracht te verfijnen, maar u krijgt nog steeds geen betrouwbare test.

Dus hoe kan ik betrouwbaar testen op een bepaald lopend proces?

Dat hangt er vanaf waar je de test voor nodig hebt.

Ik wil die service garanderen abc draait, en zo niet, start het dan

Dit is waar init en upstart voor zijn. Ze starten de service en zorgen ervoor dat de pid wordt opgeslagen in een pid-bestand. Probeer de service opnieuw te starten (via init of upstart) en het pid-bestand wordt gecontroleerd en het bestand wordt gestart als het er niet is of wordt afgebroken als het al actief is. Dit is nog steeds niet 100% betrouwbaar, maar het is zo dichtbij als je krijgt.

Zien Hoe kan ik controleren of mijn gameserver nog actief is ... voor andere oplossingen.

abc is mijn script. Ik moet ervoor zorgen dat slechts één exemplaar van mijn script wordt uitgevoerd.

Gebruik in dit geval een slotfile of een lockdir. Bijv.

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

Zien Bash FAQ 45 voor andere manieren van vergrendelen.


32
2018-06-30 07:29



Hoewel dit technisch waar is, heb ik persoonlijk nog nooit zo'n probleem in het echt ontmoet. De meeste programma's veranderen hun naam niet op manieren die scripts verbreken. Dus voor eenvoudige scripts zoiets als pgrep of ps is perfect passend en je aanpak lijkt overdreven. Als u echter een scrip voor openbare verspreiding schrijft, moet u dit op de veiligst mogelijke manier schrijven. - Scott Severance
@ScottSeverance Programma's namen veranderen is niet het probleem; dat zou ongeacht interventie vereisen. Het zijn andere gebruikers die hetzelfde programma gebruiken, of andere programma's met vergelijkbare namen die er plotseling voor zorgen dat het script valse positieven krijgt en dus het verkeerde doet. Ik geef de voorkeur aan 'werken' in plaats van 'meestal werkt'. - geirha
Ik heb een fout gemaakt. Maar velen van ons hebben systemen voor één gebruiker. En in een situatie met meerdere gebruikers is het eenvoudig om ook te grep voor de gebruikersnaam. - Scott Severance
wat als je script tijdens runtime faalt en sterft voordat het bestand wordt ontgrendeld? - jp093121
@ jp093121 De EXIT-trap wordt geactiveerd wanneer het script wordt afgesloten. Of het nu wordt afgesloten omdat het einde van het script bereikt, een exit-opdracht of een signaal ontvangt (dat kan worden afgehandeld), de rm commando wordt uitgevoerd. Dus zolang het eindigt nadat de val is gezet, zou het slot weg moeten zijn. - geirha


Dit is wat ik gebruik:

#!/bin/bash

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

In gewoon Engels: als 'pgrep' 0 retourneert, is het proces actief, anders is dit niet het geval.


Gerelateerde lezen:

Bash Scripting :: String vergelijkingen

Ubuntu-handleidingen pgrep


17
2018-06-29 22:15



thanx! ik heb dit ook geprobeerd n het werkt ook perfect :) - Nirmik
pgrep heeft dezelfde eerder genoemde "limiet" van 15 karakters, dus bijvoorbeeld pgrep gnome-power-manager zou ook falen - Thorsen
Zorg ervoor dat u pgrep's gebruikt -x optie: "Pas alleen processen toe waarvan de naam (of opdrachtregel als -f is opgegeven) exact overeenkomt met het patroon." - Alastair Irvine


Ik heb meestal een pidof -x $(basename $0) op mijn scripts om te controleren of deze al actief is.


5
2018-01-14 09:42





Riffing op het idee van @ rommel-cid, dat je kunt gebruiken pidof met de || (||) om een ​​opdracht uit te voeren als het proces niet bestaat en && om iets uit te voeren als het proces bestaat, waardoor een snelle if / then / else-voorwaarde wordt gecreëerd. Bijvoorbeeld hier is er een met een draaiend proces (mijn Chrome-browser, waarvan de procesnaam "chrome" is) en een test voor een proces dat niet bestaat. Ik heb de standaarduitvoer onderdrukt met 1> / dev / null zodat deze niet wordt afgedrukt:

$ (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
$

1
2018-03-01 23:08





Het eerste dat bij me opkwam voor je probleem:
ps aux | grep -i abc toont de details van het proces als het draait. U kunt het aantal regels of tijd waarvoor het loopt vergelijken en vergelijken met nul of een andere manipulatie. Wanneer je de bovenstaande opdracht uitvoert, zal het je ten minste één regel van de uitvoer tonen, d.w.z. details over het proces dat is gemaakt door de grep-opdracht. Dus zorg daarvoor.
Dat zou moeten doen als een simpele hack. Zet het in het bash-script en kijk of het nuttig is.


0
2018-06-29 22:03





Gebruik makend van start-stop-daemon:

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

Het werkt als een normale gebruiker.


0
2018-06-19 17:55





Ik vond dat het geaccepteerde antwoord van @John Vrbanac niet werkte voor mij, en dat het antwoord van @geirha de oorspronkelijke vraag niet beantwoordt.

De oplossing van John Vrbanac werkte niet om te controleren of een PHP-proces draaide of niet voor mij, ik gebruik CentOS 7.

Het antwoord van @ geirha zorgt er alleen voor dat een instantie nog niet wordt uitgevoerd voordat een andere wordt gestart. Dit was niet de oorspronkelijke vraag, de oorspronkelijke vraag was om te controleren of een proces draait of niet.

Dit is wat voor mij werkte:

Stel dat mijn proces de string "Jane" in de procesnaam had. Dit zal vinden of het draait of niet. Dit werkt voor BASH- en PHP-scripts.

ps -aux | grep "[J]ane" > /dev/null 2>&1
if [[ "$?" == "0" ]]; then
    echo "It's running"
else
    echo "It's not running"
fi

0
2017-11-11 19:12



Ah, ook al is dit een Ubuntu Q & A-site, het is niet verrassend dat sommige van de antwoorden hier niet op CentOS 7 werken, omdat Linux hier van het onderwerp is. Andere versies van Linux worden ondersteund op unix.stackexchange.com - Elder Geek
hoewel de auteur van het antwoord CentOS gebruikt, is dit antwoord nog steeds geldig voor ubuntu. - Phillip -Zyan K Lee- Stockmann