Jag har ett skript som jag vill gaffla vid en tidpunkt så att två kopior av samma skript körs.
Till exempel , Skulle jag vilja att följande bash-skript skulle existera:
echo $$ do_fork() echo $$
Om detta bash-skript verkligen fanns, skulle den förväntade utdata vara:
<ProcessA PID> <ProcessB PID> <ProcessA PID>
eller
<ProcessA PID> <ProcessA PID> <ProcessB PID>
Finns det något som jag kan lägga i stället för ”do_fork ()” för att få det här typ av utdata, eller för att få bash-skriptet att göra en C-liknande gaffel?
Svar
Ja. Forking stavas &
:
echo child & echo parent
Det som kan förvirra dig är att $$
är inte PID för skalprocessen, det är PID för original skalprocessen. Poängen med att göra det på det här sättet är att $$
är en unik identifierare för en viss instans av skalskriptet: det ändras inte under körning av skriptet och det skiljer sig från $$
i alla andra som körs samtidigt manus. Ett sätt att få skalprocessens faktiska PID är sh -c "echo $PPID"
.
Kontrollflödet i skalet är inte detsamma som C. Om i C du ”d skriv
first(); fork(); second(); third();
då är en skalekvivalent
after_fork () { second; third; } first; after_fork & after_fork
Den enkla skalformen first; child & parent
motsvarar det vanliga C-idiomet
first(); if (fork()) parent(); else child();
&
och $$
existerar och beter sig på detta sätt i varje Bourne-stil skal och i (t) csh. $PPID
existerade inte i den ursprungliga Bourne skal men är i POSIX (så det är i ask, bash, ksh, zsh, …).
Kommentarer
Svar
Ja, det heter subshells . Skalkoden inom parentes körs som en subshell (gaffel). Det första skalet väntar dock normalt på att barnet ska slutföra. Du kan göra det asynkront med &
-avslutaren. Se det i handling med något liknande:
#!/bin/bash (sleep 2; echo "subsh 1")& echo "topsh"
$ bash subsh.sh
Kommentarer
- Parenteserna skapar en subshell , men att ' s gaffel + vänta.
&
är gaffel ensam. Om du vill utföra mer än en pipeline i barnprocessen, det ' är tillräckligt för att använda hängslen (som utför gruppering utan att skapa en underprocess):{ sleep 2; echo child; } &
Svar
Det finns ingen infödd bash (eller, såvitt jag vet, något annat typiskt * nix-skal) sätt att göra detta. Det finns många sätt att leka gafflade processer som gör något annat asynkront, men jag tror inte att det finns något som följer den exakta semantiken för gaffel () systemanropet. vara att få ditt toppnivåskript att sprida hjälpare som gör precis det arbete du vill dela ut. Om du gör $0 $@ &
eller vad som helst, kommer du att börja från början igen och måste ta reda på det på något sätt.
Jag börjar faktiskt tänka på flera smarta sätt som man kan göra just det ….
Men , innan min hjärna blir alltför upptagen av det, tycker jag att en ganska bra regel är: om du försöker skriva något i skal och det blir full av smarta knep och du önskar fler språkfunktioner, tid att byta till ett riktigt programmeringsspråk .
Kommentarer
- Även om din poäng är väl fattad – bash ' s syntax är utan tvekan svårt och det ' saknar de mer eleganta datastrukturerna och funktionerna i Perl eller Python, bash är lika verkligt som det blir- i sin domän . Det är ett domänspecifikt språk, och jag skulle argumentera ännu bättre (mer kortfattad, enklare) än t.ex. Python i många fall. Kan du administrera ett stort system och inte känna till Python? Ja. Kan du göra det och inte känna till en lick of bash [programmering]? Jag skulle inte vilja '. Efter 30 år av skalprogrammering berättar jag det ' är så verkligt som det blir. Och ja, jag talar Python. Men låt inte ' förvirra ungdomarna.
- Som sagt, tekniskt gillar jag det här svaret mer. Att säga att " & " är svaret på användaren ' s fråga, " gaffel vid ett tillfälle så att två kopior av samma skript körs " är för mig sinne förvirrande. Vad " & ", enligt bash-manualen, är " … kör kommandot [given] i bakgrunden i en subshell. " Det måste avsluta ett kommando och det innebär en gaffel (tekniskt , i Linux, en klon ()), men då körs inte två kopior av samma skript.
&
är gaffel, det finns ' ingen exec involverad. Gaffel + exec är när du startar ett externt kommando.exec
, men de två språken har olika kontrollflöde.&
startar en subshell där det givna kommandot körs. Gaffel + exec. Du kan ' t bara sätta&
utan föregående kommando att utföra.&
på en rad i sig själv. Men du kan ' t. Det betyder inte ' t " gaffel här ". Det betyder att " kör föregående kommando i bakgrunden i en subshell ".