Jeg har et skript som jeg ønsker å forkaste på et tidspunkt, slik at to kopier av samme skript kjører.
For eksempel , Vil jeg at følgende bash-skript eksisterer:
echo $$ do_fork() echo $$
Hvis dette bash-skriptet virkelig eksisterte, ville forventet utdata være:
<ProcessA PID> <ProcessB PID> <ProcessA PID>
eller
<ProcessA PID> <ProcessA PID> <ProcessB PID>
Er det noe jeg kan sette i stedet for «do_fork ()» for å få dette slags output, eller for å få bash-skriptet til å gjøre en C-lignende gaffel?
Svar
Ja. Forking er stavet &
:
echo child & echo parent
Det som kan forvirre deg er at $$
er ikke PID for skallprosessen, det er PID for original skallprosessen. Poenget med å gjøre det på denne måten er at $$
er en unik identifikator for en bestemt forekomst av skallskriptet: det endres ikke under skriptets utførelse, og det er forskjellig fra $$
i alle andre som kjører samtidig manus. En måte å få skallprosessen til faktisk PID er sh -c "echo $PPID"
.
Kontrollflyten i skallet er ikke den samme som C. Hvis du er i C «d skriv
first(); fork(); second(); third();
så er et skallekvivalent
after_fork () { second; third; } first; after_fork & after_fork
Den enkle skallformen first; child & parent
tilsvarer det vanlige C-idiomet
first(); if (fork()) parent(); else child();
&
$$
eksisterer og oppfører seg på denne måten i alle Bourne-stil skall og i (t) csh. $PPID
eksisterte ikke i den opprinnelige Bourne skall, men er i POSIX (så det er i aske, bash, ksh, zsh, …).
Kommentarer
Svar
Ja, det heter subshells . Skallkode i parentes kjøres som en subshell (fork). Men det første skallet venter normalt på at barnet skal fullføres. Du kan gjøre det asynkront ved å bruke &
terminatoren. Se den i aksjon med noe sånt som dette:
#!/bin/bash (sleep 2; echo "subsh 1")& echo "topsh"
$ bash subsh.sh
Kommentarer
- Parentesene oppretter en subshell , men at ' s gaffel + vent.
&
er gaffel alene. Hvis du vil utføre mer enn en rørledning i barneprosessen, det ' er nok til å bruke seler (som utfører gruppering uten å lage en underordnet prosess):{ sleep 2; echo child; } &
Svar
Det er ingen innfødte bash (eller, så vidt jeg vet, noen annen typisk * nix shell) måte å gjøre dette på. Det er mange måter å gyte prosesser som gjør noe annet asynkront, men jeg tror ikke det er noe som følger den eksakte semantikken til fork () systemanropet.
Den typiske tilnærmingen vil være å la skriptet på toppnivå gyte av hjelpere som gjør akkurat det arbeidet du vil dele ut. Hvis du gjør $0 $@ &
eller hva som helst, begynner du på begynnelsen igjen og trenger å finne ut av det på en eller annen måte.
Jeg begynner faktisk å tenke på flere smarte måter man kan gjøre nettopp det ….
Men , før hjernen min blir for båret av det, tror jeg en ganske god regel er: hvis du prøver å skrive noe med skall og det blir full av smarte triks, og du ønsker flere språkfunksjoner, tid til å bytte til et ekte programmeringsspråk .
Kommentarer
- Selv om poenget ditt er godt tatt – bash ' s syntaks er uten tvil vanskelig og det ' mangler de mer elegante datastrukturene og funksjonene til Perl eller Python, bash er så ekte som det blir – i sitt domene . Det er et domenespesifikt språk, og jeg vil argumentere enda bedre (mer kortfattet, enklere) enn for eksempel Python i mange tilfeller. Kan du administrere et romslig system og ikke kjenne Python? Ja. Kan du gjøre det og ikke vite en slikk av bash [programmering]? Jeg ville ikke ' ikke prøve. Etter 30 år med skallprogrammering forteller jeg deg at det ' er så ekte som det blir. Og ja, jeg snakker Python. Men ikke forvirre ungdommene.
- Når det er sagt, teknisk sett liker jeg dette svaret mer. Å si at " & " er svaret til brukeren ' s spørsmål, " gaffel på et tidspunkt, så to kopier av samme skript kjører " er for meg tankene forvirrende. Hva " & ", ifølge bash-manualen, er " … utfører kommandoen [gitt] i bakgrunnen i en subshell. " Den må avslutte en kommando, og den innebærer en gaffel (teknisk , i Linux, en klon ()), men på det tidspunktet kjører ikke to kopier av samme skript.
&
er gaffel, det er ' ingen leder involvert. Gaffel + exec er når du starter en ekstern kommando.exec
, men de to språkene har forskjellig kontrollflyt.&
starter et subshell der den gitte kommandoen utføres. Gaffel + exec. Du kan ' t bare sette&
uten forutgående kommando å utføre.&
på en linje for seg selv. Men du kan ' t. Det betyr ikke ' t " gaffel her ". Det betyr at " utfører den forrige kommandoen i bakgrunnen i et subshell ".