Tenho um script que gostaria de bifurcar em um ponto para que duas cópias do mesmo script estejam em execução.
Por exemplo , Gostaria que o seguinte script bash existisse:
echo $$ do_fork() echo $$
Se este script bash realmente existisse, a saída esperada seria:
<ProcessA PID> <ProcessB PID> <ProcessA PID>
ou
<ProcessA PID> <ProcessA PID> <ProcessB PID>
Há algo que eu possa colocar no lugar de “do_fork ()” para conseguir isso tipo de saída ou para fazer com que o script bash faça um fork do tipo C?
Resposta
Sim. A bifurcação é escrita &
:
echo child & echo parent
O que pode estar confundindo você é que $$
não é o PID do processo shell, é o PID do processo shell original . O objetivo de torná-lo dessa forma é que $$
é um identificador único para uma instância particular do script de shell: ele não muda durante a execução do script e é diferente de $$
em qualquer outra execução simultânea roteiro. Uma maneira de obter o PID real do processo shell é sh -c "echo $PPID"
.
O fluxo de controle no shell não é o mesmo que C. Se em C você “d write
first(); fork(); second(); third();
então um shell equivalente é
after_fork () { second; third; } first; after_fork & after_fork
A forma simples de shell first; child & parent
corresponde ao idioma C usual
first(); if (fork()) parent(); else child();
&
e $$
existem e se comportam dessa forma em cada shell de estilo Bourne e em (t) csh. $PPID
não “existia no Bourne original shell, mas está em POSIX (ou seja, “está em ash, bash, ksh, zsh, …).
Comentários
- Mas isso ' s basicamente " fork + exec ", não apenas fork.
- @mattdm: Uh?
&
é fork, há ' nenhum exec envolvido. Fork + exec é quando você inicia um comando externo. - @mattdm: Ah, acho que vejo o que Cory está chegando. Há ' s não
exec
, mas os dois idiomas têm fluxo de controle diferente. - @Gilles: O bash operador de controle
&
inicia um subshell no qual o comando fornecido é executado. Fork + exec. Você pode ' t apenas colocar&
sem nenhum comando anterior para executar. - Bem, se " Bifurcação é escrita & " fosse uma afirmação verdadeira, você poderia colocar
&
em uma linha por si só. Mas você pode ' t. Não ' significa " bifurcação aqui ". Significa " executar o comando anterior em segundo plano em um subshell ".
Resposta
Sim, é chamado de subshells . O código do shell entre parênteses é executado como um subshell (fork). No entanto, o primeiro shell normalmente espera que o filho seja concluído. Você pode torná-lo assíncrono usando o terminador &
. Veja-o em ação com algo assim:
#!/bin/bash (sleep 2; echo "subsh 1")& echo "topsh"
$ bash subsh.sh
Comentários
Resposta
Não há nativos bash (ou, que eu saiba, qualquer outro * shell nix típico) maneira de fazer isso. Existem muitas maneiras de gerar processos bifurcados que fazem outra coisa de forma assíncrona, mas não acho que haja nada que siga a semântica exata da chamada de sistema fork ().
A abordagem típica seria será para que seu script de nível superior crie ajudantes que façam exatamente o trabalho que você deseja dividir. Se você fizer $0 $@ &
ou qualquer outra coisa, você “começará do início novamente e precisará descobrir isso de alguma forma.
Na verdade, estou começando a pensar em várias maneiras inteligentes de fazer exatamente isso …
Mas , antes que meu cérebro se empolgue muito com isso, acho que uma regra muito boa é: se você está tentando escrever algo em shell e está ficando cheio de truques inteligentes e você deseja mais recursos de linguagem, é hora de mudar para uma linguagem de programação real .
Comentários
- Embora seu ponto seja bem entendido – bash ' a sintaxe é indiscutivelmente difícil e ' Estando faltando as estruturas de dados e recursos mais elegantes do Perl ou Python, o bash é tão real quanto possível- em seu domínio . É uma linguagem de domínio específico, e eu diria ainda melhor (mais sucinta, mais simples) do que, por exemplo, Python em muitos casos. Você consegue administrar uma sala cheia de sistemas e não conhece o Python? sim. Você pode fazer isso e não saber uma pitada de bash [programação]? Eu não ' não gostaria de tentar. Depois de 30 anos de programação em shell, digo que ' é o mais real possível. E sim, eu falo Python. Mas não ' não confunda os jovens.
- Dito isso, tecnicamente gosto mais desta resposta. Dizer que " & " é a resposta para o usuário ' s questão, " bifurca em um ponto para que duas cópias do mesmo script estejam sendo executadas " é para meu mente confusa. O que " & " faz, de acordo com o manual do bash, é " … executa o comando [dado] em segundo plano em um subshell. " Ele deve terminar um comando e envolve um fork (tecnicamente , no Linux, um clone ()), mas nesse ponto duas cópias do mesmo script não estão em execução.
&
é fork sozinho. Se você deseja executar mais de um pipeline no processo filho, é ' o suficiente para usar colchetes (que executam o agrupamento sem criar um processo filho):{ sleep 2; echo child; } &