Řešení 1:
Co může být jednodušší než echo $!
? Jako jeden řádek:
myCommand & echo $!
Řešení 2:
Můžete použít sh -c
a exec
získat PID příkazu ještě před běží.
Chcete-li spustit myCommand
, takže jeho PID bude vytištěno před spuštěním, můžete použít:
sh -c 'echo $$; exec myCommand'
Jak to funguje:
Tím se spustí nový shell, vypíše se PID tohoto shellu a pak se použije exec
vestavěný k nahrazení shell s vaším příkazem a ujistěte se, že má stejné PID. Když váš shell spustí příkaz s exec
vestavěný, váš shell se ve skutečnosti stává tento příkaz, spíše než běžnější chování při vytváření nové kopie sebe sama, která má své vlastní samostatné PID a která se pak stává příkazem.
Považuji to za mnohem jednodušší než alternativy zahrnující asynchronní provádění (s &
), ovládání úlohy nebo vyhledávání pomocí ps
. Tyto přístupy jsou v pořádku, ale pokud nemáte konkrétní důvod je použít – například, možná, že příkaz již běží, v takovém případě by hledání jeho PID nebo použití řízení úlohy dávalo smysl – navrhuji nejprve zvážit tento způsob. (A určitě bych neuvažoval o psaní složitého skriptu nebo jiného programu, abych toho dosáhl).
Tato odpověď obsahuje příklad této techniky.
Části tohoto příkazu mohou být občas vynechány, ale ne obvykle.
I když shell, který používáte, je Bourneův styl, a proto podporuje exec
Díky této sémantice byste se obecně neměli snažit vyhýbat použití sh -c
(nebo ekvivalentní) k vytvoření nového, samostatného shell pro tento účel, protože:
- Jakmile se shell stane
myCommand
, žádný shell nečeká na spuštění následujících příkazů.sh -c 'echo $$; exec myCommand; foo
by se nemohl pokusit spustitfoo
poté, co sám sebe nahradímyCommand
. Pokud nepíšete skript, který toto spouští jako poslední příkaz, nemůžete jednoduše použítecho $$; exec myCommand
v shellu, kde spouštíte další příkazy. - Nemůžete k tomu použít subshell.
(echo $$; exec myCommand)
může být syntakticky hezčí nežsh -c 'echo $$; exec myCommand'
, ale když spustíte$$
uvnitř(
)
, udává PID nadřazeného shellu, nikoli samotného podshellu. Ale je to PID podshell, který bude PID nového příkazu. Některé shelly poskytují své vlastní nepřenosné mechanismy pro nalezení PID podshell, které byste mohli použít k tomu. Konkrétně v Bash 4,(echo $BASHPID; exec myCommand)
funguje.
Nakonec si všimněte, že některé shelly provedou optimalizaci, kde spustí příkaz jakoby pomocí exec
(tj. nejprve se vzdají rozvětvení), když je známo, že skořápka nebude muset poté nic dělat. Některé shelly se o to pokoušejí, kdykoli je to poslední příkaz, který se má spustit, zatímco jiné to udělají pouze tehdy, když před nebo za příkazem nejsou žádné další příkazy, a jiné to neudělají vůbec. Výsledkem je, že pokud zapomenete napsat exec
a stačí použít sh -c 'echo $$; myCommand'
pak to bude někdy u některých vám poskytne správné PID systémy s některými skořápky. Nedoporučuji nikdy spoléhat na takové chování a místo toho vždy zahrnout exec
když to potřebujete.
Řešení 3:
Zabalte příkaz do malého skriptu
#!/bin/bash
yourcommand &
echo $! >/path/to/pid.file
Řešení 4:
Neznám žádné jednodušší řešení, ale nepoužívám $! dostatečně dobrý? Hodnotu můžete vždy přiřadit nějaké jiné proměnné, pokud ji později budete potřebovat, jak řekli ostatní.
Jako vedlejší poznámku, místo potrubí z ps můžete použít pgrep
nebo pidof
.
Řešení 5:
použijte exec ze skriptu bash po registraci pid do souboru:
příklad:
předpokládejme, že máte skript s názvem „forever.sh“, který chcete spustit s args p1,p2,p3
zdrojový kód forever.sh:
#!/bin/sh
while [ 1 -lt 2 ] ; do
logger "$0 running with parameters \"[email protected]\""
sleep 5
done
vytvořit reaper.sh:
#!/bin/sh
echo $$ > /var/run/$1.pid
exec "[email protected]"
spustit forever.sh přes reaper.sh:
./reaper.sh ./forever.sh p1 p2 p3 p4 &
forever.sh nedělá nic jiného, než že každých 5 sekund zaznamená řádek do syslog
nyní máte pid v /var/run/forever.sh.pid
cat /var/run/forever.sh.pid
5780
a forever.sh běží dobře. syslog grep:
Nov 24 16:07:17 pinkpony cia: ./forever.sh running with parameters "p1 p2 p3 p4"
můžete to vidět v tabulce procesů:
ps axuwww|grep 'forever.sh p1' |grep -v grep
root 5780 0.0 0.0 4148 624 pts/7 S 16:07 0:00 /bin/sh ./forever.sh p1 p2 p3 p4